@final-commerce/common 2.5.0 → 2.5.1-online.2

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/dist/index.js CHANGED
@@ -20,12 +20,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  var index_exports = {};
21
21
  __export(index_exports, {
22
22
  ADYEN_ROLLOUT_COUNTRY_CODES: () => ADYEN_ROLLOUT_COUNTRY_CODES,
23
+ AFFIRM_COUNTRY_CODES: () => AFFIRM_COUNTRY_CODES,
24
+ AFFIRM_PRICE_PLANS: () => AFFIRM_PRICE_PLANS,
23
25
  AttributeType: () => AttributeType,
26
+ BNPL_METHOD_STATUS: () => BNPL_METHOD_STATUS,
27
+ BNPL_SKIP_REASON: () => BNPL_SKIP_REASON,
24
28
  BookingRatePeriod: () => BookingRatePeriod,
25
29
  BookingResourceKind: () => BookingResourceKind,
26
30
  BookingResourceStatus: () => BookingResourceStatus,
27
31
  BookingRulesError: () => BookingRulesError,
28
32
  BookingType: () => BookingType,
33
+ CANADA_PROVINCES: () => CANADA_PROVINCES,
29
34
  CONDITION_OPERATORS: () => CONDITION_OPERATORS,
30
35
  COUNTRY_CURRENCIES: () => COUNTRY_CURRENCIES,
31
36
  CURRENCY_CONFIG: () => CURRENCY_CONFIG,
@@ -42,6 +47,7 @@ __export(index_exports, {
42
47
  DualWriteStrategy: () => DualWriteStrategy,
43
48
  EUFixedRates: () => EUFixedRates,
44
49
  EUROPE: () => EUROPE,
50
+ EVERYWHERE_KEY: () => EVERYWHERE_KEY,
45
51
  ExtensionCategory: () => ExtensionCategory,
46
52
  FINANCIAL_INVARIANTS: () => FINANCIAL_INVARIANTS,
47
53
  FULFILLMENT_STATES: () => FULFILLMENT_STATES,
@@ -63,6 +69,7 @@ __export(index_exports, {
63
69
  OtherFixedRates: () => OtherFixedRates,
64
70
  OwnerType: () => OwnerType,
65
71
  PATH_MODES: () => PATH_MODES,
72
+ PAYMENT_CHANNELS: () => PAYMENT_CHANNELS,
66
73
  PAYMENT_STATES: () => PAYMENT_STATES,
67
74
  POS_VALID_INITIAL_STATES: () => POS_VALID_INITIAL_STATES,
68
75
  PaymentMethod: () => PaymentMethod,
@@ -72,6 +79,7 @@ __export(index_exports, {
72
79
  PricingLevel: () => PricingLevel,
73
80
  PricingPlanEnum: () => PricingPlanEnum,
74
81
  PricingRegionEnum: () => PricingRegionEnum,
82
+ ProcessorType: () => ProcessorType,
75
83
  ProductStatus: () => ProductStatus,
76
84
  ProductType: () => ProductType,
77
85
  PublicationAvailability: () => PublicationAvailability,
@@ -90,6 +98,12 @@ __export(index_exports, {
90
98
  SYSTEM_FAMILY_IDS: () => SYSTEM_FAMILY_IDS,
91
99
  SYSTEM_UNITS: () => SYSTEM_UNITS,
92
100
  SYSTEM_UNIT_IDS: () => SYSTEM_UNIT_IDS,
101
+ ShippingChannel: () => ShippingChannel,
102
+ ShippingNoOptionReason: () => ShippingNoOptionReason,
103
+ ShippingOptionType: () => ShippingOptionType,
104
+ ShippingRateType: () => ShippingRateType,
105
+ ShippingZoneError: () => ShippingZoneError,
106
+ ShippingZoneKind: () => ShippingZoneKind,
93
107
  StationStatus: () => StationStatus,
94
108
  StripeCurrencyCode: () => StripeCurrencyCode,
95
109
  StripeStatus: () => StripeStatus,
@@ -97,6 +111,7 @@ __export(index_exports, {
97
111
  TopMetericsSort: () => TopMetericsSort,
98
112
  UserTypes: () => UserTypes,
99
113
  addAmounts: () => addAmounts,
114
+ addressPlaceKeys: () => addressPlaceKeys,
100
115
  amountToString: () => amountToString,
101
116
  assertUnitSane: () => assertUnitSane,
102
117
  availableIn: () => availableIn,
@@ -148,6 +163,8 @@ __export(index_exports, {
148
163
  holdExpiresAt: () => holdExpiresAt,
149
164
  inferStatesFromLegacyStatus: () => inferStatesFromLegacyStatus,
150
165
  isAdyenRolloutCountry: () => isAdyenRolloutCountry,
166
+ isAffirmCountry: () => isAffirmCountry,
167
+ isAffirmPricePlan: () => isAffirmPricePlan,
151
168
  isConditionOperator: () => isConditionOperator,
152
169
  isFulfillmentState: () => isFulfillmentState,
153
170
  isPaymentState: () => isPaymentState,
@@ -155,19 +172,31 @@ __export(index_exports, {
155
172
  isSystemFamilyCode: () => isSystemFamilyCode,
156
173
  isValidQuantity: () => isValidQuantity,
157
174
  isWhole: () => isWhole,
175
+ listCountries: () => listCountries,
176
+ listProvinces: () => listProvinces,
158
177
  mapToLegacyStatus: () => mapToLegacyStatus,
159
178
  maxPrecisionFor: () => maxPrecisionFor,
160
179
  mergeFragment: () => mergeFragment,
161
180
  multiplyAmount: () => multiplyAmount,
181
+ normalizeAddress: () => normalizeAddress,
182
+ normalizeCityKey: () => normalizeCityKey,
183
+ normalizeCountry: () => normalizeCountry,
162
184
  normalizeMongoIdString: () => normalizeMongoIdString,
185
+ normalizePostCode: () => normalizePostCode,
186
+ normalizeProvince: () => normalizeProvince,
163
187
  occupancyIn: () => occupancyIn,
164
188
  parseAmountToMinorUnits: () => parseAmountToMinorUnits,
165
189
  parseCurrencyCode: () => parseCurrencyCode,
166
190
  parseStripeCurrencyCode: () => parseStripeCurrencyCode,
191
+ placeKey: () => placeKey,
167
192
  planWindow: () => planWindow,
193
+ postCodeMatchesProvince: () => postCodeMatchesProvince,
168
194
  presentAt: () => presentAt,
195
+ priceForTotal: () => priceForTotal,
196
+ provincesForPostCode: () => provincesForPostCode,
169
197
  removeFragment: () => removeFragment,
170
198
  resolveFamily: () => resolveFamily,
199
+ resolveShipping: () => resolveShipping,
171
200
  resolveTemplate: () => resolveTemplate,
172
201
  resolveUnit: () => resolveUnit,
173
202
  roundToPrecision: () => roundToPrecision,
@@ -183,6 +212,7 @@ __export(index_exports, {
183
212
  toMinorUnits: () => toMinorUnits,
184
213
  validateConfig: () => validateConfig,
185
214
  validateFragmentCompatibility: () => validateFragmentCompatibility,
215
+ validateShippingZone: () => validateShippingZone,
186
216
  violatesFinancialInvariant: () => violatesFinancialInvariant,
187
217
  windowEndsAt: () => windowEndsAt,
188
218
  withinPresence: () => withinPresence
@@ -391,6 +421,7 @@ var OrderPlatform = /* @__PURE__ */ ((OrderPlatform2) => {
391
421
  OrderPlatform2["POS"] = "in-store";
392
422
  OrderPlatform2["WOO_COMMERCE"] = "woo-commerce";
393
423
  OrderPlatform2["PUBLIC_API"] = "public-api";
424
+ OrderPlatform2["ONLINE_STORE"] = "online-store";
394
425
  return OrderPlatform2;
395
426
  })(OrderPlatform || {});
396
427
  var CustomerPlatform = /* @__PURE__ */ ((CustomerPlatform2) => {
@@ -676,6 +707,50 @@ var ResourceAvailabilityState = /* @__PURE__ */ ((ResourceAvailabilityState2) =>
676
707
  return ResourceAvailabilityState2;
677
708
  })(ResourceAvailabilityState || {});
678
709
 
710
+ // enums/shipping.enum.ts
711
+ var ShippingZoneKind = /* @__PURE__ */ ((ShippingZoneKind2) => {
712
+ ShippingZoneKind2["COUNTRY"] = "country";
713
+ ShippingZoneKind2["PROVINCE"] = "province";
714
+ ShippingZoneKind2["CITY"] = "city";
715
+ ShippingZoneKind2["EVERYWHERE"] = "everywhere";
716
+ return ShippingZoneKind2;
717
+ })(ShippingZoneKind || {});
718
+ var ShippingOptionType = /* @__PURE__ */ ((ShippingOptionType2) => {
719
+ ShippingOptionType2["SHIP"] = "ship";
720
+ ShippingOptionType2["PICKUP"] = "pickup";
721
+ return ShippingOptionType2;
722
+ })(ShippingOptionType || {});
723
+ var ShippingRateType = /* @__PURE__ */ ((ShippingRateType2) => {
724
+ ShippingRateType2["FLAT"] = "flat";
725
+ return ShippingRateType2;
726
+ })(ShippingRateType || {});
727
+ var ShippingChannel = /* @__PURE__ */ ((ShippingChannel2) => {
728
+ ShippingChannel2["WEB"] = "web";
729
+ ShippingChannel2["POS"] = "pos";
730
+ return ShippingChannel2;
731
+ })(ShippingChannel || {});
732
+ var ShippingNoOptionReason = /* @__PURE__ */ ((ShippingNoOptionReason2) => {
733
+ ShippingNoOptionReason2["INCOMPLETE"] = "INCOMPLETE";
734
+ ShippingNoOptionReason2["ADDRESS_MISMATCH"] = "ADDRESS_MISMATCH";
735
+ ShippingNoOptionReason2["NO_COVERAGE"] = "NO_COVERAGE";
736
+ ShippingNoOptionReason2["BLOCKED"] = "BLOCKED";
737
+ ShippingNoOptionReason2["NO_OPTION"] = "NO_OPTION";
738
+ return ShippingNoOptionReason2;
739
+ })(ShippingNoOptionReason || {});
740
+ var ShippingZoneError = /* @__PURE__ */ ((ShippingZoneError2) => {
741
+ ShippingZoneError2["NO_PLACES"] = "NO_PLACES";
742
+ ShippingZoneError2["INVALID_PLACE"] = "INVALID_PLACE";
743
+ ShippingZoneError2["DUPLICATE_PLACE"] = "DUPLICATE_PLACE";
744
+ ShippingZoneError2["NO_WEBSITE_OPTION"] = "NO_WEBSITE_OPTION";
745
+ ShippingZoneError2["INVALID_PRICE"] = "INVALID_PRICE";
746
+ ShippingZoneError2["INVALID_DAYS"] = "INVALID_DAYS";
747
+ ShippingZoneError2["INVALID_TIERS"] = "INVALID_TIERS";
748
+ ShippingZoneError2["NO_CHANNEL"] = "NO_CHANNEL";
749
+ ShippingZoneError2["PICKUP_WITHOUT_STORE"] = "PICKUP_WITHOUT_STORE";
750
+ ShippingZoneError2["MISSING_NAME"] = "MISSING_NAME";
751
+ return ShippingZoneError2;
752
+ })(ShippingZoneError || {});
753
+
679
754
  // utils/currency.util.ts
680
755
  var CURRENCY_CONFIG = {
681
756
  // Major currencies with 2 decimal places
@@ -3194,7 +3269,9 @@ function buildGrid(rule, timeZone, from, to, now, busy = []) {
3194
3269
  const start = startAt.getTime();
3195
3270
  if (start < askedFrom || start >= askedTo) return false;
3196
3271
  if (start < notBefore || start > notAfter) return false;
3197
- return !blocked.some(({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom);
3272
+ return !blocked.some(
3273
+ ({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom
3274
+ );
3198
3275
  }).sort((first, second) => +first.startAt - +second.startAt);
3199
3276
  }
3200
3277
  function slotsForWindow(grid, startAt, endAt) {
@@ -3313,7 +3390,14 @@ function buildAvailability({
3313
3390
  for (const slot of slots2) {
3314
3391
  const { taken, foreignProductId } = occupancyIn(mine, productId, slot.startAt, slot.bufferEndAt, shared);
3315
3392
  const free = foreignProductId ? 0 : Math.max(capacity - taken, 0);
3316
- const entry = byInstant.get(+slot.startAt) ?? { ...slot, capacity: 0, booked: 0, free: 0, resources: [], dayKey: shopDayKey(slot.startAt, resource.timeZone) };
3393
+ const entry = byInstant.get(+slot.startAt) ?? {
3394
+ ...slot,
3395
+ capacity: 0,
3396
+ booked: 0,
3397
+ free: 0,
3398
+ resources: [],
3399
+ dayKey: shopDayKey(slot.startAt, resource.timeZone)
3400
+ };
3317
3401
  entry.capacity += capacity;
3318
3402
  entry.booked += foreignProductId ? capacity : taken;
3319
3403
  entry.free += free;
@@ -3386,20 +3470,377 @@ function planWindow({ rule, timeZone, presence, startAt, endAt, now, busy = [] }
3386
3470
  }
3387
3471
  var holdExpiresAt = (rule, now) => new Date(now.getTime() + (rule.window.holdMinutes ?? DEFAULT_HOLD_MINUTES) * 6e4);
3388
3472
 
3473
+ // shipping/fold-text.ts
3474
+ function foldText(value) {
3475
+ return value.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/&/g, " and ").replace(/[^a-z0-9]+/g, " ").trim();
3476
+ }
3477
+
3478
+ // shipping/countries.ts
3479
+ var NOT_COUNTRIES = /* @__PURE__ */ new Set(["AC", "CP", "CQ", "DG", "EA", "EU", "EZ", "IC", "QO", "TA", "UN", "XA", "XB", "ZZ"]);
3480
+ var ALIASES = {
3481
+ usa: "US",
3482
+ "united states of america": "US",
3483
+ uk: "GB",
3484
+ "great britain": "GB",
3485
+ england: "GB",
3486
+ uae: "AE",
3487
+ can: "CA",
3488
+ mex: "MX",
3489
+ aus: "AU",
3490
+ gbr: "GB"
3491
+ };
3492
+ var NAME_LOCALES = ["en", "fr"];
3493
+ function regionNames(locale) {
3494
+ try {
3495
+ return new Intl.DisplayNames([locale], { type: "region", fallback: "none" });
3496
+ } catch {
3497
+ return null;
3498
+ }
3499
+ }
3500
+ function canonicalCode(code) {
3501
+ try {
3502
+ return new Intl.Locale(`und-${code}`).maximize().region ?? code;
3503
+ } catch {
3504
+ return code;
3505
+ }
3506
+ }
3507
+ function allCodes() {
3508
+ const names = regionNames("en");
3509
+ if (!names) return [];
3510
+ const codes2 = [];
3511
+ for (let a = 65; a <= 90; a++) {
3512
+ for (let b = 65; b <= 90; b++) {
3513
+ const code = String.fromCharCode(a, b);
3514
+ if (!NOT_COUNTRIES.has(code) && names.of(code) && canonicalCode(code) === code) codes2.push(code);
3515
+ }
3516
+ }
3517
+ return codes2;
3518
+ }
3519
+ var lookup = null;
3520
+ var codes = null;
3521
+ function countryCodes() {
3522
+ codes ??= allCodes();
3523
+ return codes;
3524
+ }
3525
+ function countryLookup() {
3526
+ if (lookup) return lookup;
3527
+ lookup = new Map(Object.entries(ALIASES));
3528
+ for (const locale of NAME_LOCALES) {
3529
+ const names = regionNames(locale);
3530
+ if (!names) continue;
3531
+ for (const code of countryCodes()) {
3532
+ const name = names.of(code);
3533
+ if (name) lookup.set(foldText(name), code);
3534
+ }
3535
+ }
3536
+ return lookup;
3537
+ }
3538
+ function normalizeCountry(value) {
3539
+ const text = (value ?? "").trim();
3540
+ if (!text) return void 0;
3541
+ const upper = text.toUpperCase();
3542
+ if (upper.length === 2) {
3543
+ if (NOT_COUNTRIES.has(upper)) return void 0;
3544
+ const code = canonicalCode(upper);
3545
+ if (countryCodes().includes(code)) return code;
3546
+ }
3547
+ return countryLookup().get(foldText(text));
3548
+ }
3549
+ function listCountries(locale = "en") {
3550
+ const names = regionNames(locale) ?? regionNames("en");
3551
+ return countryCodes().map((code) => ({ code, name: names?.of(code) ?? code })).sort((a, b) => a.name.localeCompare(b.name, locale));
3552
+ }
3553
+
3554
+ // shipping/provinces.ts
3555
+ var CANADA_PROVINCES = [
3556
+ { code: "AB", name: "Alberta", nameFr: "Alberta", postalLetters: ["T"] },
3557
+ { code: "BC", name: "British Columbia", nameFr: "Colombie-Britannique", postalLetters: ["V"] },
3558
+ { code: "MB", name: "Manitoba", nameFr: "Manitoba", postalLetters: ["R"] },
3559
+ { code: "NB", name: "New Brunswick", nameFr: "Nouveau-Brunswick", postalLetters: ["E"] },
3560
+ {
3561
+ code: "NL",
3562
+ name: "Newfoundland and Labrador",
3563
+ nameFr: "Terre-Neuve-et-Labrador",
3564
+ postalLetters: ["A"],
3565
+ aliases: ["NF", "LB", "Newfoundland", "Labrador"]
3566
+ },
3567
+ { code: "NS", name: "Nova Scotia", nameFr: "Nouvelle-\xC9cosse", postalLetters: ["B"] },
3568
+ { code: "NT", name: "Northwest Territories", nameFr: "Territoires du Nord-Ouest", postalLetters: ["X"] },
3569
+ { code: "NU", name: "Nunavut", nameFr: "Nunavut", postalLetters: ["X"] },
3570
+ { code: "ON", name: "Ontario", nameFr: "Ontario", postalLetters: ["K", "L", "M", "N", "P"] },
3571
+ {
3572
+ code: "PE",
3573
+ name: "Prince Edward Island",
3574
+ nameFr: "\xCEle-du-Prince-\xC9douard",
3575
+ postalLetters: ["C"],
3576
+ aliases: ["PEI"]
3577
+ },
3578
+ { code: "QC", name: "Quebec", nameFr: "Qu\xE9bec", postalLetters: ["G", "H", "J"], aliases: ["PQ"] },
3579
+ { code: "SK", name: "Saskatchewan", nameFr: "Saskatchewan", postalLetters: ["S"] },
3580
+ { code: "YT", name: "Yukon", nameFr: "Yukon", postalLetters: ["Y"], aliases: ["YK"] }
3581
+ ];
3582
+ var PROVINCES_BY_COUNTRY = { CA: CANADA_PROVINCES };
3583
+ var lookups = /* @__PURE__ */ new Map();
3584
+ function provinceLookup(country) {
3585
+ const provinces = PROVINCES_BY_COUNTRY[country];
3586
+ if (!provinces) return void 0;
3587
+ let lookup2 = lookups.get(country);
3588
+ if (!lookup2) {
3589
+ lookup2 = /* @__PURE__ */ new Map();
3590
+ for (const p of provinces) {
3591
+ for (const label of [p.code, p.name, p.nameFr, ...p.aliases ?? []]) lookup2.set(foldText(label), p.code);
3592
+ }
3593
+ lookups.set(country, lookup2);
3594
+ }
3595
+ return lookup2;
3596
+ }
3597
+ function normalizeProvince(country, value) {
3598
+ if (!country || !value?.trim()) return void 0;
3599
+ return provinceLookup(country)?.get(foldText(value));
3600
+ }
3601
+ function listProvinces(country) {
3602
+ return PROVINCES_BY_COUNTRY[country] ?? [];
3603
+ }
3604
+ function provincesForPostCode(country, postCode) {
3605
+ const letter = postCode?.charAt(0);
3606
+ if (!country || !letter) return [];
3607
+ return listProvinces(country).filter((p) => p.postalLetters.includes(letter)).map((p) => p.code);
3608
+ }
3609
+
3610
+ // shipping/normalize.ts
3611
+ var EVERYWHERE_KEY = "*";
3612
+ function normalizeCityKey(value) {
3613
+ const words = foldText(value ?? "").split(" ").filter(Boolean).map((word) => word === "saint" ? "st" : word === "sainte" ? "ste" : word);
3614
+ return words.length ? words.join("") : void 0;
3615
+ }
3616
+ function normalizePostCode(value) {
3617
+ const compact = (value ?? "").replace(/[^0-9a-z]/gi, "").toUpperCase();
3618
+ return compact || void 0;
3619
+ }
3620
+ function normalizeAddress(address) {
3621
+ if (!address) return {};
3622
+ const country = normalizeCountry(address.country);
3623
+ const postCode = normalizePostCode(address.postCode ?? address.postalCode ?? address.zip);
3624
+ const fromPostCode = provincesForPostCode(country, postCode);
3625
+ const province = normalizeProvince(country, address.state ?? address.province) ?? (fromPostCode.length === 1 ? fromPostCode[0] : void 0);
3626
+ return { country, province, cityKey: normalizeCityKey(address.city), postCode };
3627
+ }
3628
+ function postCodeMatchesProvince(address) {
3629
+ const candidates = provincesForPostCode(address.country, address.postCode);
3630
+ if (!address.province || candidates.length === 0) return true;
3631
+ return candidates.includes(address.province);
3632
+ }
3633
+ function placeKey(place) {
3634
+ const country = normalizeCountry(place.country);
3635
+ if (!country) return void 0;
3636
+ if (!place.province) return country;
3637
+ const province = normalizeProvince(country, place.province);
3638
+ if (!province) return void 0;
3639
+ if (!place.city) return `${country}-${province}`;
3640
+ const city = normalizeCityKey(place.city);
3641
+ return city ? `${country}-${province}/${city}` : void 0;
3642
+ }
3643
+ function addressPlaceKeys(address) {
3644
+ const keys = [];
3645
+ if (address.country && address.province && address.cityKey) {
3646
+ keys.push(`${address.country}-${address.province}/${address.cityKey}`);
3647
+ }
3648
+ if (address.country && address.province) keys.push(`${address.country}-${address.province}`);
3649
+ if (address.country) keys.push(address.country);
3650
+ keys.push(EVERYWHERE_KEY);
3651
+ return keys;
3652
+ }
3653
+
3654
+ // shipping/resolve.ts
3655
+ function resolveShipping({ zones, address, itemsTotal, channel }) {
3656
+ const shipsToCountries = countriesShippedTo(zones);
3657
+ const none = (reason, zone2) => ({
3658
+ zoneId: zone2?.id ?? null,
3659
+ options: [],
3660
+ reason,
3661
+ message: zone2?.message?.trim() || null,
3662
+ shipsToCountries
3663
+ });
3664
+ const normalized = normalizeAddress(address);
3665
+ if (!normalized.country) return none("INCOMPLETE" /* INCOMPLETE */);
3666
+ if (!postCodeMatchesProvince(normalized)) return none("ADDRESS_MISMATCH" /* ADDRESS_MISMATCH */);
3667
+ const zone = findZone(zones, addressPlaceKeys(normalized));
3668
+ if (!zone) return none("NO_COVERAGE" /* NO_COVERAGE */);
3669
+ const offered = zone.options.filter((option) => isOffered(option, zone, channel));
3670
+ if (offered.length === 0) {
3671
+ return none(zone.ships ? "NO_OPTION" /* NO_OPTION */ : "BLOCKED" /* BLOCKED */, zone);
3672
+ }
3673
+ const quotes = offered.map((option) => quote(option, zone.id, itemsTotal));
3674
+ const ship = quotes.filter((q) => q.type === "ship" /* SHIP */).sort((a, b) => a.amount - b.amount);
3675
+ const pickup = quotes.filter((q) => q.type === "pickup" /* PICKUP */).sort((a, b) => a.amount - b.amount);
3676
+ return {
3677
+ zoneId: zone.id,
3678
+ options: [...ship, ...pickup],
3679
+ reason: null,
3680
+ message: zone.ships ? null : zone.message?.trim() || null,
3681
+ shipsToCountries
3682
+ };
3683
+ }
3684
+ function findZone(zones, keys) {
3685
+ const byKey = /* @__PURE__ */ new Map();
3686
+ for (const zone of zones) {
3687
+ for (const key of zoneKeys(zone)) if (!byKey.has(key)) byKey.set(key, zone);
3688
+ }
3689
+ for (const key of keys) {
3690
+ const zone = byKey.get(key);
3691
+ if (zone) return zone;
3692
+ }
3693
+ return void 0;
3694
+ }
3695
+ function zoneKeys(zone) {
3696
+ if (zone.kind === "everywhere" /* EVERYWHERE */) return [EVERYWHERE_KEY];
3697
+ return zone.places.map(placeKey).filter((key) => Boolean(key));
3698
+ }
3699
+ function isOffered(option, zone, channel) {
3700
+ if (!option.channels.some((c) => c === channel)) return false;
3701
+ if (option.type === "pickup" /* PICKUP */) return channel !== "pos" /* POS */;
3702
+ return zone.ships;
3703
+ }
3704
+ function priceForTotal(option, itemsTotal) {
3705
+ const tiers = [...option.priceByTotal ?? []].sort((a, b) => a.from - b.from);
3706
+ let price = option.price;
3707
+ for (const tier of tiers) if (itemsTotal >= tier.from) price = tier.price;
3708
+ if (option.freeOver != null && itemsTotal >= option.freeOver) return 0;
3709
+ return price;
3710
+ }
3711
+ function quote(option, zoneId, itemsTotal) {
3712
+ const amount = priceForTotal(option, itemsTotal);
3713
+ const freeOver = option.freeOver ?? null;
3714
+ return {
3715
+ optionId: option.id,
3716
+ zoneId,
3717
+ type: option.type,
3718
+ name: option.name?.trim() || null,
3719
+ amount,
3720
+ amountToFree: freeOver != null && amount > 0 ? freeOver - itemsTotal : null,
3721
+ minDays: option.minDays ?? null,
3722
+ maxDays: option.maxDays ?? null,
3723
+ outletId: option.outletId ?? null
3724
+ };
3725
+ }
3726
+ function countriesShippedTo(zones) {
3727
+ const countries = /* @__PURE__ */ new Set();
3728
+ for (const zone of zones) {
3729
+ if (!zone.ships) continue;
3730
+ for (const key of zoneKeys(zone)) if (key !== EVERYWHERE_KEY) countries.add(key.slice(0, 2));
3731
+ }
3732
+ return [...countries].sort();
3733
+ }
3734
+
3735
+ // shipping/validate.ts
3736
+ function validateShippingZone(zone) {
3737
+ const problems = [...placeProblems(zone)];
3738
+ for (const option of zone.options) problems.push(...optionProblems(option));
3739
+ const reachesWebsite = zone.options.some((option) => option.channels.includes("web" /* WEB */));
3740
+ if (zone.ships && !reachesWebsite) problems.push({ code: "NO_WEBSITE_OPTION" /* NO_WEBSITE_OPTION */ });
3741
+ return problems;
3742
+ }
3743
+ function placeProblems(zone) {
3744
+ if (zone.kind === "everywhere" /* EVERYWHERE */) {
3745
+ return zone.places.length ? [{ code: "INVALID_PLACE" /* INVALID_PLACE */ }] : [];
3746
+ }
3747
+ if (zone.places.length === 0) return [{ code: "NO_PLACES" /* NO_PLACES */ }];
3748
+ if (!zone.places.every((place) => fitsKind(place, zone.kind))) return [{ code: "INVALID_PLACE" /* INVALID_PLACE */ }];
3749
+ const keys = zone.places.map(placeKey);
3750
+ if (keys.some((key) => !key)) return [{ code: "INVALID_PLACE" /* INVALID_PLACE */ }];
3751
+ if (new Set(keys).size !== keys.length) return [{ code: "DUPLICATE_PLACE" /* DUPLICATE_PLACE */ }];
3752
+ return [];
3753
+ }
3754
+ function fitsKind(place, kind) {
3755
+ const hasProvince = Boolean(place.province?.trim());
3756
+ const hasCity = Boolean(place.city?.trim());
3757
+ if (kind === "country" /* COUNTRY */) return !hasProvince && !hasCity;
3758
+ if (kind === "province" /* PROVINCE */) return hasProvince && !hasCity;
3759
+ if (kind === "city" /* CITY */) return hasProvince && hasCity;
3760
+ return false;
3761
+ }
3762
+ var isAmount = (value) => Number.isInteger(value) && value >= 0;
3763
+ var isDays = (value) => value == null || isAmount(value);
3764
+ function optionProblems(option) {
3765
+ const problems = [];
3766
+ const isPickup = option.type === "pickup" /* PICKUP */;
3767
+ if (!isAmount(option.price) || option.freeOver != null && !isAmount(option.freeOver)) {
3768
+ problems.push("INVALID_PRICE" /* INVALID_PRICE */);
3769
+ }
3770
+ if (!isPickup && !option.name?.trim()) problems.push("MISSING_NAME" /* MISSING_NAME */);
3771
+ if (!isDays(option.minDays) || !isDays(option.maxDays) || (option.minDays ?? 0) > (option.maxDays ?? Infinity)) {
3772
+ problems.push("INVALID_DAYS" /* INVALID_DAYS */);
3773
+ }
3774
+ if (!tiersAreValid(option)) problems.push("INVALID_TIERS" /* INVALID_TIERS */);
3775
+ if (option.channels.length === 0) problems.push("NO_CHANNEL" /* NO_CHANNEL */);
3776
+ if (isPickup && !option.outletId) problems.push("PICKUP_WITHOUT_STORE" /* PICKUP_WITHOUT_STORE */);
3777
+ return problems.map((code) => ({ code, optionId: option.id }));
3778
+ }
3779
+ function tiersAreValid(option) {
3780
+ const tiers = option.priceByTotal ?? [];
3781
+ const froms = tiers.map((tier) => tier.from);
3782
+ return tiers.every((tier) => Number.isInteger(tier.from) && tier.from > 0 && isAmount(tier.price)) && new Set(froms).size === froms.length;
3783
+ }
3784
+
3389
3785
  // constants/adyen.constants.ts
3390
3786
  var ADYEN_ROLLOUT_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
3391
3787
  function isAdyenRolloutCountry(alpha2) {
3392
3788
  return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);
3393
3789
  }
3790
+ var AFFIRM_PRICE_PLANS = ["core", "standard", "signature"];
3791
+ function isAffirmPricePlan(value) {
3792
+ return typeof value === "string" && AFFIRM_PRICE_PLANS.includes(value);
3793
+ }
3794
+ var AFFIRM_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
3795
+ function isAffirmCountry(alpha2) {
3796
+ return !!alpha2 && AFFIRM_COUNTRY_CODES.has(alpha2.toUpperCase());
3797
+ }
3798
+ var BNPL_METHOD_STATUS = {
3799
+ ACTIVE: "active",
3800
+ PENDING: "pending",
3801
+ UNAVAILABLE: "unavailable",
3802
+ UNKNOWN: "unknown"
3803
+ };
3804
+ var BNPL_SKIP_REASON = {
3805
+ PENDING: "pending",
3806
+ NO_SUPPORT_EMAIL: "no_support_email",
3807
+ NO_CURRENCY: "no_currency",
3808
+ NO_BUSINESS_LINE: "no_business_line"
3809
+ };
3810
+
3811
+ // pos-types/active/ProcessorType.ts
3812
+ var ProcessorType = /* @__PURE__ */ ((ProcessorType2) => {
3813
+ ProcessorType2["FINAL_PAY"] = "Terminal";
3814
+ ProcessorType2["TAP_TO_PAY"] = "TapToPay";
3815
+ ProcessorType2["MOTO"] = "Moto";
3816
+ ProcessorType2["CLOUD"] = "Cloud";
3817
+ ProcessorType2["BLUETOOTH"] = "Bluetooth";
3818
+ ProcessorType2["CASH"] = "Cash";
3819
+ ProcessorType2["CUSTOM_PAY"] = "CustomPay";
3820
+ ProcessorType2["VENDARA"] = "Vendara";
3821
+ ProcessorType2["REDEEM"] = "Redeem";
3822
+ ProcessorType2["INTEGRATION"] = "Integration";
3823
+ ProcessorType2["PAYMENT_LINK"] = "PaymentLink";
3824
+ ProcessorType2["ONLINE_PAYMENT"] = "OnlinePayment";
3825
+ return ProcessorType2;
3826
+ })(ProcessorType || {});
3827
+
3828
+ // constants/payment-channel.constants.ts
3829
+ var PAYMENT_CHANNELS = ["inPerson", "online"];
3394
3830
  // Annotate the CommonJS export names for ESM import in node:
3395
3831
  0 && (module.exports = {
3396
3832
  ADYEN_ROLLOUT_COUNTRY_CODES,
3833
+ AFFIRM_COUNTRY_CODES,
3834
+ AFFIRM_PRICE_PLANS,
3397
3835
  AttributeType,
3836
+ BNPL_METHOD_STATUS,
3837
+ BNPL_SKIP_REASON,
3398
3838
  BookingRatePeriod,
3399
3839
  BookingResourceKind,
3400
3840
  BookingResourceStatus,
3401
3841
  BookingRulesError,
3402
3842
  BookingType,
3843
+ CANADA_PROVINCES,
3403
3844
  CONDITION_OPERATORS,
3404
3845
  COUNTRY_CURRENCIES,
3405
3846
  CURRENCY_CONFIG,
@@ -3416,6 +3857,7 @@ function isAdyenRolloutCountry(alpha2) {
3416
3857
  DualWriteStrategy,
3417
3858
  EUFixedRates,
3418
3859
  EUROPE,
3860
+ EVERYWHERE_KEY,
3419
3861
  ExtensionCategory,
3420
3862
  FINANCIAL_INVARIANTS,
3421
3863
  FULFILLMENT_STATES,
@@ -3437,6 +3879,7 @@ function isAdyenRolloutCountry(alpha2) {
3437
3879
  OtherFixedRates,
3438
3880
  OwnerType,
3439
3881
  PATH_MODES,
3882
+ PAYMENT_CHANNELS,
3440
3883
  PAYMENT_STATES,
3441
3884
  POS_VALID_INITIAL_STATES,
3442
3885
  PaymentMethod,
@@ -3446,6 +3889,7 @@ function isAdyenRolloutCountry(alpha2) {
3446
3889
  PricingLevel,
3447
3890
  PricingPlanEnum,
3448
3891
  PricingRegionEnum,
3892
+ ProcessorType,
3449
3893
  ProductStatus,
3450
3894
  ProductType,
3451
3895
  PublicationAvailability,
@@ -3464,6 +3908,12 @@ function isAdyenRolloutCountry(alpha2) {
3464
3908
  SYSTEM_FAMILY_IDS,
3465
3909
  SYSTEM_UNITS,
3466
3910
  SYSTEM_UNIT_IDS,
3911
+ ShippingChannel,
3912
+ ShippingNoOptionReason,
3913
+ ShippingOptionType,
3914
+ ShippingRateType,
3915
+ ShippingZoneError,
3916
+ ShippingZoneKind,
3467
3917
  StationStatus,
3468
3918
  StripeCurrencyCode,
3469
3919
  StripeStatus,
@@ -3471,6 +3921,7 @@ function isAdyenRolloutCountry(alpha2) {
3471
3921
  TopMetericsSort,
3472
3922
  UserTypes,
3473
3923
  addAmounts,
3924
+ addressPlaceKeys,
3474
3925
  amountToString,
3475
3926
  assertUnitSane,
3476
3927
  availableIn,
@@ -3522,6 +3973,8 @@ function isAdyenRolloutCountry(alpha2) {
3522
3973
  holdExpiresAt,
3523
3974
  inferStatesFromLegacyStatus,
3524
3975
  isAdyenRolloutCountry,
3976
+ isAffirmCountry,
3977
+ isAffirmPricePlan,
3525
3978
  isConditionOperator,
3526
3979
  isFulfillmentState,
3527
3980
  isPaymentState,
@@ -3529,19 +3982,31 @@ function isAdyenRolloutCountry(alpha2) {
3529
3982
  isSystemFamilyCode,
3530
3983
  isValidQuantity,
3531
3984
  isWhole,
3985
+ listCountries,
3986
+ listProvinces,
3532
3987
  mapToLegacyStatus,
3533
3988
  maxPrecisionFor,
3534
3989
  mergeFragment,
3535
3990
  multiplyAmount,
3991
+ normalizeAddress,
3992
+ normalizeCityKey,
3993
+ normalizeCountry,
3536
3994
  normalizeMongoIdString,
3995
+ normalizePostCode,
3996
+ normalizeProvince,
3537
3997
  occupancyIn,
3538
3998
  parseAmountToMinorUnits,
3539
3999
  parseCurrencyCode,
3540
4000
  parseStripeCurrencyCode,
4001
+ placeKey,
3541
4002
  planWindow,
4003
+ postCodeMatchesProvince,
3542
4004
  presentAt,
4005
+ priceForTotal,
4006
+ provincesForPostCode,
3543
4007
  removeFragment,
3544
4008
  resolveFamily,
4009
+ resolveShipping,
3545
4010
  resolveTemplate,
3546
4011
  resolveUnit,
3547
4012
  roundToPrecision,
@@ -3557,6 +4022,7 @@ function isAdyenRolloutCountry(alpha2) {
3557
4022
  toMinorUnits,
3558
4023
  validateConfig,
3559
4024
  validateFragmentCompatibility,
4025
+ validateShippingZone,
3560
4026
  violatesFinancialInvariant,
3561
4027
  windowEndsAt,
3562
4028
  withinPresence