@huckleberry-inc/address 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -0
- package/build/cjs/AddressFormatter.js +98 -0
- package/build/cjs/format.js +53 -0
- package/build/cjs/graphqlQuery.js +76 -0
- package/build/cjs/index.js +23 -0
- package/build/cjs/loader.js +70 -0
- package/build/cjs/node_modules/@shopify/address-consts/build/esm/index.mjs.js +32 -0
- package/build/cjs/packages/address/src/AddressFormatter.js +98 -0
- package/build/cjs/packages/address/src/format.js +53 -0
- package/build/cjs/packages/address/src/graphqlQuery.js +76 -0
- package/build/cjs/packages/address/src/index.js +27 -0
- package/build/cjs/packages/address/src/loader.js +70 -0
- package/build/cjs/packages/address/src/utilities.js +65 -0
- package/build/cjs/utilities.js +65 -0
- package/build/esm/AddressFormatter.mjs +94 -0
- package/build/esm/format.mjs +48 -0
- package/build/esm/graphqlQuery.mjs +72 -0
- package/build/esm/index.mjs +4 -0
- package/build/esm/loader.mjs +64 -0
- package/build/esm/node_modules/@shopify/address-consts/build/esm/index.mjs.mjs +27 -0
- package/build/esm/packages/address/src/AddressFormatter.mjs +94 -0
- package/build/esm/packages/address/src/format.mjs +48 -0
- package/build/esm/packages/address/src/graphqlQuery.mjs +72 -0
- package/build/esm/packages/address/src/index.mjs +4 -0
- package/build/esm/packages/address/src/loader.mjs +64 -0
- package/build/esm/packages/address/src/utilities.mjs +59 -0
- package/build/esm/utilities.mjs +59 -0
- package/build/esnext/AddressFormatter.esnext +94 -0
- package/build/esnext/format.esnext +48 -0
- package/build/esnext/graphqlQuery.esnext +72 -0
- package/build/esnext/index.esnext +4 -0
- package/build/esnext/loader.esnext +64 -0
- package/build/esnext/node_modules/@shopify/address-consts/build/esm/index.mjs.esnext +27 -0
- package/build/esnext/packages/address/src/AddressFormatter.esnext +94 -0
- package/build/esnext/packages/address/src/format.esnext +48 -0
- package/build/esnext/packages/address/src/graphqlQuery.esnext +72 -0
- package/build/esnext/packages/address/src/index.esnext +4 -0
- package/build/esnext/packages/address/src/loader.esnext +64 -0
- package/build/esnext/packages/address/src/utilities.esnext +59 -0
- package/build/esnext/utilities.esnext +59 -0
- package/build/ts/AddressFormatter.d.ts +23 -0
- package/build/ts/AddressFormatter.d.ts.map +1 -0
- package/build/ts/format.d.ts +29 -0
- package/build/ts/format.d.ts.map +1 -0
- package/build/ts/graphqlQuery.d.ts +3 -0
- package/build/ts/graphqlQuery.d.ts.map +1 -0
- package/build/ts/index.d.ts +5 -0
- package/build/ts/index.d.ts.map +1 -0
- package/build/ts/loader.d.ts +11 -0
- package/build/ts/loader.d.ts.map +1 -0
- package/build/ts/utilities.d.ts +8 -0
- package/build/ts/utilities.d.ts.map +1 -0
- package/index.esnext +2 -0
- package/index.js +1 -0
- package/index.mjs +2 -0
- package/package.json +51 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
let FieldName;
|
|
2
|
+
(function (FieldName) {
|
|
3
|
+
FieldName["FirstName"] = "firstName";
|
|
4
|
+
FieldName["LastName"] = "lastName";
|
|
5
|
+
FieldName["Country"] = "country";
|
|
6
|
+
FieldName["City"] = "city";
|
|
7
|
+
FieldName["PostalCode"] = "zip";
|
|
8
|
+
FieldName["Zone"] = "province";
|
|
9
|
+
FieldName["Address1"] = "address1";
|
|
10
|
+
FieldName["Address2"] = "address2";
|
|
11
|
+
FieldName["Phone"] = "phone";
|
|
12
|
+
FieldName["Company"] = "company";
|
|
13
|
+
})(FieldName || (FieldName = {}));
|
|
14
|
+
const GRAPHQL_ENDPOINT = 'https://atlas.shopifysvc.com/graphql';
|
|
15
|
+
let GraphqlOperationName;
|
|
16
|
+
|
|
17
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
18
|
+
(function (GraphqlOperationName) {
|
|
19
|
+
GraphqlOperationName["Countries"] = "countries";
|
|
20
|
+
GraphqlOperationName["Country"] = "country";
|
|
21
|
+
})(GraphqlOperationName || (GraphqlOperationName = {}));
|
|
22
|
+
const HEADERS = {
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
'Access-Control-Allow-Origin': '*'
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { FieldName, GRAPHQL_ENDPOINT, GraphqlOperationName, HEADERS };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { formatAddress, buildOrderedFields } from './format.esnext';
|
|
2
|
+
import { loadCountry, loadCountries } from './loader.esnext';
|
|
3
|
+
|
|
4
|
+
const ORDERED_COUNTRIES_CACHE = new Map();
|
|
5
|
+
class AddressFormatter {
|
|
6
|
+
/**
|
|
7
|
+
* Useful in tests or any situation where the cache has undesirable
|
|
8
|
+
* side-effects.
|
|
9
|
+
*/
|
|
10
|
+
static resetCache() {
|
|
11
|
+
ORDERED_COUNTRIES_CACHE.clear();
|
|
12
|
+
}
|
|
13
|
+
constructor(locale) {
|
|
14
|
+
this.locale = locale;
|
|
15
|
+
this.locale = locale;
|
|
16
|
+
}
|
|
17
|
+
updateLocale(locale) {
|
|
18
|
+
this.locale = locale;
|
|
19
|
+
}
|
|
20
|
+
async getCountry(countryCode, {
|
|
21
|
+
includeHiddenZones = false
|
|
22
|
+
} = {}) {
|
|
23
|
+
const country = this.loadCountryFromCache(countryCode, includeHiddenZones);
|
|
24
|
+
if (country) return country;
|
|
25
|
+
return loadCountry(this.locale, countryCode, {
|
|
26
|
+
includeHiddenZones
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async getCountries({
|
|
30
|
+
includeHiddenZones = false
|
|
31
|
+
} = {}) {
|
|
32
|
+
const cacheKey = this.cacheKey(this.locale, includeHiddenZones);
|
|
33
|
+
const cachedCountries = ORDERED_COUNTRIES_CACHE.get(cacheKey);
|
|
34
|
+
if (cachedCountries) return cachedCountries;
|
|
35
|
+
const countries = await loadCountries(this.locale, {
|
|
36
|
+
includeHiddenZones
|
|
37
|
+
});
|
|
38
|
+
ORDERED_COUNTRIES_CACHE.set(cacheKey, countries);
|
|
39
|
+
return countries;
|
|
40
|
+
}
|
|
41
|
+
async getZoneName(countryCode, zoneCode) {
|
|
42
|
+
const country = await this.getCountry(countryCode);
|
|
43
|
+
const countryZone = country.zones.find(item => item.code === zoneCode);
|
|
44
|
+
if (!(countryZone !== null && countryZone !== void 0 && countryZone.name)) return undefined;
|
|
45
|
+
return countryZone.name;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Returns the address ordered in an array based based on the country code
|
|
49
|
+
* Eg.:
|
|
50
|
+
* [
|
|
51
|
+
* 'Shopify',
|
|
52
|
+
* 'First Name Last Name',
|
|
53
|
+
* 'Address 1',
|
|
54
|
+
* 'address2',
|
|
55
|
+
* 'Montréal',
|
|
56
|
+
* 'Canada Quebec H2J 4B7',
|
|
57
|
+
* '514 444 3333'
|
|
58
|
+
* ]
|
|
59
|
+
*/
|
|
60
|
+
async format(address) {
|
|
61
|
+
const country = await this.getCountry(address.country);
|
|
62
|
+
return formatAddress(address, country);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Returns an array that shows how to order fields based on the country code
|
|
66
|
+
* Eg.:
|
|
67
|
+
* [
|
|
68
|
+
* ['company'],
|
|
69
|
+
* ['firstName', 'lastName'],
|
|
70
|
+
* ['address1'],
|
|
71
|
+
* ['address2'],
|
|
72
|
+
* ['city'],
|
|
73
|
+
* ['country', 'province', 'zip'],
|
|
74
|
+
* ['phone']
|
|
75
|
+
* ]
|
|
76
|
+
*/
|
|
77
|
+
async getOrderedFields(countryCode) {
|
|
78
|
+
const country = await this.getCountry(countryCode);
|
|
79
|
+
return buildOrderedFields(country);
|
|
80
|
+
}
|
|
81
|
+
cacheKey(locale, includeHiddenZones) {
|
|
82
|
+
/* Cache list of countries per locale, both with and without hidden zones included */
|
|
83
|
+
return `${locale}-${includeHiddenZones}`;
|
|
84
|
+
}
|
|
85
|
+
loadCountryFromCache(countryCode, includeHiddenZones) {
|
|
86
|
+
const cachedCountries = ORDERED_COUNTRIES_CACHE.get(this.cacheKey(this.locale, includeHiddenZones));
|
|
87
|
+
if (!cachedCountries) return null;
|
|
88
|
+
return cachedCountries.find(({
|
|
89
|
+
code
|
|
90
|
+
}) => code === countryCode);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { AddressFormatter as default };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { renderLineTemplate, FIELD_REGEXP, FIELDS_MAPPING } from './utilities.esnext';
|
|
2
|
+
|
|
3
|
+
const LINE_DELIMITER = '_';
|
|
4
|
+
const DEFAULT_FORM_LAYOUT = '{firstName}{lastName}_{company}_{address1}_{address2}_{city}_{country}{province}{zip}_{phone}';
|
|
5
|
+
const DEFAULT_SHOW_LAYOUT = '{lastName} {firstName}_{company}_{address1} {address2}_{city} {province} {zip}_{country}_{phone}';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* When it's time to render any address, use this function so that it's properly
|
|
9
|
+
* formatted for the country's locale.
|
|
10
|
+
*
|
|
11
|
+
* ```typescript
|
|
12
|
+
* ['Shopify', 'Lindenstraße 9-14', '10969 Berlin', 'Germany'];
|
|
13
|
+
* ```
|
|
14
|
+
* @returns all lines of a formatted address as an array of strings.
|
|
15
|
+
*/
|
|
16
|
+
function formatAddress(address, country) {
|
|
17
|
+
const layout = country.formatting.show || DEFAULT_SHOW_LAYOUT;
|
|
18
|
+
return layout.split(LINE_DELIMITER).map(lineTemplate => renderLineTemplate(country, lineTemplate, address).trim());
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* In an edit form, this function can be used to properly order all the input
|
|
23
|
+
* fields.
|
|
24
|
+
*
|
|
25
|
+
* ```typescript
|
|
26
|
+
* [
|
|
27
|
+
* ['firstName', 'lastName'],
|
|
28
|
+
* ['company'],
|
|
29
|
+
* ['address1'],
|
|
30
|
+
* ['address2'],
|
|
31
|
+
* ['city'],
|
|
32
|
+
* ['country', 'province', 'zip'],
|
|
33
|
+
* ['phone'],
|
|
34
|
+
* ];
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function buildOrderedFields(country) {
|
|
38
|
+
const format = country ? country.formatting.edit : DEFAULT_FORM_LAYOUT;
|
|
39
|
+
return format.split(LINE_DELIMITER).map(lineTemplate => {
|
|
40
|
+
const result = lineTemplate.match(FIELD_REGEXP);
|
|
41
|
+
if (!result) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return result.map(field => FIELDS_MAPPING[field]);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { buildOrderedFields, formatAddress };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const query = `
|
|
2
|
+
query getCountries($locale: SupportedLocale!) {
|
|
3
|
+
countries(locale: $locale) {
|
|
4
|
+
name
|
|
5
|
+
code
|
|
6
|
+
continent
|
|
7
|
+
phoneNumberPrefix
|
|
8
|
+
autocompletionField
|
|
9
|
+
provinceKey
|
|
10
|
+
labels {
|
|
11
|
+
address1
|
|
12
|
+
address2
|
|
13
|
+
city
|
|
14
|
+
company
|
|
15
|
+
country
|
|
16
|
+
firstName
|
|
17
|
+
lastName
|
|
18
|
+
phone
|
|
19
|
+
postalCode
|
|
20
|
+
zone
|
|
21
|
+
}
|
|
22
|
+
optionalLabels {
|
|
23
|
+
address2
|
|
24
|
+
}
|
|
25
|
+
formatting {
|
|
26
|
+
edit
|
|
27
|
+
show
|
|
28
|
+
}
|
|
29
|
+
zones {
|
|
30
|
+
name
|
|
31
|
+
code
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
query getCountry($countryCode: SupportedCountry!, $locale: SupportedLocale!) {
|
|
37
|
+
country(countryCode: $countryCode, locale: $locale) {
|
|
38
|
+
name
|
|
39
|
+
code
|
|
40
|
+
continent
|
|
41
|
+
phoneNumberPrefix
|
|
42
|
+
autocompletionField
|
|
43
|
+
provinceKey
|
|
44
|
+
labels {
|
|
45
|
+
address1
|
|
46
|
+
address2
|
|
47
|
+
city
|
|
48
|
+
company
|
|
49
|
+
country
|
|
50
|
+
firstName
|
|
51
|
+
lastName
|
|
52
|
+
phone
|
|
53
|
+
postalCode
|
|
54
|
+
zone
|
|
55
|
+
}
|
|
56
|
+
optionalLabels {
|
|
57
|
+
address2
|
|
58
|
+
}
|
|
59
|
+
formatting {
|
|
60
|
+
edit
|
|
61
|
+
show
|
|
62
|
+
}
|
|
63
|
+
zones {
|
|
64
|
+
name
|
|
65
|
+
code
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
var query$1 = query;
|
|
71
|
+
|
|
72
|
+
export { query$1 as default };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { CountryLoaderError, loadCountries, loadCountry } from './loader.esnext';
|
|
2
|
+
export { buildOrderedFields, formatAddress } from './format.esnext';
|
|
3
|
+
export { default } from './AddressFormatter.esnext';
|
|
4
|
+
export { FieldName, GRAPHQL_ENDPOINT, GraphqlOperationName, HEADERS } from '../../../node_modules/@shopify/address-consts/build/esm/index.mjs.esnext';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import query from './graphqlQuery.esnext';
|
|
2
|
+
import { GRAPHQL_ENDPOINT, HEADERS, GraphqlOperationName } from '../../../node_modules/@shopify/address-consts/build/esm/index.mjs.esnext';
|
|
3
|
+
|
|
4
|
+
const loadCountries = memoizeAsync(async (locale, {
|
|
5
|
+
includeHiddenZones = false
|
|
6
|
+
} = {}) => {
|
|
7
|
+
const response = await fetch(GRAPHQL_ENDPOINT, {
|
|
8
|
+
method: 'POST',
|
|
9
|
+
headers: HEADERS,
|
|
10
|
+
body: JSON.stringify({
|
|
11
|
+
query,
|
|
12
|
+
operationName: GraphqlOperationName.Countries,
|
|
13
|
+
variables: {
|
|
14
|
+
locale: locale.replace(/-/, '_').toUpperCase(),
|
|
15
|
+
includeHiddenZones
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
});
|
|
19
|
+
const countries = await response.json();
|
|
20
|
+
if (!('data' in countries) && 'errors' in countries) {
|
|
21
|
+
throw new CountryLoaderError(countries);
|
|
22
|
+
}
|
|
23
|
+
return countries.data.countries;
|
|
24
|
+
});
|
|
25
|
+
const loadCountry = memoizeAsync(async (locale, countryCode, {
|
|
26
|
+
includeHiddenZones = false
|
|
27
|
+
} = {}) => {
|
|
28
|
+
const response = await fetch(GRAPHQL_ENDPOINT, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
headers: HEADERS,
|
|
31
|
+
body: JSON.stringify({
|
|
32
|
+
query,
|
|
33
|
+
operationName: GraphqlOperationName.Country,
|
|
34
|
+
variables: {
|
|
35
|
+
countryCode,
|
|
36
|
+
locale: locale.replace(/-/, '_').toUpperCase(),
|
|
37
|
+
includeHiddenZones
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
});
|
|
41
|
+
const country = await response.json();
|
|
42
|
+
if (!('data' in country) && 'errors' in country) {
|
|
43
|
+
throw new CountryLoaderError(country);
|
|
44
|
+
}
|
|
45
|
+
return country.data.country;
|
|
46
|
+
});
|
|
47
|
+
class CountryLoaderError extends Error {
|
|
48
|
+
constructor(errors) {
|
|
49
|
+
const errorMessage = errors.errors.map(error => error.message).join('; ');
|
|
50
|
+
super(errorMessage);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function memoizeAsync(asyncFunction) {
|
|
54
|
+
const cache = {};
|
|
55
|
+
return (...args) => {
|
|
56
|
+
const stringifiedArgs = JSON.stringify(args);
|
|
57
|
+
if (!cache[stringifiedArgs]) {
|
|
58
|
+
cache[stringifiedArgs] = asyncFunction.apply(this, args);
|
|
59
|
+
}
|
|
60
|
+
return cache[stringifiedArgs];
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { CountryLoaderError, loadCountries, loadCountry };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { FieldName } from '../../../node_modules/@shopify/address-consts/build/esm/index.mjs.esnext';
|
|
2
|
+
|
|
3
|
+
const FIELD_REGEXP = /({\w+})/g;
|
|
4
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
5
|
+
const FIELDS_MAPPING = {
|
|
6
|
+
'{firstName}': FieldName.FirstName,
|
|
7
|
+
'{lastName}': FieldName.LastName,
|
|
8
|
+
'{country}': FieldName.Country,
|
|
9
|
+
'{city}': FieldName.City,
|
|
10
|
+
'{zip}': FieldName.PostalCode,
|
|
11
|
+
'{province}': FieldName.Zone,
|
|
12
|
+
'{address1}': FieldName.Address1,
|
|
13
|
+
'{address2}': FieldName.Address2,
|
|
14
|
+
'{phone}': FieldName.Phone,
|
|
15
|
+
'{company}': FieldName.Company
|
|
16
|
+
};
|
|
17
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* Returns empty string if all replacement fields are empty.
|
|
21
|
+
*/
|
|
22
|
+
function renderLineTemplate(country, template, address) {
|
|
23
|
+
const result = template.match(FIELD_REGEXP);
|
|
24
|
+
let line = template;
|
|
25
|
+
if (!result) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
let lineIsEmpty = true;
|
|
29
|
+
result.forEach(key => {
|
|
30
|
+
const addressKey = key.replace('{', '').replace('}', '');
|
|
31
|
+
if (address[addressKey]) {
|
|
32
|
+
lineIsEmpty = false;
|
|
33
|
+
}
|
|
34
|
+
switch (addressKey) {
|
|
35
|
+
case FieldName.Country:
|
|
36
|
+
line = line.replace(`{${FieldName.Country}}`, country.name);
|
|
37
|
+
break;
|
|
38
|
+
case FieldName.Zone:
|
|
39
|
+
line = line.replace(`{${FieldName.Zone}}`, address.province ? getZone(country.zones, address.province).name : '');
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
line = line.replace(key, address[addressKey] || '');
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
if (lineIsEmpty) {
|
|
47
|
+
return '';
|
|
48
|
+
} else {
|
|
49
|
+
return line.trim().replace(' ', ' ');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function getZone(zones, zoneCode) {
|
|
53
|
+
return zones.find(zone => zone.code === zoneCode) || {
|
|
54
|
+
name: '',
|
|
55
|
+
code: ''
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { FIELDS_MAPPING, FIELD_REGEXP, renderLineTemplate };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { FieldName } from '@huckleberry-inc/address-consts';
|
|
2
|
+
|
|
3
|
+
const FIELD_REGEXP = /({\w+})/g;
|
|
4
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
5
|
+
const FIELDS_MAPPING = {
|
|
6
|
+
'{firstName}': FieldName.FirstName,
|
|
7
|
+
'{lastName}': FieldName.LastName,
|
|
8
|
+
'{country}': FieldName.Country,
|
|
9
|
+
'{city}': FieldName.City,
|
|
10
|
+
'{zip}': FieldName.PostalCode,
|
|
11
|
+
'{province}': FieldName.Zone,
|
|
12
|
+
'{address1}': FieldName.Address1,
|
|
13
|
+
'{address2}': FieldName.Address2,
|
|
14
|
+
'{phone}': FieldName.Phone,
|
|
15
|
+
'{company}': FieldName.Company
|
|
16
|
+
};
|
|
17
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* Returns empty string if all replacement fields are empty.
|
|
21
|
+
*/
|
|
22
|
+
function renderLineTemplate(country, template, address) {
|
|
23
|
+
const result = template.match(FIELD_REGEXP);
|
|
24
|
+
let line = template;
|
|
25
|
+
if (!result) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
let lineIsEmpty = true;
|
|
29
|
+
result.forEach(key => {
|
|
30
|
+
const addressKey = key.replace('{', '').replace('}', '');
|
|
31
|
+
if (address[addressKey]) {
|
|
32
|
+
lineIsEmpty = false;
|
|
33
|
+
}
|
|
34
|
+
switch (addressKey) {
|
|
35
|
+
case FieldName.Country:
|
|
36
|
+
line = line.replace(`{${FieldName.Country}}`, country.name);
|
|
37
|
+
break;
|
|
38
|
+
case FieldName.Zone:
|
|
39
|
+
line = line.replace(`{${FieldName.Zone}}`, address.province ? getZone(country.zones, address.province).name : '');
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
line = line.replace(key, address[addressKey] || '');
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
if (lineIsEmpty) {
|
|
47
|
+
return '';
|
|
48
|
+
} else {
|
|
49
|
+
return line.trim().replace(' ', ' ');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function getZone(zones, zoneCode) {
|
|
53
|
+
return zones.find(zone => zone.code === zoneCode) || {
|
|
54
|
+
name: '',
|
|
55
|
+
code: ''
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { FIELDS_MAPPING, FIELD_REGEXP, renderLineTemplate };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Address, FieldName, Country } from '@shopify/address-consts';
|
|
2
|
+
export default class AddressFormatter {
|
|
3
|
+
private locale;
|
|
4
|
+
/**
|
|
5
|
+
* Useful in tests or any situation where the cache has undesirable
|
|
6
|
+
* side-effects.
|
|
7
|
+
*/
|
|
8
|
+
static resetCache(): void;
|
|
9
|
+
constructor(locale: string);
|
|
10
|
+
updateLocale(locale: string): void;
|
|
11
|
+
getCountry(countryCode: string, { includeHiddenZones }?: {
|
|
12
|
+
includeHiddenZones?: boolean | undefined;
|
|
13
|
+
}): Promise<Country>;
|
|
14
|
+
getCountries({ includeHiddenZones }?: {
|
|
15
|
+
includeHiddenZones?: boolean | undefined;
|
|
16
|
+
}): Promise<Country[]>;
|
|
17
|
+
getZoneName(countryCode: string, zoneCode: string): Promise<string | undefined>;
|
|
18
|
+
format(address: Address): Promise<string[]>;
|
|
19
|
+
getOrderedFields(countryCode: string): Promise<FieldName[][]>;
|
|
20
|
+
private cacheKey;
|
|
21
|
+
private loadCountryFromCache;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=AddressFormatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddressFormatter.d.ts","sourceRoot":"","sources":["../../src/AddressFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAC,MAAM,yBAAyB,CAAC;AAOzE,MAAM,CAAC,OAAO,OAAO,gBAAgB;IASvB,OAAO,CAAC,MAAM;IAR1B;;;OAGG;IACH,MAAM,CAAC,UAAU;gBAIG,MAAM,EAAE,MAAM;IAIlC,YAAY,CAAC,MAAM,EAAE,MAAM;IAIrB,UAAU,CACd,WAAW,EAAE,MAAM,EACnB,EAAC,kBAA0B,EAAC;;KAAK,GAChC,OAAO,CAAC,OAAO,CAAC;IAOb,YAAY,CAAC,EAAC,kBAA0B,EAAC;;KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAYnE,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAoBxB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiB3C,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;IAMnE,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,oBAAoB;CAW7B"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Address, Country, FieldName } from '@shopify/address-consts';
|
|
2
|
+
/**
|
|
3
|
+
* When it's time to render any address, use this function so that it's properly
|
|
4
|
+
* formatted for the country's locale.
|
|
5
|
+
*
|
|
6
|
+
* ```typescript
|
|
7
|
+
* ['Shopify', 'Lindenstraße 9-14', '10969 Berlin', 'Germany'];
|
|
8
|
+
* ```
|
|
9
|
+
* @returns all lines of a formatted address as an array of strings.
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatAddress(address: Address, country: Country): string[];
|
|
12
|
+
/**
|
|
13
|
+
* In an edit form, this function can be used to properly order all the input
|
|
14
|
+
* fields.
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* [
|
|
18
|
+
* ['firstName', 'lastName'],
|
|
19
|
+
* ['company'],
|
|
20
|
+
* ['address1'],
|
|
21
|
+
* ['address2'],
|
|
22
|
+
* ['city'],
|
|
23
|
+
* ['country', 'province', 'zip'],
|
|
24
|
+
* ['phone'],
|
|
25
|
+
* ];
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildOrderedFields(country: Country): FieldName[][];
|
|
29
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAC,MAAM,yBAAyB,CAAC;AAUzE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,CAO1E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,EAAE,CAUlE"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const query = "\nquery getCountries($locale: SupportedLocale!) {\n countries(locale: $locale) {\n name\n code\n continent\n phoneNumberPrefix\n autocompletionField\n provinceKey\n labels {\n address1\n address2\n city\n company\n country\n firstName\n lastName\n phone\n postalCode\n zone\n }\n optionalLabels {\n address2\n }\n formatting {\n edit\n show\n }\n zones {\n name\n code\n }\n }\n}\n\nquery getCountry($countryCode: SupportedCountry!, $locale: SupportedLocale!) {\n country(countryCode: $countryCode, locale: $locale) {\n name\n code\n continent\n phoneNumberPrefix\n autocompletionField\n provinceKey\n labels {\n address1\n address2\n city\n company\n country\n firstName\n lastName\n phone\n postalCode\n zone\n }\n optionalLabels {\n address2\n }\n formatting {\n edit\n show\n }\n zones {\n name\n code\n }\n }\n}\n";
|
|
2
|
+
export default query;
|
|
3
|
+
//# sourceMappingURL=graphqlQuery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphqlQuery.d.ts","sourceRoot":"","sources":["../../src/graphqlQuery.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,KAAK,qiCAoEV,CAAC;AAEF,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AAExC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Country, ResponseError } from '@shopify/address-consts';
|
|
2
|
+
export declare const loadCountries: (locale: string, options?: {
|
|
3
|
+
includeHiddenZones?: boolean;
|
|
4
|
+
}) => Promise<Country[]>;
|
|
5
|
+
export declare const loadCountry: (locale: string, countryCode: string, options?: {
|
|
6
|
+
includeHiddenZones?: boolean;
|
|
7
|
+
}) => Promise<Country>;
|
|
8
|
+
export declare class CountryLoaderError extends Error {
|
|
9
|
+
constructor(errors: ResponseError);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAGP,aAAa,EACd,MAAM,yBAAyB,CAAC;AASjC,eAAO,MAAM,aAAa,EAAE,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAC,KACrC,OAAO,CAAC,OAAO,EAAE,CAwBrB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,CACxB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAC,KACrC,OAAO,CAAC,OAAO,CA4BnB,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,MAAM,EAAE,aAAa;CAIlC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Address, Country } from '@shopify/address-consts';
|
|
2
|
+
import { FieldName } from '@shopify/address-consts';
|
|
3
|
+
export declare const FIELD_REGEXP: RegExp;
|
|
4
|
+
export declare const FIELDS_MAPPING: {
|
|
5
|
+
[key: string]: FieldName;
|
|
6
|
+
};
|
|
7
|
+
export declare function renderLineTemplate(country: Country, template: string, address: Address): string;
|
|
8
|
+
//# sourceMappingURL=utilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../src/utilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAE,OAAO,EAAO,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAC,SAAS,EAAC,MAAM,yBAAyB,CAAC;AAElD,eAAO,MAAM,YAAY,QAAa,CAAC;AAEvC,eAAO,MAAM,cAAc,EAAE;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CAY1B,CAAC;AAMF,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,GACf,MAAM,CAoCR"}
|
package/index.esnext
ADDED
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require("./build/cjs/index.js");
|
package/index.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@huckleberry-inc/address",
|
|
3
|
+
"version": "4.3.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Address utilities for formatting addresses",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "./build/ts/index.d.ts",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public",
|
|
10
|
+
"@shopify:registry": "https://registry.npmjs.org"
|
|
11
|
+
},
|
|
12
|
+
"author": "Shopify Inc.",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/Shopify/quilt.git",
|
|
16
|
+
"directory": "packages/address"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/Shopify/quilt/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/Shopify/quilt/blob/main/packages/address/README.md",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.12.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@shopify/address-mocks": "^3.3.1",
|
|
27
|
+
"@shopify/jest-dom-mocks": "^5.2.0"
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@huckleberry-inc/address-consts": "^4.2.0"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"build/",
|
|
35
|
+
"!build/*.tsbuildinfo",
|
|
36
|
+
"!build/ts/**/tests/",
|
|
37
|
+
"index.js",
|
|
38
|
+
"index.mjs",
|
|
39
|
+
"index.esnext"
|
|
40
|
+
],
|
|
41
|
+
"module": "index.mjs",
|
|
42
|
+
"esnext": "index.esnext",
|
|
43
|
+
"exports": {
|
|
44
|
+
".": {
|
|
45
|
+
"types": "./build/ts/index.d.ts",
|
|
46
|
+
"esnext": "./index.esnext",
|
|
47
|
+
"import": "./index.mjs",
|
|
48
|
+
"require": "./index.js"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|