Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions DRAFT_PR_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Draft: Country Address Formatting API

## Summary

This PR introduces a new TypeScript module in the `lang/typescript` package that provides a public API for fetching country-specific address formatting details.

## What's New

### API Functions

- `getCountryFormatting(countryCode, locale)` - Fetch complete formatting details for a country/locale
- `hasCountryFormatting(countryCode, locale)` - Check if formatting data exists
- `getAvailableLocales(countryCode)` - Get available locales for a country

### Type Definitions

- `CountryFormatting` - Complete country formatting object
- `AddressFormat` - Edit and show templates
- `AddressFormatExtended` - Extended formatting with separators
- `AdditionalAddressFields` - Required field flags per country
- `Zone` - Political subdivisions (states/provinces)
- `AddressLabels` - Localized field labels

### Features

1. **Dynamic Imports**: Loads country/locale data on-demand via dynamic imports for optimal bundle size
2. **Type Safety**: Full TypeScript type definitions for all data structures
3. **Localization**: Supports multiple locales per country (e.g., CA has en/fr, BR has pt-br/en)
4. **Comprehensive Data**: Includes formatting templates, zones, labels, postal code patterns
5. **Pure Static**: No internal Shopify systems mentioned - ready for open-source

## Data Organization

```
lang/typescript/src/
├── country-formatting.ts (105 lines - main API)
├── country-formatting.md (240 lines - documentation)
├── country-formatting.example.ts (94 lines - usage examples)
├── types/
│ └── country-formatting.ts (268 lines - type definitions)
└── data/
├── CA/
│ ├── en.json (Canadian English formatting)
│ └── fr.json (Canadian French formatting)
└── BR/
├── en.json (Brazilian English formatting)
└── pt-br.json (Brazilian Portuguese formatting)
```

## Example Usage

```typescript
import {getCountryFormatting} from '@shopify/worldwide';

// Get Canadian address formatting in English
const ca = await getCountryFormatting('CA', 'en');

console.log(ca.format.edit);
// "{country}_{firstName}{lastName}_{company}_{address1}_{address2}_{city}{province}{zip}_{phone}"

console.log(ca.labels.province); // "Province"
console.log(ca.zones.find(z => z.code === 'ON').name); // "Ontario"
```

## Country Differences Demonstrated

The stub data shows key differences between countries:

**Canada (CA)**:
- Uses `address1` and `address2` fields
- Requires province, city, and postal code
- Standard North American format

**Brazil (BR)**:
- Uses split street fields: `streetName` + `streetNumber`
- Requires `neighborhood` field
- Uses `line2` for complement
- Different display format with dashes and state abbreviation

## Files Changed

- `lang/typescript/src/index.ts` - Exports new API
- `lang/typescript/src/country-formatting.ts` - Main API module
- `lang/typescript/src/country-formatting.md` - Documentation
- `lang/typescript/src/country-formatting.example.ts` - Usage examples
- `lang/typescript/src/types/country-formatting.ts` - Type definitions
- `lang/typescript/src/data/CA/en.json` - Canadian English data
- `lang/typescript/src/data/CA/fr.json` - Canadian French data
- `lang/typescript/src/data/BR/en.json` - Brazilian English data
- `lang/typescript/src/data/BR/pt-br.json` - Brazilian Portuguese data

## Next Steps

1. Generate full data set from YAML sources (currently only CA and BR as stubs)
2. Add build step to convert YAML → JSON chunks
3. Add validation utilities using `zip_regex` patterns
4. Add formatting utilities that apply the templates
5. Add zone lookup utilities (e.g., find zone by postal code)
6. Write unit tests
7. Update main package README

## Notes

- No internal Shopify details leaked
- Pure static data API
- Designed for code splitting via dynamic imports
- Ready for npm package publication
94 changes: 94 additions & 0 deletions lang/typescript/src/country-formatting.example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Example usage of the Country Formatting API
*

Check failure on line 3 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Delete `·`
* This file demonstrates how to use the getCountryFormatting API
* to fetch and work with country-specific address formatting data.
*/

import {
getCountryFormatting,
hasCountryFormatting,
getAvailableLocales,
} from './country-formatting';

async function examples() {
console.log('=== Country Formatting API Examples ===\n');

Check failure on line 15 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement

// Example 1: Get Canadian formatting in English
console.log('Example 1: Canadian formatting (English)');

Check failure on line 18 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement
const caEN = await getCountryFormatting('CA', 'en');
console.log('Country:', caEN.name);

Check failure on line 20 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement
console.log('Edit template:', caEN.format.edit);

Check failure on line 21 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement
console.log('Province label:', caEN.labels.province);

Check failure on line 22 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement
console.log('Postal code example:', caEN.zip_example);

Check failure on line 23 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement
console.log('Number of provinces/territories:', caEN.zones?.length);

Check failure on line 24 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement
console.log();

Check failure on line 25 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement

// Example 2: Get Canadian formatting in French
console.log('Example 2: Canadian formatting (French)');

Check failure on line 28 in lang/typescript/src/country-formatting.example.ts

View workflow job for this annotation

GitHub Actions / Build Typescript

Unexpected console statement
const caFR = await getCountryFormatting('CA', 'fr');
console.log('Country:', caFR.name);
console.log('Province label:', caFR.labels.province);
const quebec = caFR.zones?.find(z => z.code === 'QC');
console.log('Quebec name in French:', quebec?.name);
console.log();

// Example 3: Get Brazilian formatting
console.log('Example 3: Brazilian formatting (Portuguese)');
const brPT = await getCountryFormatting('BR', 'pt-br');
console.log('Country:', brPT.name);
console.log('Show template:', brPT.format.show);
console.log('ZIP code label:', brPT.labels.zip);
console.log('Neighborhood label:', brPT.labels.neighborhood);
console.log('Uses split street fields:', brPT.additional_address_fields.street_name);
console.log();

// Example 4: Check available locales
console.log('Example 4: Check available locales');
const caLocales = await getAvailableLocales('CA');
console.log('Canada locales:', caLocales);
const brLocales = await getAvailableLocales('BR');
console.log('Brazil locales:', brLocales);
console.log();

// Example 5: Check if formatting exists
console.log('Example 5: Check if formatting exists');
const hasCAEN = await hasCountryFormatting('CA', 'en');
console.log('Has CA/en:', hasCAEN);
const hasCAES = await hasCountryFormatting('CA', 'es');
console.log('Has CA/es:', hasCAES);
console.log();

// Example 6: Work with zones
console.log('Example 6: Working with zones');
const ontario = caEN.zones?.find(z => z.code === 'ON');
if (ontario) {
console.log('Province:', ontario.name);
console.log('Code:', ontario.code);
console.log('Postal code prefixes:', ontario.zip_prefixes?.join(', '));
console.log('Neighboring zones:', ontario.neighboring_zones?.join(', '));
}
console.log();

// Example 7: Compare field requirements across countries
console.log('Example 7: Field requirements comparison');
console.log('Canada requires province:', caEN.additional_address_fields.province);
console.log('Canada requires neighborhood:', caEN.additional_address_fields.neighborhood || false);
console.log('Brazil requires province:', brPT.additional_address_fields.province);
console.log('Brazil requires neighborhood:', brPT.additional_address_fields.neighborhood);
console.log('Brazil uses street_name field:', brPT.additional_address_fields.street_name);
console.log();

// Example 8: Error handling
console.log('Example 8: Error handling');
try {
await getCountryFormatting('XX', 'en');
} catch (error) {
console.log('Expected error:', (error as Error).message);
}
}

// Run examples if this file is executed directly
if (require.main === module) {
examples().catch(console.error);
}
Loading
Loading