@shopify/address
Advanced tools
Comparing version 2.4.1 to 2.4.3
@@ -46,3 +46,2 @@ "use strict"; | ||
var ORDERED_COUNTRIES_CACHE = {}; | ||
var COUNTRIES_CACHE = {}; | ||
var AddressFormatter = /** @class */ (function () { | ||
@@ -52,7 +51,5 @@ function AddressFormatter(locale) { | ||
this.locale = locale; | ||
COUNTRIES_CACHE[this.locale] = {}; | ||
} | ||
AddressFormatter.prototype.updateLocale = function (locale) { | ||
this.locale = locale; | ||
COUNTRIES_CACHE[this.locale] = {}; | ||
}; | ||
@@ -72,3 +69,2 @@ AddressFormatter.prototype.getCountry = function (countryCode) { | ||
country = _a.sent(); | ||
COUNTRIES_CACHE[this.locale][country.code] = country; | ||
return [2 /*return*/, country]; | ||
@@ -84,7 +80,3 @@ } | ||
switch (_a.label) { | ||
case 0: | ||
if (ORDERED_COUNTRIES_CACHE[this.locale]) { | ||
return [2 /*return*/, ORDERED_COUNTRIES_CACHE[this.locale]]; | ||
} | ||
return [4 /*yield*/, loader_1.loadCountries(this.locale)]; | ||
case 0: return [4 /*yield*/, loader_1.loadCountries(this.locale)]; | ||
case 1: | ||
@@ -184,6 +176,2 @@ countries = _a.sent(); | ||
AddressFormatter.prototype.loadCountryFromCache = function (countryCode) { | ||
var cachedCountry = COUNTRIES_CACHE[this.locale][countryCode]; | ||
if (cachedCountry) { | ||
return cachedCountry; | ||
} | ||
if (ORDERED_COUNTRIES_CACHE[this.locale]) { | ||
@@ -190,0 +178,0 @@ return ORDERED_COUNTRIES_CACHE[this.locale].find(function (country) { |
@@ -7,5 +7,5 @@ import { Country } from './types'; | ||
} | ||
export declare function loadCountries(locale: string): Promise<Country[]>; | ||
export declare function loadCountry(locale: string, countryCode: string): Promise<Country>; | ||
export declare const loadCountries: (locale: string) => Promise<Country[]>; | ||
export declare const loadCountry: (locale: string, countryCode: string) => Promise<Country>; | ||
export declare const SUPPORTED_LOCALES: string[]; | ||
export declare function toSupportedLocale(locale: string): string; |
@@ -53,2 +53,3 @@ "use strict"; | ||
}; | ||
var _this = this; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -66,69 +67,57 @@ var graphqlQuery_1 = __importDefault(require("./graphqlQuery")); | ||
}; | ||
function loadCountries(locale) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var response, countries; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, fetch(exports.GRAPHQL_ENDPOINT, { | ||
method: 'POST', | ||
headers: HEADERS, | ||
body: JSON.stringify({ | ||
query: graphqlQuery_1.default, | ||
operationName: GRAPHQL_OPERATION_NAMES.countries, | ||
variables: { | ||
locale: toSupportedLocale(locale), | ||
}, | ||
}), | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
return [4 /*yield*/, response.json()]; | ||
case 2: | ||
countries = _a.sent(); | ||
if ('errors' in countries) { | ||
throw new CountryLoaderError(countries); | ||
} | ||
else { | ||
return [2 /*return*/, countries.data.countries]; | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
exports.loadCountries = memoizeAsync(function (locale) { return __awaiter(_this, void 0, void 0, function () { | ||
var response, countries; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, fetch(exports.GRAPHQL_ENDPOINT, { | ||
method: 'POST', | ||
headers: HEADERS, | ||
body: JSON.stringify({ | ||
query: graphqlQuery_1.default, | ||
operationName: GRAPHQL_OPERATION_NAMES.countries, | ||
variables: { | ||
locale: toSupportedLocale(locale), | ||
}, | ||
}), | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
return [4 /*yield*/, response.json()]; | ||
case 2: | ||
countries = _a.sent(); | ||
if ('errors' in countries) { | ||
throw new CountryLoaderError(countries); | ||
} | ||
return [2 /*return*/, countries.data.countries]; | ||
} | ||
}); | ||
} | ||
exports.loadCountries = loadCountries; | ||
function loadCountry(locale, countryCode) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var response, country; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, fetch(exports.GRAPHQL_ENDPOINT, { | ||
method: 'POST', | ||
headers: HEADERS, | ||
body: JSON.stringify({ | ||
query: graphqlQuery_1.default, | ||
operationName: GRAPHQL_OPERATION_NAMES.country, | ||
variables: { | ||
countryCode: countryCode, | ||
locale: toSupportedLocale(locale), | ||
}, | ||
}), | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
return [4 /*yield*/, response.json()]; | ||
case 2: | ||
country = _a.sent(); | ||
if ('errors' in country) { | ||
throw new CountryLoaderError(country); | ||
} | ||
else { | ||
return [2 /*return*/, country.data.country]; | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
exports.loadCountry = memoizeAsync(function (locale, countryCode) { return __awaiter(_this, void 0, void 0, function () { | ||
var response, country; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, fetch(exports.GRAPHQL_ENDPOINT, { | ||
method: 'POST', | ||
headers: HEADERS, | ||
body: JSON.stringify({ | ||
query: graphqlQuery_1.default, | ||
operationName: GRAPHQL_OPERATION_NAMES.country, | ||
variables: { | ||
countryCode: countryCode, | ||
locale: toSupportedLocale(locale), | ||
}, | ||
}), | ||
})]; | ||
case 1: | ||
response = _a.sent(); | ||
return [4 /*yield*/, response.json()]; | ||
case 2: | ||
country = _a.sent(); | ||
if ('errors' in country) { | ||
throw new CountryLoaderError(country); | ||
} | ||
return [2 /*return*/, country.data.country]; | ||
} | ||
}); | ||
} | ||
exports.loadCountry = loadCountry; | ||
}); }); | ||
var CountryLoaderError = /** @class */ (function (_super) { | ||
@@ -167,1 +156,16 @@ __extends(CountryLoaderError, _super); | ||
exports.toSupportedLocale = toSupportedLocale; | ||
function memoizeAsync(asyncFunction) { | ||
var _this = this; | ||
var cache = {}; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var stringifiedArgs = JSON.stringify(args); | ||
if (!cache[stringifiedArgs]) { | ||
cache[stringifiedArgs] = asyncFunction.apply(_this, args); | ||
} | ||
return cache[stringifiedArgs]; | ||
}; | ||
} |
{ | ||
"name": "@shopify/address", | ||
"version": "2.4.1", | ||
"version": "2.4.3", | ||
"license": "MIT", | ||
@@ -26,2 +26,3 @@ "description": "Address utilities for formatting addresses.", | ||
"devDependencies": { | ||
"@shopify/address-mocks": "^1.0.4", | ||
"@shopify/jest-dom-mocks": "^2.1.0", | ||
@@ -28,0 +29,0 @@ "typescript": "~3.0.1" |
@@ -16,12 +16,5 @@ import {Address, FieldName, Country} from './types'; | ||
const COUNTRIES_CACHE: { | ||
[locale: string]: { | ||
[countryCode: string]: Country; | ||
}; | ||
} = {}; | ||
export default class AddressFormatter { | ||
constructor(private locale: string) { | ||
this.locale = locale; | ||
COUNTRIES_CACHE[this.locale] = {}; | ||
} | ||
@@ -31,3 +24,2 @@ | ||
this.locale = locale; | ||
COUNTRIES_CACHE[this.locale] = {}; | ||
} | ||
@@ -42,3 +34,2 @@ | ||
country = await loadCountry(this.locale, countryCode); | ||
COUNTRIES_CACHE[this.locale][country.code] = country; | ||
@@ -49,5 +40,2 @@ return country; | ||
async getCountries(): Promise<Country[]> { | ||
if (ORDERED_COUNTRIES_CACHE[this.locale]) { | ||
return ORDERED_COUNTRIES_CACHE[this.locale]; | ||
} | ||
const countries = await loadCountries(this.locale); | ||
@@ -128,8 +116,2 @@ ORDERED_COUNTRIES_CACHE[this.locale] = countries; | ||
): Country | undefined | null { | ||
const cachedCountry = COUNTRIES_CACHE[this.locale][countryCode]; | ||
if (cachedCountry) { | ||
return cachedCountry; | ||
} | ||
if (ORDERED_COUNTRIES_CACHE[this.locale]) { | ||
@@ -136,0 +118,0 @@ return ORDERED_COUNTRIES_CACHE[this.locale].find(country => { |
@@ -21,3 +21,5 @@ import { | ||
export async function loadCountries(locale: string): Promise<Country[]> { | ||
export const loadCountries: ( | ||
locale: string, | ||
) => Promise<Country[]> = memoizeAsync(async (locale: string) => { | ||
const response = await fetch(GRAPHQL_ENDPOINT, { | ||
@@ -34,35 +36,41 @@ method: 'POST', | ||
}); | ||
const countries: | ||
| LoadCountriesResponse | ||
| ResponseError = await response.json(); | ||
if ('errors' in countries) { | ||
throw new CountryLoaderError(countries); | ||
} else { | ||
return countries.data.countries; | ||
} | ||
} | ||
export async function loadCountry( | ||
return countries.data.countries; | ||
}); | ||
export const loadCountry: ( | ||
locale: string, | ||
countryCode: string, | ||
): Promise<Country> { | ||
const response = await fetch(GRAPHQL_ENDPOINT, { | ||
method: 'POST', | ||
headers: HEADERS, | ||
body: JSON.stringify({ | ||
query, | ||
operationName: GRAPHQL_OPERATION_NAMES.country, | ||
variables: { | ||
countryCode, | ||
locale: toSupportedLocale(locale), | ||
}, | ||
}), | ||
}); | ||
const country: LoadCountryResponse = await response.json(); | ||
if ('errors' in country) { | ||
throw new CountryLoaderError(country); | ||
} else { | ||
) => Promise<Country> = memoizeAsync( | ||
async (locale: string, countryCode: string): Promise<Country> => { | ||
const response = await fetch(GRAPHQL_ENDPOINT, { | ||
method: 'POST', | ||
headers: HEADERS, | ||
body: JSON.stringify({ | ||
query, | ||
operationName: GRAPHQL_OPERATION_NAMES.country, | ||
variables: { | ||
countryCode, | ||
locale: toSupportedLocale(locale), | ||
}, | ||
}), | ||
}); | ||
const country: LoadCountryResponse = await response.json(); | ||
if ('errors' in country) { | ||
throw new CountryLoaderError(country); | ||
} | ||
return country.data.country; | ||
} | ||
} | ||
}, | ||
); | ||
@@ -99,1 +107,18 @@ class CountryLoaderError extends Error { | ||
} | ||
type AsyncFunc = (...args: any[]) => Promise<any>; | ||
interface Cache { | ||
[key: string]: Promise<any>; | ||
} | ||
function memoizeAsync(asyncFunction: AsyncFunc) { | ||
const cache: Cache = {}; | ||
return (...args: any[]) => { | ||
const stringifiedArgs = JSON.stringify(args); | ||
if (!cache[stringifiedArgs]) { | ||
cache[stringifiedArgs] = asyncFunction.apply(this, args); | ||
} | ||
return cache[stringifiedArgs] as Promise<any>; | ||
}; | ||
} |
import {fetch} from '@shopify/jest-dom-mocks'; | ||
import {mockCountryRequests} from '../../../address-mocks/src'; | ||
import {Address, FieldName} from '../types'; | ||
import AddressFormatter from '..'; | ||
import {mockCountryRequests} from './utilities'; | ||
import {toSupportedLocale} from '../loader'; | ||
@@ -26,3 +26,3 @@ | ||
const addressFormatter = new AddressFormatter('ja'); | ||
let country = await addressFormatter.getCountry('JP'); | ||
let country = await addressFormatter.getCountry('CA'); | ||
@@ -32,3 +32,3 @@ expect(country.name).toEqual('カナダ'); | ||
addressFormatter.updateLocale('en'); | ||
country = await addressFormatter.getCountry('JP'); | ||
country = await addressFormatter.getCountry('CA'); | ||
@@ -57,3 +57,4 @@ expect(country.name).toEqual('Canada'); | ||
it('should not call the API again for the same country if the locale is the same', async () => { | ||
const addressFormatter = new AddressFormatter('ja'); | ||
const addressFormatter = new AddressFormatter('pt-br'); | ||
await addressFormatter.getCountry('CA'); | ||
@@ -66,3 +67,3 @@ await addressFormatter.getCountry('CA'); | ||
it('should call the API again for the same country if the locale changes', async () => { | ||
const addressFormatter = new AddressFormatter('ja'); | ||
const addressFormatter = new AddressFormatter('fr'); | ||
await addressFormatter.getCountry('CA'); | ||
@@ -72,3 +73,3 @@ | ||
addressFormatter.updateLocale('en'); | ||
addressFormatter.updateLocale('es'); | ||
await addressFormatter.getCountry('CA'); | ||
@@ -133,3 +134,3 @@ | ||
'Shopify', | ||
'田中恵子様', | ||
'田中 恵子様', | ||
'514 xxx xxxx', | ||
@@ -150,3 +151,3 @@ ]); | ||
'Shopify', | ||
'田中恵子様', | ||
'田中 恵子様', | ||
'514 xxx xxxx', | ||
@@ -153,0 +154,0 @@ ]); |
@@ -1,5 +0,6 @@ | ||
import {Country} from '../types'; | ||
import {fixtures} from '../../../address-mocks/src/fixtures'; | ||
import {renderLineTemplate} from '../utilities'; | ||
import {countryCAEn} from './fixtures'; | ||
const Canada = fixtures.country.EN.data.country; | ||
const address = { | ||
@@ -21,9 +22,5 @@ company: 'Shopify', | ||
const template = '{country} - {city} {zip} {province}'; | ||
expect( | ||
renderLineTemplate( | ||
countryCAEn.data.country as Country, | ||
template, | ||
address, | ||
), | ||
).toEqual('Canada - 目黒区 100-8994'); | ||
expect(renderLineTemplate(Canada, template, address)).toEqual( | ||
'Canada - 目黒区 100-8994', | ||
); | ||
}); | ||
@@ -34,3 +31,3 @@ | ||
expect( | ||
renderLineTemplate(countryCAEn.data.country as Country, template, { | ||
renderLineTemplate(Canada, template, { | ||
...address, | ||
@@ -44,9 +41,5 @@ province: 'lol', | ||
const template = '{country} - {city} {zip} {province} {what}'; | ||
expect( | ||
renderLineTemplate( | ||
countryCAEn.data.country as Country, | ||
template, | ||
address, | ||
), | ||
).toEqual('Canada - 目黒区 100-8994'); | ||
expect(renderLineTemplate(Canada, template, address)).toEqual( | ||
'Canada - 目黒区 100-8994', | ||
); | ||
}); | ||
@@ -56,9 +49,3 @@ | ||
const template = '{firstName} - {lastName}'; | ||
expect( | ||
renderLineTemplate( | ||
countryCAEn.data.country as Country, | ||
template, | ||
address, | ||
), | ||
).toEqual(''); | ||
expect(renderLineTemplate(Canada, template, address)).toEqual(''); | ||
}); | ||
@@ -68,9 +55,3 @@ | ||
const template = '[Nope]'; | ||
expect( | ||
renderLineTemplate( | ||
countryCAEn.data.country as Country, | ||
template, | ||
address, | ||
), | ||
).toEqual(''); | ||
expect(renderLineTemplate(Canada, template, address)).toEqual(''); | ||
}); | ||
@@ -81,3 +62,3 @@ | ||
expect( | ||
renderLineTemplate(countryCAEn.data.country as Country, template, { | ||
renderLineTemplate(Canada, template, { | ||
...address, | ||
@@ -84,0 +65,0 @@ province: 'NOPE', |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47979
3
24
1175
3