arky-sdk 0.9.13 → 0.9.16

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.
Files changed (40) hide show
  1. package/README.md +16 -12
  2. package/dist/admin-C-ZTxvz3.d.ts +1544 -0
  3. package/dist/admin-Dm2WRN6q.d.cts +1544 -0
  4. package/dist/admin.cjs +982 -425
  5. package/dist/admin.cjs.map +1 -1
  6. package/dist/admin.d.cts +3 -3
  7. package/dist/admin.d.ts +3 -3
  8. package/dist/admin.js +982 -425
  9. package/dist/admin.js.map +1 -1
  10. package/dist/{api-DvsFdOaF.d.cts → api-D37IpMSq.d.cts} +1417 -665
  11. package/dist/{api-DvsFdOaF.d.ts → api-D37IpMSq.d.ts} +1417 -665
  12. package/dist/index.cjs +1317 -539
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +3 -3
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +1317 -539
  17. package/dist/index.js.map +1 -1
  18. package/dist/{index-CQd9b_7n.d.ts → inventory-DdN96PX3.d.cts} +6 -4
  19. package/dist/{index-BC06yiuv.d.cts → inventory-Dh1RevEb.d.ts} +6 -4
  20. package/dist/storefront.cjs +1210 -658
  21. package/dist/storefront.cjs.map +1 -1
  22. package/dist/storefront.d.cts +88 -285
  23. package/dist/storefront.d.ts +88 -285
  24. package/dist/storefront.js +1207 -659
  25. package/dist/storefront.js.map +1 -1
  26. package/dist/types.cjs.map +1 -1
  27. package/dist/types.d.cts +1 -1
  28. package/dist/types.d.ts +1 -1
  29. package/dist/types.js.map +1 -1
  30. package/dist/utils.cjs +198 -16
  31. package/dist/utils.cjs.map +1 -1
  32. package/dist/utils.d.cts +18 -2
  33. package/dist/utils.d.ts +18 -2
  34. package/dist/utils.js +191 -17
  35. package/dist/utils.js.map +1 -1
  36. package/package.json +4 -5
  37. package/dist/admin-Q9MBFwCb.d.cts +0 -1496
  38. package/dist/admin-ZLXD4_en.d.ts +0 -1496
  39. package/scripts/contract-admin.mjs +0 -120
  40. package/scripts/contract-storefront.mjs +0 -296
package/dist/utils.cjs CHANGED
@@ -30,32 +30,76 @@ function nameToKey(name) {
30
30
  }
31
31
 
32
32
  // src/utils/price.ts
33
+ var SUPPORTED_STORE_CURRENCIES = Object.freeze([
34
+ "USD",
35
+ "EUR",
36
+ "GBP",
37
+ "JPY",
38
+ "CNY",
39
+ "CHF",
40
+ "AUD",
41
+ "CAD",
42
+ "HKD",
43
+ "SGD",
44
+ "NZD",
45
+ "KRW",
46
+ "SEK",
47
+ "NOK",
48
+ "DKK",
49
+ "INR",
50
+ "MXN",
51
+ "BRL",
52
+ "ZAR",
53
+ "RUB",
54
+ "TRY",
55
+ "PLN",
56
+ "THB",
57
+ "IDR",
58
+ "MYR",
59
+ "PHP",
60
+ "CZK",
61
+ "ILS",
62
+ "AED",
63
+ "SAR",
64
+ "HUF",
65
+ "RON",
66
+ "BGN",
67
+ "HRK",
68
+ "BAM",
69
+ "RSD",
70
+ "MKD",
71
+ "ALL"
72
+ ]);
73
+ var SUPPORTED_STORE_CURRENCY_SET = Object.freeze(
74
+ new Set(SUPPORTED_STORE_CURRENCIES)
75
+ );
76
+ var ZERO_MINOR_UNIT_STORE_CURRENCIES = Object.freeze(
77
+ /* @__PURE__ */ new Set(["JPY", "KRW"])
78
+ );
33
79
  function formatCurrency(amount, currencyCode, locale = "en") {
34
- if (!currencyCode) return "";
80
+ const normalized = currencyCode.trim().toUpperCase();
81
+ if (!normalized) return "";
82
+ const minorUnits = getCurrencyMinorUnits(normalized);
35
83
  return new Intl.NumberFormat(locale, {
36
84
  style: "currency",
37
- currency: currencyCode.toUpperCase()
85
+ currency: normalized,
86
+ minimumFractionDigits: minorUnits,
87
+ maximumFractionDigits: minorUnits
38
88
  }).format(amount);
39
89
  }
40
- function getMinorUnits(currency) {
41
- try {
42
- const formatter = new Intl.NumberFormat("en", {
43
- style: "currency",
44
- currency: currency.toUpperCase()
45
- });
46
- const parts = formatter.formatToParts(1.11);
47
- const fractionPart = parts.find((p) => p.type === "fraction");
48
- return fractionPart?.value.length ?? 2;
49
- } catch {
50
- return 2;
90
+ function getCurrencyMinorUnits(currency) {
91
+ const normalized = currency.trim().toUpperCase();
92
+ if (!SUPPORTED_STORE_CURRENCY_SET.has(normalized)) {
93
+ throw new RangeError(`Unsupported currency '${currency}'`);
51
94
  }
95
+ return ZERO_MINOR_UNIT_STORE_CURRENCIES.has(normalized) ? 0 : 2;
52
96
  }
53
97
  function convertToMajor(minorAmount, currency) {
54
- const units = getMinorUnits(currency);
98
+ const units = getCurrencyMinorUnits(currency);
55
99
  return minorAmount / Math.pow(10, units);
56
100
  }
57
101
  function convertToMinor(majorAmount, currency) {
58
- const units = getMinorUnits(currency);
102
+ const units = getCurrencyMinorUnits(currency);
59
103
  return Math.round(majorAmount * Math.pow(10, units));
60
104
  }
61
105
  function getCurrencySymbol(currency) {
@@ -77,7 +121,9 @@ function getCurrencyName(currency) {
77
121
  }
78
122
  }
79
123
  function formatMinor(amountMinor, currency) {
80
- if (!currency) return "";
124
+ if (!Number.isSafeInteger(amountMinor)) {
125
+ throw new RangeError("Minor-unit amount must be a safe integer");
126
+ }
81
127
  return formatCurrency(convertToMajor(amountMinor, currency), currency);
82
128
  }
83
129
 
@@ -101,19 +147,155 @@ function getFirstAvailableFCId(variant, quantity = 1) {
101
147
  return inv?.location_id;
102
148
  }
103
149
 
150
+ // src/utils/durableRequest.ts
151
+ var DurableRequestStorageError = class extends Error {
152
+ constructor(message) {
153
+ super(message);
154
+ this.name = "DurableRequestStorageError";
155
+ }
156
+ };
157
+ function unavailable(label, reason) {
158
+ return new DurableRequestStorageError(
159
+ `Cannot safely start ${label} because its durable request ${reason}`
160
+ );
161
+ }
162
+ function requestStorage(label) {
163
+ try {
164
+ const storage = globalThis.localStorage;
165
+ if (!storage) throw new Error("localStorage is unavailable");
166
+ return storage;
167
+ } catch {
168
+ throw unavailable(label, "storage is unavailable");
169
+ }
170
+ }
171
+ function readStoredRequest(storage, storageKey, label) {
172
+ let raw;
173
+ try {
174
+ raw = storage.getItem(storageKey);
175
+ } catch {
176
+ throw unavailable(label, "state cannot be read");
177
+ }
178
+ if (raw === null) return null;
179
+ let value;
180
+ try {
181
+ value = JSON.parse(raw);
182
+ } catch {
183
+ throw unavailable(label, "state is corrupt");
184
+ }
185
+ if (typeof value !== "object" || value === null || Object.keys(value).length !== 2 || typeof value.requestJson !== "string" || !value.requestJson || typeof value.id !== "string" || !value.id) {
186
+ throw unavailable(label, "state is invalid");
187
+ }
188
+ try {
189
+ JSON.parse(value.requestJson);
190
+ } catch {
191
+ throw unavailable(label, "payload is corrupt");
192
+ }
193
+ return value;
194
+ }
195
+ function serializeRequest(request, label) {
196
+ try {
197
+ const serialized = JSON.stringify(request);
198
+ if (!serialized) throw new Error("Request is not JSON serializable");
199
+ return serialized;
200
+ } catch {
201
+ throw unavailable(label, "payload cannot be persisted");
202
+ }
203
+ }
204
+ function readDurableRequest(storageKey, label) {
205
+ const stored = readStoredRequest(requestStorage(label), storageKey, label);
206
+ return stored ? { storageKey, ...stored } : null;
207
+ }
208
+ function durableRequestPayload(request) {
209
+ return JSON.parse(request.requestJson);
210
+ }
211
+ async function withDurableRequestLock(storageKey, label, task) {
212
+ let locks;
213
+ try {
214
+ locks = globalThis.navigator.locks;
215
+ if (!locks) throw new Error("Web Locks are unavailable");
216
+ } catch {
217
+ throw unavailable(label, "cross-tab lock is unavailable");
218
+ }
219
+ let callbackEntered = false;
220
+ try {
221
+ return await locks.request(
222
+ `arky:durable-request:${storageKey}`,
223
+ { mode: "exclusive", ifAvailable: true },
224
+ async (lock) => {
225
+ callbackEntered = true;
226
+ if (!lock) {
227
+ throw unavailable(label, "is already active in another tab");
228
+ }
229
+ return task();
230
+ }
231
+ );
232
+ } catch (error) {
233
+ if (callbackEntered) throw error;
234
+ throw unavailable(label, "cross-tab lock could not be acquired");
235
+ }
236
+ }
237
+ function getOrCreateDurableRequest(storageKey, payload, label) {
238
+ const storage = requestStorage(label);
239
+ const requestJson = serializeRequest(payload, label);
240
+ const stored = readStoredRequest(storage, storageKey, label);
241
+ if (stored) {
242
+ if (stored.requestJson !== requestJson) {
243
+ throw unavailable(label, "has a different unresolved payload");
244
+ }
245
+ return { storageKey, ...stored };
246
+ }
247
+ const request = {
248
+ requestJson,
249
+ id: crypto.randomUUID()
250
+ };
251
+ try {
252
+ storage.setItem(storageKey, JSON.stringify(request));
253
+ } catch {
254
+ throw unavailable(label, "state cannot be saved");
255
+ }
256
+ const persisted = readStoredRequest(storage, storageKey, label);
257
+ if (persisted?.requestJson !== request.requestJson || persisted.id !== request.id) {
258
+ throw unavailable(label, "state was not saved exactly");
259
+ }
260
+ return { storageKey, ...request };
261
+ }
262
+ function clearDurableRequest(request, label) {
263
+ const storage = requestStorage(label);
264
+ const stored = readStoredRequest(storage, request.storageKey, label);
265
+ if (stored?.requestJson !== request.requestJson || stored.id !== request.id) {
266
+ throw unavailable(label, "state changed before it could be cleared");
267
+ }
268
+ try {
269
+ storage.removeItem(request.storageKey);
270
+ } catch {
271
+ throw unavailable(label, "state could not be cleared");
272
+ }
273
+ if (readStoredRequest(storage, request.storageKey, label) !== null) {
274
+ throw unavailable(label, "state was not cleared");
275
+ }
276
+ }
277
+
278
+ exports.DurableRequestStorageError = DurableRequestStorageError;
279
+ exports.SUPPORTED_STORE_CURRENCIES = SUPPORTED_STORE_CURRENCIES;
280
+ exports.clearDurableRequest = clearDurableRequest;
104
281
  exports.convertToMajor = convertToMajor;
105
282
  exports.convertToMinor = convertToMinor;
283
+ exports.durableRequestPayload = durableRequestPayload;
106
284
  exports.formatMinor = formatMinor;
107
285
  exports.getAvailableStock = getAvailableStock;
286
+ exports.getCurrencyMinorUnits = getCurrencyMinorUnits;
108
287
  exports.getCurrencyName = getCurrencyName;
109
288
  exports.getCurrencySymbol = getCurrencySymbol;
110
289
  exports.getFirstAvailableFCId = getFirstAvailableFCId;
111
290
  exports.getInventoryAt = getInventoryAt;
291
+ exports.getOrCreateDurableRequest = getOrCreateDurableRequest;
112
292
  exports.getReservedStock = getReservedStock;
113
293
  exports.hasStock = hasStock;
114
294
  exports.isValidKey = isValidKey;
115
295
  exports.nameToKey = nameToKey;
296
+ exports.readDurableRequest = readDurableRequest;
116
297
  exports.toKey = toKey;
117
298
  exports.validateKey = validateKey;
299
+ exports.withDurableRequestLock = withDurableRequestLock;
118
300
  //# sourceMappingURL=utils.cjs.map
119
301
  //# sourceMappingURL=utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/keyValidation.ts","../src/utils/price.ts","../src/utils/inventory.ts"],"names":[],"mappings":"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","file":"utils.cjs","sourcesContent":["\nconst KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;\n\nexport function isValidKey(key: string): boolean {\n if (!key || key.length === 0) return false;\n return KEY_PATTERN.test(key);\n}\n\nexport function validateKey(key: string): { valid: boolean; error?: string } {\n if (!key || key.length === 0) {\n return { valid: false, error: \"Key is required\" };\n }\n\n if (key.length > 255) {\n return { valid: false, error: \"Key must be 255 characters or less\" };\n }\n\n if (!KEY_PATTERN.test(key)) {\n return {\n valid: false,\n error:\n \"Key can only contain letters, numbers, underscores (_) and hyphens (-)\",\n };\n }\n\n return { valid: true };\n}\n\nexport function toKey(input: string): string {\n if (!input) return \"\";\n\n return input\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, \"_\")\n .replace(/[^a-z0-9_-]/g, \"\")\n .replace(/^[-_]+|[-_]+$/g, \"\")\n .replace(/[-_]{2,}/g, \"_\");\n}\n\nexport function nameToKey(name: string): string {\n return toKey(name);\n}\n","import type { OrderPayment, Price } from '../types';\n\ntype AnyPayment = Pick<OrderPayment, 'total' | 'currency'>;\n\nfunction formatCurrency(amount: number, currencyCode: string, locale: string = 'en'): string {\n if (!currencyCode) return '';\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: currencyCode.toUpperCase(),\n }).format(amount);\n}\n\nfunction getMinorUnits(currency: string): number {\n try {\n const formatter = new Intl.NumberFormat('en', {\n style: 'currency',\n currency: currency.toUpperCase(),\n });\n const parts = formatter.formatToParts(1.11);\n const fractionPart = parts.find(p => p.type === 'fraction');\n return fractionPart?.value.length ?? 2;\n } catch {\n return 2;\n }\n}\n\nexport function convertToMajor(minorAmount: number, currency: string): number {\n const units = getMinorUnits(currency);\n return minorAmount / Math.pow(10, units);\n}\n\nexport function convertToMinor(majorAmount: number, currency: string): number {\n const units = getMinorUnits(currency);\n return Math.round(majorAmount * Math.pow(10, units));\n}\n\nexport function getCurrencySymbol(currency: string): string {\n try {\n return new Intl.NumberFormat('en', {\n style: 'currency',\n currency: currency.toUpperCase(),\n currencyDisplay: 'narrowSymbol'\n }).formatToParts(0).find(p => p.type === 'currency')?.value || currency.toUpperCase();\n } catch {\n return currency.toUpperCase();\n }\n}\n\nexport function getCurrencyName(currency: string): string {\n try {\n return new Intl.DisplayNames(['en'], { type: 'currency' }).of(currency.toUpperCase()) || currency.toUpperCase();\n } catch {\n return currency.toUpperCase();\n }\n}\n\nexport function formatMinor(amountMinor: number, currency: string): string {\n if (!currency) return '';\n return formatCurrency(convertToMajor(amountMinor, currency), currency);\n}\n\nexport function formatPayment(payment: AnyPayment): string {\n return formatMinor(payment.total, payment.currency);\n}\n\nexport function formatPrice(prices: Price[], marketId?: string): string {\n if (!prices || prices.length === 0) return '';\n\n const price = marketId\n ? prices.find(p => p.market === marketId) || prices[0]\n : prices[0];\n\n if (!price) return '';\n\n return formatMinor(price.amount, price.currency);\n}\n\nexport function getPriceAmount(prices: Price[], marketId: string): number {\n if (!prices || prices.length === 0) return 0;\n const price = prices.find(p => p.market === marketId) || prices[0];\n return price?.amount || 0;\n}\n","import type { InventoryLevel, Location } from '../types';\n\nexport interface VariantWithInventory {\n inventory: InventoryLevel[];\n}\n\n\nexport function getAvailableStock(variant: VariantWithInventory): number {\n if (!variant?.inventory) return 0;\n return variant.inventory.reduce((sum, inv) => sum + inv.available, 0);\n}\n\n\nexport function getReservedStock(variant: VariantWithInventory): number {\n if (!variant?.inventory) return 0;\n return variant.inventory.reduce((sum, inv) => sum + inv.reserved, 0);\n}\n\n\nexport function hasStock(variant: VariantWithInventory, quantity: number = 1): boolean {\n return getAvailableStock(variant) >= quantity;\n}\n\n\nexport function getInventoryAt(\n variant: VariantWithInventory,\n locationId: string\n): InventoryLevel | undefined {\n return variant?.inventory?.find(inv => inv.location_id === locationId);\n}\n\n\nexport function getFirstAvailableFCId(\n variant: VariantWithInventory,\n quantity: number = 1\n): string | undefined {\n const inv = variant?.inventory?.find(i => i.available >= quantity);\n return inv?.location_id;\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/keyValidation.ts","../src/utils/price.ts","../src/utils/inventory.ts","../src/utils/durableRequest.ts"],"names":[],"mappings":"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","file":"utils.cjs","sourcesContent":["\nconst KEY_PATTERN = /^[a-zA-Z0-9_-]+$/;\n\nexport function isValidKey(key: string): boolean {\n if (!key || key.length === 0) return false;\n return KEY_PATTERN.test(key);\n}\n\nexport function validateKey(key: string): { valid: boolean; error?: string } {\n if (!key || key.length === 0) {\n return { valid: false, error: \"Key is required\" };\n }\n\n if (key.length > 255) {\n return { valid: false, error: \"Key must be 255 characters or less\" };\n }\n\n if (!KEY_PATTERN.test(key)) {\n return {\n valid: false,\n error:\n \"Key can only contain letters, numbers, underscores (_) and hyphens (-)\",\n };\n }\n\n return { valid: true };\n}\n\nexport function toKey(input: string): string {\n if (!input) return \"\";\n\n return input\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, \"_\")\n .replace(/[^a-z0-9_-]/g, \"\")\n .replace(/^[-_]+|[-_]+$/g, \"\")\n .replace(/[-_]{2,}/g, \"_\");\n}\n\nexport function nameToKey(name: string): string {\n return toKey(name);\n}\n","import type { OrderMoney, Price } from '../types';\n\ntype OrderTotal = Pick<OrderMoney, 'total' | 'currency'>;\n\nexport const SUPPORTED_STORE_CURRENCIES = Object.freeze([\n 'USD', 'EUR', 'GBP', 'JPY', 'CNY', 'CHF', 'AUD', 'CAD', 'HKD', 'SGD',\n 'NZD', 'KRW', 'SEK', 'NOK', 'DKK', 'INR', 'MXN', 'BRL', 'ZAR', 'RUB',\n 'TRY', 'PLN', 'THB', 'IDR', 'MYR', 'PHP', 'CZK', 'ILS', 'AED', 'SAR',\n 'HUF', 'RON', 'BGN', 'HRK', 'BAM', 'RSD', 'MKD', 'ALL',\n] as const);\n\nconst SUPPORTED_STORE_CURRENCY_SET: ReadonlySet<string> = Object.freeze(\n new Set<string>(SUPPORTED_STORE_CURRENCIES),\n);\n\nconst ZERO_MINOR_UNIT_STORE_CURRENCIES: ReadonlySet<string> = Object.freeze(\n new Set<string>(['JPY', 'KRW']),\n);\n\nfunction formatCurrency(amount: number, currencyCode: string, locale: string = 'en'): string {\n const normalized = currencyCode.trim().toUpperCase();\n if (!normalized) return '';\n const minorUnits = getCurrencyMinorUnits(normalized);\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: normalized,\n minimumFractionDigits: minorUnits,\n maximumFractionDigits: minorUnits,\n }).format(amount);\n}\n\nexport function getCurrencyMinorUnits(currency: string): number {\n const normalized = currency.trim().toUpperCase();\n if (!SUPPORTED_STORE_CURRENCY_SET.has(normalized)) {\n throw new RangeError(`Unsupported currency '${currency}'`);\n }\n return ZERO_MINOR_UNIT_STORE_CURRENCIES.has(normalized) ? 0 : 2;\n}\n\nexport function convertToMajor(minorAmount: number, currency: string): number {\n const units = getCurrencyMinorUnits(currency);\n return minorAmount / Math.pow(10, units);\n}\n\nexport function convertToMinor(majorAmount: number, currency: string): number {\n const units = getCurrencyMinorUnits(currency);\n return Math.round(majorAmount * Math.pow(10, units));\n}\n\nexport function getCurrencySymbol(currency: string): string {\n try {\n return new Intl.NumberFormat('en', {\n style: 'currency',\n currency: currency.toUpperCase(),\n currencyDisplay: 'narrowSymbol'\n }).formatToParts(0).find(p => p.type === 'currency')?.value || currency.toUpperCase();\n } catch {\n return currency.toUpperCase();\n }\n}\n\nexport function getCurrencyName(currency: string): string {\n try {\n return new Intl.DisplayNames(['en'], { type: 'currency' }).of(currency.toUpperCase()) || currency.toUpperCase();\n } catch {\n return currency.toUpperCase();\n }\n}\n\nexport function formatMinor(amountMinor: number, currency: string): string {\n if (!Number.isSafeInteger(amountMinor)) {\n throw new RangeError('Minor-unit amount must be a safe integer');\n }\n return formatCurrency(convertToMajor(amountMinor, currency), currency);\n}\n\nexport function formatPayment(payment: OrderTotal): string {\n return formatMinor(payment.total, payment.currency);\n}\n\nexport function formatPrice(prices: Price[], marketId?: string): string {\n if (!prices || prices.length === 0 || !marketId) return '';\n\n const price = prices.find(p => p.market === marketId);\n if (!price || !Number.isSafeInteger(price.amount) || price.amount < 0 || !price.currency) return '';\n\n return formatMinor(price.amount, price.currency);\n}\n\nexport function getPriceAmount(prices: Price[], marketId: string): number | null {\n if (!prices || prices.length === 0 || !marketId) return null;\n const price = prices.find(p => p.market === marketId);\n return price && Number.isSafeInteger(price.amount) && price.amount >= 0 ? price.amount : null;\n}\n","import type { InventoryLevel, Location } from '../types';\n\nexport interface VariantWithInventory {\n inventory: InventoryLevel[];\n}\n\n\nexport function getAvailableStock(variant: VariantWithInventory): number {\n if (!variant?.inventory) return 0;\n return variant.inventory.reduce((sum, inv) => sum + inv.available, 0);\n}\n\n\nexport function getReservedStock(variant: VariantWithInventory): number {\n if (!variant?.inventory) return 0;\n return variant.inventory.reduce((sum, inv) => sum + inv.reserved, 0);\n}\n\n\nexport function hasStock(variant: VariantWithInventory, quantity: number = 1): boolean {\n return getAvailableStock(variant) >= quantity;\n}\n\n\nexport function getInventoryAt(\n variant: VariantWithInventory,\n locationId: string\n): InventoryLevel | undefined {\n return variant?.inventory?.find(inv => inv.location_id === locationId);\n}\n\n\nexport function getFirstAvailableFCId(\n variant: VariantWithInventory,\n quantity: number = 1\n): string | undefined {\n const inv = variant?.inventory?.find(i => i.available >= quantity);\n return inv?.location_id;\n}\n","export interface DurableRequest {\n storageKey: string;\n requestJson: string;\n id: string;\n}\n\ntype StoredDurableRequest = Omit<DurableRequest, \"storageKey\">;\n\nexport class DurableRequestStorageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DurableRequestStorageError\";\n }\n}\n\nfunction unavailable(label: string, reason: string): DurableRequestStorageError {\n return new DurableRequestStorageError(\n `Cannot safely start ${label} because its durable request ${reason}`,\n );\n}\n\nfunction requestStorage(label: string): Storage {\n try {\n const storage = globalThis.localStorage;\n if (!storage) throw new Error(\"localStorage is unavailable\");\n return storage;\n } catch {\n throw unavailable(label, \"storage is unavailable\");\n }\n}\n\nfunction readStoredRequest(\n storage: Storage,\n storageKey: string,\n label: string,\n): StoredDurableRequest | null {\n let raw: string | null;\n try {\n raw = storage.getItem(storageKey);\n } catch {\n throw unavailable(label, \"state cannot be read\");\n }\n if (raw === null) return null;\n\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n throw unavailable(label, \"state is corrupt\");\n }\n if (\n typeof value !== \"object\" ||\n value === null ||\n Object.keys(value).length !== 2 ||\n typeof (value as Record<string, unknown>).requestJson !== \"string\" ||\n !(value as Record<string, unknown>).requestJson ||\n typeof (value as Record<string, unknown>).id !== \"string\" ||\n !(value as Record<string, unknown>).id\n ) {\n throw unavailable(label, \"state is invalid\");\n }\n try {\n JSON.parse((value as Record<string, string>).requestJson);\n } catch {\n throw unavailable(label, \"payload is corrupt\");\n }\n return value as StoredDurableRequest;\n}\n\nfunction serializeRequest(request: unknown, label: string): string {\n try {\n const serialized = JSON.stringify(request);\n if (!serialized) throw new Error(\"Request is not JSON serializable\");\n return serialized;\n } catch {\n throw unavailable(label, \"payload cannot be persisted\");\n }\n}\n\nexport function readDurableRequest(\n storageKey: string,\n label: string,\n): DurableRequest | null {\n const stored = readStoredRequest(requestStorage(label), storageKey, label);\n return stored ? { storageKey, ...stored } : null;\n}\n\nexport function durableRequestPayload(request: DurableRequest): unknown {\n return JSON.parse(request.requestJson);\n}\n\nexport async function withDurableRequestLock<T>(\n storageKey: string,\n label: string,\n task: () => Promise<T>,\n): Promise<T> {\n let locks: LockManager;\n try {\n locks = globalThis.navigator.locks;\n if (!locks) throw new Error(\"Web Locks are unavailable\");\n } catch {\n throw unavailable(label, \"cross-tab lock is unavailable\");\n }\n\n let callbackEntered = false;\n try {\n return await locks.request(\n `arky:durable-request:${storageKey}`,\n { mode: \"exclusive\", ifAvailable: true },\n async (lock) => {\n callbackEntered = true;\n if (!lock) {\n throw unavailable(label, \"is already active in another tab\");\n }\n return task();\n },\n );\n } catch (error) {\n if (callbackEntered) throw error;\n throw unavailable(label, \"cross-tab lock could not be acquired\");\n }\n}\n\nexport function getOrCreateDurableRequest(\n storageKey: string,\n payload: unknown,\n label: string,\n): DurableRequest {\n const storage = requestStorage(label);\n const requestJson = serializeRequest(payload, label);\n const stored = readStoredRequest(storage, storageKey, label);\n if (stored) {\n if (stored.requestJson !== requestJson) {\n throw unavailable(label, \"has a different unresolved payload\");\n }\n return { storageKey, ...stored };\n }\n\n const request: StoredDurableRequest = {\n requestJson,\n id: crypto.randomUUID(),\n };\n try {\n storage.setItem(storageKey, JSON.stringify(request));\n } catch {\n throw unavailable(label, \"state cannot be saved\");\n }\n const persisted = readStoredRequest(storage, storageKey, label);\n if (persisted?.requestJson !== request.requestJson || persisted.id !== request.id) {\n throw unavailable(label, \"state was not saved exactly\");\n }\n return { storageKey, ...request };\n}\n\nexport function clearDurableRequest(request: DurableRequest, label: string): void {\n const storage = requestStorage(label);\n const stored = readStoredRequest(storage, request.storageKey, label);\n if (\n stored?.requestJson !== request.requestJson ||\n stored.id !== request.id\n ) {\n throw unavailable(label, \"state changed before it could be cleared\");\n }\n try {\n storage.removeItem(request.storageKey);\n } catch {\n throw unavailable(label, \"state could not be cleared\");\n }\n if (readStoredRequest(storage, request.storageKey, label) !== null) {\n throw unavailable(label, \"state was not cleared\");\n }\n}\n"]}
package/dist/utils.d.cts CHANGED
@@ -1,2 +1,18 @@
1
- export { k as convertToMajor, l as convertToMinor, a as formatMinor, c as getAvailableStock, b as getCurrencyName, g as getCurrencySymbol, j as getFirstAvailableFCId, e as getInventoryAt, d as getReservedStock, h as hasStock, i as isValidKey, n as nameToKey, t as toKey, v as validateKey } from './index-BC06yiuv.cjs';
2
- import './api-DvsFdOaF.cjs';
1
+ export { S as SUPPORTED_STORE_CURRENCIES, c as convertToMajor, b as convertToMinor, f as formatMinor, e as getAvailableStock, d as getCurrencyMinorUnits, a as getCurrencyName, g as getCurrencySymbol, l as getFirstAvailableFCId, k as getInventoryAt, h as getReservedStock, j as hasStock, i as isValidKey, n as nameToKey, t as toKey, v as validateKey } from './inventory-DdN96PX3.cjs';
2
+ import './api-D37IpMSq.cjs';
3
+
4
+ interface DurableRequest {
5
+ storageKey: string;
6
+ requestJson: string;
7
+ id: string;
8
+ }
9
+ declare class DurableRequestStorageError extends Error {
10
+ constructor(message: string);
11
+ }
12
+ declare function readDurableRequest(storageKey: string, label: string): DurableRequest | null;
13
+ declare function durableRequestPayload(request: DurableRequest): unknown;
14
+ declare function withDurableRequestLock<T>(storageKey: string, label: string, task: () => Promise<T>): Promise<T>;
15
+ declare function getOrCreateDurableRequest(storageKey: string, payload: unknown, label: string): DurableRequest;
16
+ declare function clearDurableRequest(request: DurableRequest, label: string): void;
17
+
18
+ export { type DurableRequest, DurableRequestStorageError, clearDurableRequest, durableRequestPayload, getOrCreateDurableRequest, readDurableRequest, withDurableRequestLock };
package/dist/utils.d.ts CHANGED
@@ -1,2 +1,18 @@
1
- export { k as convertToMajor, l as convertToMinor, a as formatMinor, c as getAvailableStock, b as getCurrencyName, g as getCurrencySymbol, j as getFirstAvailableFCId, e as getInventoryAt, d as getReservedStock, h as hasStock, i as isValidKey, n as nameToKey, t as toKey, v as validateKey } from './index-CQd9b_7n.js';
2
- import './api-DvsFdOaF.js';
1
+ export { S as SUPPORTED_STORE_CURRENCIES, c as convertToMajor, b as convertToMinor, f as formatMinor, e as getAvailableStock, d as getCurrencyMinorUnits, a as getCurrencyName, g as getCurrencySymbol, l as getFirstAvailableFCId, k as getInventoryAt, h as getReservedStock, j as hasStock, i as isValidKey, n as nameToKey, t as toKey, v as validateKey } from './inventory-Dh1RevEb.js';
2
+ import './api-D37IpMSq.js';
3
+
4
+ interface DurableRequest {
5
+ storageKey: string;
6
+ requestJson: string;
7
+ id: string;
8
+ }
9
+ declare class DurableRequestStorageError extends Error {
10
+ constructor(message: string);
11
+ }
12
+ declare function readDurableRequest(storageKey: string, label: string): DurableRequest | null;
13
+ declare function durableRequestPayload(request: DurableRequest): unknown;
14
+ declare function withDurableRequestLock<T>(storageKey: string, label: string, task: () => Promise<T>): Promise<T>;
15
+ declare function getOrCreateDurableRequest(storageKey: string, payload: unknown, label: string): DurableRequest;
16
+ declare function clearDurableRequest(request: DurableRequest, label: string): void;
17
+
18
+ export { type DurableRequest, DurableRequestStorageError, clearDurableRequest, durableRequestPayload, getOrCreateDurableRequest, readDurableRequest, withDurableRequestLock };
package/dist/utils.js CHANGED
@@ -28,32 +28,76 @@ function nameToKey(name) {
28
28
  }
29
29
 
30
30
  // src/utils/price.ts
31
+ var SUPPORTED_STORE_CURRENCIES = Object.freeze([
32
+ "USD",
33
+ "EUR",
34
+ "GBP",
35
+ "JPY",
36
+ "CNY",
37
+ "CHF",
38
+ "AUD",
39
+ "CAD",
40
+ "HKD",
41
+ "SGD",
42
+ "NZD",
43
+ "KRW",
44
+ "SEK",
45
+ "NOK",
46
+ "DKK",
47
+ "INR",
48
+ "MXN",
49
+ "BRL",
50
+ "ZAR",
51
+ "RUB",
52
+ "TRY",
53
+ "PLN",
54
+ "THB",
55
+ "IDR",
56
+ "MYR",
57
+ "PHP",
58
+ "CZK",
59
+ "ILS",
60
+ "AED",
61
+ "SAR",
62
+ "HUF",
63
+ "RON",
64
+ "BGN",
65
+ "HRK",
66
+ "BAM",
67
+ "RSD",
68
+ "MKD",
69
+ "ALL"
70
+ ]);
71
+ var SUPPORTED_STORE_CURRENCY_SET = Object.freeze(
72
+ new Set(SUPPORTED_STORE_CURRENCIES)
73
+ );
74
+ var ZERO_MINOR_UNIT_STORE_CURRENCIES = Object.freeze(
75
+ /* @__PURE__ */ new Set(["JPY", "KRW"])
76
+ );
31
77
  function formatCurrency(amount, currencyCode, locale = "en") {
32
- if (!currencyCode) return "";
78
+ const normalized = currencyCode.trim().toUpperCase();
79
+ if (!normalized) return "";
80
+ const minorUnits = getCurrencyMinorUnits(normalized);
33
81
  return new Intl.NumberFormat(locale, {
34
82
  style: "currency",
35
- currency: currencyCode.toUpperCase()
83
+ currency: normalized,
84
+ minimumFractionDigits: minorUnits,
85
+ maximumFractionDigits: minorUnits
36
86
  }).format(amount);
37
87
  }
38
- function getMinorUnits(currency) {
39
- try {
40
- const formatter = new Intl.NumberFormat("en", {
41
- style: "currency",
42
- currency: currency.toUpperCase()
43
- });
44
- const parts = formatter.formatToParts(1.11);
45
- const fractionPart = parts.find((p) => p.type === "fraction");
46
- return fractionPart?.value.length ?? 2;
47
- } catch {
48
- return 2;
88
+ function getCurrencyMinorUnits(currency) {
89
+ const normalized = currency.trim().toUpperCase();
90
+ if (!SUPPORTED_STORE_CURRENCY_SET.has(normalized)) {
91
+ throw new RangeError(`Unsupported currency '${currency}'`);
49
92
  }
93
+ return ZERO_MINOR_UNIT_STORE_CURRENCIES.has(normalized) ? 0 : 2;
50
94
  }
51
95
  function convertToMajor(minorAmount, currency) {
52
- const units = getMinorUnits(currency);
96
+ const units = getCurrencyMinorUnits(currency);
53
97
  return minorAmount / Math.pow(10, units);
54
98
  }
55
99
  function convertToMinor(majorAmount, currency) {
56
- const units = getMinorUnits(currency);
100
+ const units = getCurrencyMinorUnits(currency);
57
101
  return Math.round(majorAmount * Math.pow(10, units));
58
102
  }
59
103
  function getCurrencySymbol(currency) {
@@ -75,7 +119,9 @@ function getCurrencyName(currency) {
75
119
  }
76
120
  }
77
121
  function formatMinor(amountMinor, currency) {
78
- if (!currency) return "";
122
+ if (!Number.isSafeInteger(amountMinor)) {
123
+ throw new RangeError("Minor-unit amount must be a safe integer");
124
+ }
79
125
  return formatCurrency(convertToMajor(amountMinor, currency), currency);
80
126
  }
81
127
 
@@ -99,6 +145,134 @@ function getFirstAvailableFCId(variant, quantity = 1) {
99
145
  return inv?.location_id;
100
146
  }
101
147
 
102
- export { convertToMajor, convertToMinor, formatMinor, getAvailableStock, getCurrencyName, getCurrencySymbol, getFirstAvailableFCId, getInventoryAt, getReservedStock, hasStock, isValidKey, nameToKey, toKey, validateKey };
148
+ // src/utils/durableRequest.ts
149
+ var DurableRequestStorageError = class extends Error {
150
+ constructor(message) {
151
+ super(message);
152
+ this.name = "DurableRequestStorageError";
153
+ }
154
+ };
155
+ function unavailable(label, reason) {
156
+ return new DurableRequestStorageError(
157
+ `Cannot safely start ${label} because its durable request ${reason}`
158
+ );
159
+ }
160
+ function requestStorage(label) {
161
+ try {
162
+ const storage = globalThis.localStorage;
163
+ if (!storage) throw new Error("localStorage is unavailable");
164
+ return storage;
165
+ } catch {
166
+ throw unavailable(label, "storage is unavailable");
167
+ }
168
+ }
169
+ function readStoredRequest(storage, storageKey, label) {
170
+ let raw;
171
+ try {
172
+ raw = storage.getItem(storageKey);
173
+ } catch {
174
+ throw unavailable(label, "state cannot be read");
175
+ }
176
+ if (raw === null) return null;
177
+ let value;
178
+ try {
179
+ value = JSON.parse(raw);
180
+ } catch {
181
+ throw unavailable(label, "state is corrupt");
182
+ }
183
+ if (typeof value !== "object" || value === null || Object.keys(value).length !== 2 || typeof value.requestJson !== "string" || !value.requestJson || typeof value.id !== "string" || !value.id) {
184
+ throw unavailable(label, "state is invalid");
185
+ }
186
+ try {
187
+ JSON.parse(value.requestJson);
188
+ } catch {
189
+ throw unavailable(label, "payload is corrupt");
190
+ }
191
+ return value;
192
+ }
193
+ function serializeRequest(request, label) {
194
+ try {
195
+ const serialized = JSON.stringify(request);
196
+ if (!serialized) throw new Error("Request is not JSON serializable");
197
+ return serialized;
198
+ } catch {
199
+ throw unavailable(label, "payload cannot be persisted");
200
+ }
201
+ }
202
+ function readDurableRequest(storageKey, label) {
203
+ const stored = readStoredRequest(requestStorage(label), storageKey, label);
204
+ return stored ? { storageKey, ...stored } : null;
205
+ }
206
+ function durableRequestPayload(request) {
207
+ return JSON.parse(request.requestJson);
208
+ }
209
+ async function withDurableRequestLock(storageKey, label, task) {
210
+ let locks;
211
+ try {
212
+ locks = globalThis.navigator.locks;
213
+ if (!locks) throw new Error("Web Locks are unavailable");
214
+ } catch {
215
+ throw unavailable(label, "cross-tab lock is unavailable");
216
+ }
217
+ let callbackEntered = false;
218
+ try {
219
+ return await locks.request(
220
+ `arky:durable-request:${storageKey}`,
221
+ { mode: "exclusive", ifAvailable: true },
222
+ async (lock) => {
223
+ callbackEntered = true;
224
+ if (!lock) {
225
+ throw unavailable(label, "is already active in another tab");
226
+ }
227
+ return task();
228
+ }
229
+ );
230
+ } catch (error) {
231
+ if (callbackEntered) throw error;
232
+ throw unavailable(label, "cross-tab lock could not be acquired");
233
+ }
234
+ }
235
+ function getOrCreateDurableRequest(storageKey, payload, label) {
236
+ const storage = requestStorage(label);
237
+ const requestJson = serializeRequest(payload, label);
238
+ const stored = readStoredRequest(storage, storageKey, label);
239
+ if (stored) {
240
+ if (stored.requestJson !== requestJson) {
241
+ throw unavailable(label, "has a different unresolved payload");
242
+ }
243
+ return { storageKey, ...stored };
244
+ }
245
+ const request = {
246
+ requestJson,
247
+ id: crypto.randomUUID()
248
+ };
249
+ try {
250
+ storage.setItem(storageKey, JSON.stringify(request));
251
+ } catch {
252
+ throw unavailable(label, "state cannot be saved");
253
+ }
254
+ const persisted = readStoredRequest(storage, storageKey, label);
255
+ if (persisted?.requestJson !== request.requestJson || persisted.id !== request.id) {
256
+ throw unavailable(label, "state was not saved exactly");
257
+ }
258
+ return { storageKey, ...request };
259
+ }
260
+ function clearDurableRequest(request, label) {
261
+ const storage = requestStorage(label);
262
+ const stored = readStoredRequest(storage, request.storageKey, label);
263
+ if (stored?.requestJson !== request.requestJson || stored.id !== request.id) {
264
+ throw unavailable(label, "state changed before it could be cleared");
265
+ }
266
+ try {
267
+ storage.removeItem(request.storageKey);
268
+ } catch {
269
+ throw unavailable(label, "state could not be cleared");
270
+ }
271
+ if (readStoredRequest(storage, request.storageKey, label) !== null) {
272
+ throw unavailable(label, "state was not cleared");
273
+ }
274
+ }
275
+
276
+ export { DurableRequestStorageError, SUPPORTED_STORE_CURRENCIES, clearDurableRequest, convertToMajor, convertToMinor, durableRequestPayload, formatMinor, getAvailableStock, getCurrencyMinorUnits, getCurrencyName, getCurrencySymbol, getFirstAvailableFCId, getInventoryAt, getOrCreateDurableRequest, getReservedStock, hasStock, isValidKey, nameToKey, readDurableRequest, toKey, validateKey, withDurableRequestLock };
103
277
  //# sourceMappingURL=utils.js.map
104
278
  //# sourceMappingURL=utils.js.map