@final-commerce/common 2.7.0 → 2.7.1-online.1

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
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  BookingResourceStatus: () => BookingResourceStatus,
37
37
  BookingRulesError: () => BookingRulesError,
38
38
  BookingType: () => BookingType,
39
+ CANADA_PROVINCES: () => CANADA_PROVINCES,
39
40
  CONDITION_OPERATORS: () => CONDITION_OPERATORS,
40
41
  COUNTRY_CURRENCIES: () => COUNTRY_CURRENCIES,
41
42
  CURRENCY_CONFIG: () => CURRENCY_CONFIG,
@@ -52,6 +53,7 @@ __export(index_exports, {
52
53
  DualWriteStrategy: () => DualWriteStrategy,
53
54
  EUFixedRates: () => EUFixedRates,
54
55
  EUROPE: () => EUROPE,
56
+ EVERYWHERE_KEY: () => EVERYWHERE_KEY,
55
57
  ExtensionCategory: () => ExtensionCategory,
56
58
  FINANCIAL_INVARIANTS: () => FINANCIAL_INVARIANTS,
57
59
  FULFILLMENT_STATES: () => FULFILLMENT_STATES,
@@ -73,6 +75,7 @@ __export(index_exports, {
73
75
  OtherFixedRates: () => OtherFixedRates,
74
76
  OwnerType: () => OwnerType,
75
77
  PATH_MODES: () => PATH_MODES,
78
+ PAYMENT_CHANNELS: () => PAYMENT_CHANNELS,
76
79
  PAYMENT_STATES: () => PAYMENT_STATES,
77
80
  POS_VALID_INITIAL_STATES: () => POS_VALID_INITIAL_STATES,
78
81
  PaymentMethod: () => PaymentMethod,
@@ -82,6 +85,7 @@ __export(index_exports, {
82
85
  PricingLevel: () => PricingLevel,
83
86
  PricingPlanEnum: () => PricingPlanEnum,
84
87
  PricingRegionEnum: () => PricingRegionEnum,
88
+ ProcessorType: () => ProcessorType,
85
89
  ProductStatus: () => ProductStatus,
86
90
  ProductType: () => ProductType,
87
91
  PublicationAvailability: () => PublicationAvailability,
@@ -100,6 +104,12 @@ __export(index_exports, {
100
104
  SYSTEM_FAMILY_IDS: () => SYSTEM_FAMILY_IDS,
101
105
  SYSTEM_UNITS: () => SYSTEM_UNITS,
102
106
  SYSTEM_UNIT_IDS: () => SYSTEM_UNIT_IDS,
107
+ ShippingChannel: () => ShippingChannel,
108
+ ShippingNoOptionReason: () => ShippingNoOptionReason,
109
+ ShippingOptionType: () => ShippingOptionType,
110
+ ShippingRateType: () => ShippingRateType,
111
+ ShippingZoneError: () => ShippingZoneError,
112
+ ShippingZoneKind: () => ShippingZoneKind,
103
113
  StationStatus: () => StationStatus,
104
114
  StripeCurrencyCode: () => StripeCurrencyCode,
105
115
  StripeStatus: () => StripeStatus,
@@ -107,6 +117,7 @@ __export(index_exports, {
107
117
  TopMetericsSort: () => TopMetericsSort,
108
118
  UserTypes: () => UserTypes,
109
119
  addAmounts: () => addAmounts,
120
+ addressPlaceKeys: () => addressPlaceKeys,
110
121
  adyenLegalEntityRequiresStateOrProvince: () => adyenLegalEntityRequiresStateOrProvince,
111
122
  adyenRequiresJobTitle: () => adyenRequiresJobTitle,
112
123
  adyenStoreRequiresStateOrProvince: () => adyenStoreRequiresStateOrProvince,
@@ -185,25 +196,37 @@ __export(index_exports, {
185
196
  isSystemFamilyCode: () => isSystemFamilyCode,
186
197
  isValidQuantity: () => isValidQuantity,
187
198
  isWhole: () => isWhole,
199
+ listCountries: () => listCountries,
200
+ listProvinces: () => listProvinces,
188
201
  mapToLegacyStatus: () => mapToLegacyStatus,
189
202
  maxPrecisionFor: () => maxPrecisionFor,
190
203
  mergeFragment: () => mergeFragment,
191
204
  modifiersSellable: () => modifiersSellable,
192
205
  multiplyAmount: () => multiplyAmount,
206
+ normalizeAddress: () => normalizeAddress,
207
+ normalizeCityKey: () => normalizeCityKey,
208
+ normalizeCountry: () => normalizeCountry,
193
209
  normalizeMongoIdString: () => normalizeMongoIdString,
210
+ normalizePostCode: () => normalizePostCode,
211
+ normalizeProvince: () => normalizeProvince,
194
212
  occupancyIn: () => occupancyIn,
195
213
  parseAmountToMinorUnits: () => parseAmountToMinorUnits,
196
214
  parseCurrencyCode: () => parseCurrencyCode,
197
215
  parseStripeCurrencyCode: () => parseStripeCurrencyCode,
216
+ placeKey: () => placeKey,
198
217
  planWindow: () => planWindow,
199
218
  poolDemand: () => poolDemand,
200
219
  poolOf: () => poolOf,
201
220
  poolShortfall: () => poolShortfall,
202
221
  poolStockAt: () => poolStockAt,
222
+ postCodeMatchesProvince: () => postCodeMatchesProvince,
203
223
  presentAt: () => presentAt,
224
+ priceForTotal: () => priceForTotal,
225
+ provincesForPostCode: () => provincesForPostCode,
204
226
  removeFragment: () => removeFragment,
205
227
  resolveFamily: () => resolveFamily,
206
228
  resolveModifiersForProduct: () => resolveModifiersForProduct,
229
+ resolveShipping: () => resolveShipping,
207
230
  resolveTemplate: () => resolveTemplate,
208
231
  resolveUnit: () => resolveUnit,
209
232
  roundToPrecision: () => roundToPrecision,
@@ -220,6 +243,7 @@ __export(index_exports, {
220
243
  validateConfig: () => validateConfig,
221
244
  validateFragmentCompatibility: () => validateFragmentCompatibility,
222
245
  validateOrderStatuses: () => validateOrderStatuses,
246
+ validateShippingZone: () => validateShippingZone,
223
247
  violatesFinancialInvariant: () => violatesFinancialInvariant,
224
248
  windowEndsAt: () => windowEndsAt,
225
249
  withinPresence: () => withinPresence
@@ -428,6 +452,7 @@ var OrderPlatform = /* @__PURE__ */ ((OrderPlatform2) => {
428
452
  OrderPlatform2["POS"] = "in-store";
429
453
  OrderPlatform2["WOO_COMMERCE"] = "woo-commerce";
430
454
  OrderPlatform2["PUBLIC_API"] = "public-api";
455
+ OrderPlatform2["ONLINE_STORE"] = "online-store";
431
456
  return OrderPlatform2;
432
457
  })(OrderPlatform || {});
433
458
  var CustomerPlatform = /* @__PURE__ */ ((CustomerPlatform2) => {
@@ -714,6 +739,50 @@ var ResourceAvailabilityState = /* @__PURE__ */ ((ResourceAvailabilityState2) =>
714
739
  return ResourceAvailabilityState2;
715
740
  })(ResourceAvailabilityState || {});
716
741
 
742
+ // enums/shipping.enum.ts
743
+ var ShippingZoneKind = /* @__PURE__ */ ((ShippingZoneKind2) => {
744
+ ShippingZoneKind2["COUNTRY"] = "country";
745
+ ShippingZoneKind2["PROVINCE"] = "province";
746
+ ShippingZoneKind2["CITY"] = "city";
747
+ ShippingZoneKind2["EVERYWHERE"] = "everywhere";
748
+ return ShippingZoneKind2;
749
+ })(ShippingZoneKind || {});
750
+ var ShippingOptionType = /* @__PURE__ */ ((ShippingOptionType2) => {
751
+ ShippingOptionType2["SHIP"] = "ship";
752
+ ShippingOptionType2["PICKUP"] = "pickup";
753
+ return ShippingOptionType2;
754
+ })(ShippingOptionType || {});
755
+ var ShippingRateType = /* @__PURE__ */ ((ShippingRateType2) => {
756
+ ShippingRateType2["FLAT"] = "flat";
757
+ return ShippingRateType2;
758
+ })(ShippingRateType || {});
759
+ var ShippingChannel = /* @__PURE__ */ ((ShippingChannel2) => {
760
+ ShippingChannel2["WEB"] = "web";
761
+ ShippingChannel2["POS"] = "pos";
762
+ return ShippingChannel2;
763
+ })(ShippingChannel || {});
764
+ var ShippingNoOptionReason = /* @__PURE__ */ ((ShippingNoOptionReason2) => {
765
+ ShippingNoOptionReason2["INCOMPLETE"] = "INCOMPLETE";
766
+ ShippingNoOptionReason2["ADDRESS_MISMATCH"] = "ADDRESS_MISMATCH";
767
+ ShippingNoOptionReason2["NO_COVERAGE"] = "NO_COVERAGE";
768
+ ShippingNoOptionReason2["BLOCKED"] = "BLOCKED";
769
+ ShippingNoOptionReason2["NO_OPTION"] = "NO_OPTION";
770
+ return ShippingNoOptionReason2;
771
+ })(ShippingNoOptionReason || {});
772
+ var ShippingZoneError = /* @__PURE__ */ ((ShippingZoneError2) => {
773
+ ShippingZoneError2["NO_PLACES"] = "NO_PLACES";
774
+ ShippingZoneError2["INVALID_PLACE"] = "INVALID_PLACE";
775
+ ShippingZoneError2["DUPLICATE_PLACE"] = "DUPLICATE_PLACE";
776
+ ShippingZoneError2["NO_WEBSITE_OPTION"] = "NO_WEBSITE_OPTION";
777
+ ShippingZoneError2["INVALID_PRICE"] = "INVALID_PRICE";
778
+ ShippingZoneError2["INVALID_DAYS"] = "INVALID_DAYS";
779
+ ShippingZoneError2["INVALID_TIERS"] = "INVALID_TIERS";
780
+ ShippingZoneError2["NO_CHANNEL"] = "NO_CHANNEL";
781
+ ShippingZoneError2["PICKUP_WITHOUT_STORE"] = "PICKUP_WITHOUT_STORE";
782
+ ShippingZoneError2["MISSING_NAME"] = "MISSING_NAME";
783
+ return ShippingZoneError2;
784
+ })(ShippingZoneError || {});
785
+
717
786
  // utils/currency.util.ts
718
787
  var CURRENCY_CONFIG = {
719
788
  // Major currencies with 2 decimal places
@@ -3792,6 +3861,321 @@ function planWindow({ rule, timeZone, presence, startAt, endAt, now, busy = [] }
3792
3861
  }
3793
3862
  var holdExpiresAt = (rule, now) => new Date(now.getTime() + (rule.window.holdMinutes ?? DEFAULT_HOLD_MINUTES) * 6e4);
3794
3863
 
3864
+ // shipping/fold-text.ts
3865
+ function foldText(value) {
3866
+ return value.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/&/g, " and ").replace(/[^a-z0-9]+/g, " ").trim();
3867
+ }
3868
+
3869
+ // shipping/countries.ts
3870
+ var NOT_COUNTRIES = /* @__PURE__ */ new Set(["AC", "CP", "CQ", "DG", "EA", "EU", "EZ", "IC", "QO", "TA", "UN", "XA", "XB", "ZZ"]);
3871
+ var ALIASES = {
3872
+ canada: "CA",
3873
+ "united states": "US",
3874
+ usa: "US",
3875
+ "united states of america": "US",
3876
+ uk: "GB",
3877
+ "great britain": "GB",
3878
+ england: "GB",
3879
+ uae: "AE",
3880
+ can: "CA",
3881
+ mex: "MX",
3882
+ aus: "AU",
3883
+ gbr: "GB"
3884
+ };
3885
+ var NAME_LOCALES = ["en", "fr"];
3886
+ function regionNames(locale) {
3887
+ try {
3888
+ return new Intl.DisplayNames([locale], { type: "region", fallback: "none" });
3889
+ } catch {
3890
+ return null;
3891
+ }
3892
+ }
3893
+ function canonicalCode(code) {
3894
+ try {
3895
+ return new Intl.Locale(`und-${code}`).maximize().region ?? code;
3896
+ } catch {
3897
+ return code;
3898
+ }
3899
+ }
3900
+ function allCodes() {
3901
+ const names = regionNames("en");
3902
+ if (!names) return [];
3903
+ const codes2 = [];
3904
+ for (let a = 65; a <= 90; a++) {
3905
+ for (let b = 65; b <= 90; b++) {
3906
+ const code = String.fromCharCode(a, b);
3907
+ if (!NOT_COUNTRIES.has(code) && names.of(code) && canonicalCode(code) === code) codes2.push(code);
3908
+ }
3909
+ }
3910
+ return codes2;
3911
+ }
3912
+ var lookup = null;
3913
+ var codes = null;
3914
+ function countryCodes() {
3915
+ codes ??= allCodes();
3916
+ return codes;
3917
+ }
3918
+ function countryLookup() {
3919
+ if (lookup) return lookup;
3920
+ lookup = new Map(Object.entries(ALIASES));
3921
+ for (const locale of NAME_LOCALES) {
3922
+ const names = regionNames(locale);
3923
+ if (!names) continue;
3924
+ for (const code of countryCodes()) {
3925
+ const name = names.of(code);
3926
+ if (name) lookup.set(foldText(name), code);
3927
+ }
3928
+ }
3929
+ return lookup;
3930
+ }
3931
+ function normalizeCountry(value) {
3932
+ const text = (value ?? "").trim();
3933
+ if (!text) return void 0;
3934
+ const upper = text.toUpperCase();
3935
+ if (upper.length === 2) {
3936
+ if (NOT_COUNTRIES.has(upper)) return void 0;
3937
+ if (countryCodes().length === 0) return /^[A-Z]{2}$/.test(upper) ? upper : void 0;
3938
+ const code = canonicalCode(upper);
3939
+ if (countryCodes().includes(code)) return code;
3940
+ }
3941
+ return countryLookup().get(foldText(text));
3942
+ }
3943
+ function listCountries(locale = "en") {
3944
+ const names = regionNames(locale) ?? regionNames("en");
3945
+ return countryCodes().map((code) => ({ code, name: names?.of(code) ?? code })).sort((a, b) => a.name.localeCompare(b.name, locale));
3946
+ }
3947
+
3948
+ // shipping/provinces.ts
3949
+ var CANADA_PROVINCES = [
3950
+ { code: "AB", name: "Alberta", nameFr: "Alberta", postalLetters: ["T"] },
3951
+ { code: "BC", name: "British Columbia", nameFr: "Colombie-Britannique", postalLetters: ["V"] },
3952
+ { code: "MB", name: "Manitoba", nameFr: "Manitoba", postalLetters: ["R"] },
3953
+ { code: "NB", name: "New Brunswick", nameFr: "Nouveau-Brunswick", postalLetters: ["E"] },
3954
+ {
3955
+ code: "NL",
3956
+ name: "Newfoundland and Labrador",
3957
+ nameFr: "Terre-Neuve-et-Labrador",
3958
+ postalLetters: ["A"],
3959
+ aliases: ["NF", "LB", "Newfoundland", "Labrador"]
3960
+ },
3961
+ { code: "NS", name: "Nova Scotia", nameFr: "Nouvelle-\xC9cosse", postalLetters: ["B"] },
3962
+ { code: "NT", name: "Northwest Territories", nameFr: "Territoires du Nord-Ouest", postalLetters: ["X"] },
3963
+ { code: "NU", name: "Nunavut", nameFr: "Nunavut", postalLetters: ["X"] },
3964
+ { code: "ON", name: "Ontario", nameFr: "Ontario", postalLetters: ["K", "L", "M", "N", "P"] },
3965
+ {
3966
+ code: "PE",
3967
+ name: "Prince Edward Island",
3968
+ nameFr: "\xCEle-du-Prince-\xC9douard",
3969
+ postalLetters: ["C"],
3970
+ aliases: ["PEI"]
3971
+ },
3972
+ { code: "QC", name: "Quebec", nameFr: "Qu\xE9bec", postalLetters: ["G", "H", "J"], aliases: ["PQ"] },
3973
+ { code: "SK", name: "Saskatchewan", nameFr: "Saskatchewan", postalLetters: ["S"] },
3974
+ { code: "YT", name: "Yukon", nameFr: "Yukon", postalLetters: ["Y"], aliases: ["YK"] }
3975
+ ];
3976
+ var PROVINCES_BY_COUNTRY = { CA: CANADA_PROVINCES };
3977
+ var lookups = /* @__PURE__ */ new Map();
3978
+ function provinceLookup(country) {
3979
+ const provinces = PROVINCES_BY_COUNTRY[country];
3980
+ if (!provinces) return void 0;
3981
+ let lookup2 = lookups.get(country);
3982
+ if (!lookup2) {
3983
+ lookup2 = /* @__PURE__ */ new Map();
3984
+ for (const p of provinces) {
3985
+ for (const label of [p.code, p.name, p.nameFr, ...p.aliases ?? []]) lookup2.set(foldText(label), p.code);
3986
+ }
3987
+ lookups.set(country, lookup2);
3988
+ }
3989
+ return lookup2;
3990
+ }
3991
+ function normalizeProvince(country, value) {
3992
+ if (!country || !value?.trim()) return void 0;
3993
+ return provinceLookup(country)?.get(foldText(value));
3994
+ }
3995
+ function listProvinces(country) {
3996
+ return PROVINCES_BY_COUNTRY[country] ?? [];
3997
+ }
3998
+ function provincesForPostCode(country, postCode) {
3999
+ const letter = postCode?.charAt(0);
4000
+ if (!country || !letter) return [];
4001
+ return listProvinces(country).filter((p) => p.postalLetters.includes(letter)).map((p) => p.code);
4002
+ }
4003
+
4004
+ // shipping/normalize.ts
4005
+ var EVERYWHERE_KEY = "*";
4006
+ function normalizeCityKey(value) {
4007
+ const words = foldText(value ?? "").split(" ").filter(Boolean).map((word) => word === "saint" ? "st" : word === "sainte" ? "ste" : word);
4008
+ return words.length ? words.join("") : void 0;
4009
+ }
4010
+ function normalizePostCode(value) {
4011
+ const compact = (value ?? "").replace(/[^0-9a-z]/gi, "").toUpperCase();
4012
+ return compact || void 0;
4013
+ }
4014
+ function normalizeAddress(address) {
4015
+ if (!address) return {};
4016
+ const country = normalizeCountry(address.country);
4017
+ const postCode = normalizePostCode(address.postCode ?? address.postalCode ?? address.zip);
4018
+ const fromPostCode = provincesForPostCode(country, postCode);
4019
+ const province = normalizeProvince(country, address.state ?? address.province) ?? (fromPostCode.length === 1 ? fromPostCode[0] : void 0);
4020
+ return { country, province, cityKey: normalizeCityKey(address.city), postCode };
4021
+ }
4022
+ function postCodeMatchesProvince(address) {
4023
+ const candidates = provincesForPostCode(address.country, address.postCode);
4024
+ if (!address.province || candidates.length === 0) return true;
4025
+ return candidates.includes(address.province);
4026
+ }
4027
+ function placeKey(place) {
4028
+ const country = normalizeCountry(place.country);
4029
+ if (!country) return void 0;
4030
+ if (!place.province) return country;
4031
+ const province = normalizeProvince(country, place.province);
4032
+ if (!province) return void 0;
4033
+ if (!place.city) return `${country}-${province}`;
4034
+ const city = normalizeCityKey(place.city);
4035
+ return city ? `${country}-${province}/${city}` : void 0;
4036
+ }
4037
+ function addressPlaceKeys(address) {
4038
+ const keys = [];
4039
+ if (address.country && address.province && address.cityKey) {
4040
+ keys.push(`${address.country}-${address.province}/${address.cityKey}`);
4041
+ }
4042
+ if (address.country && address.province) keys.push(`${address.country}-${address.province}`);
4043
+ if (address.country) keys.push(address.country);
4044
+ keys.push(EVERYWHERE_KEY);
4045
+ return keys;
4046
+ }
4047
+
4048
+ // shipping/resolve.ts
4049
+ function resolveShipping({ zones, address, itemsTotal, channel }) {
4050
+ const shipsToCountries = countriesShippedTo(zones);
4051
+ const none = (reason, zone2) => ({
4052
+ zoneId: zone2?.id ?? null,
4053
+ options: [],
4054
+ reason,
4055
+ message: zone2?.message?.trim() || null,
4056
+ shipsToCountries
4057
+ });
4058
+ const normalized = normalizeAddress(address);
4059
+ if (!normalized.country) return none("INCOMPLETE" /* INCOMPLETE */);
4060
+ if (!postCodeMatchesProvince(normalized)) return none("ADDRESS_MISMATCH" /* ADDRESS_MISMATCH */);
4061
+ const zone = findZone(zones, addressPlaceKeys(normalized));
4062
+ if (!zone) return none("NO_COVERAGE" /* NO_COVERAGE */);
4063
+ const offered = zone.options.filter((option) => isOffered(option, zone, channel));
4064
+ if (offered.length === 0) {
4065
+ return none(zone.ships ? "NO_OPTION" /* NO_OPTION */ : "BLOCKED" /* BLOCKED */, zone);
4066
+ }
4067
+ const quotes = offered.map((option) => quote(option, zone.id, itemsTotal));
4068
+ const ship = quotes.filter((q) => q.type === "ship" /* SHIP */).sort((a, b) => a.amount - b.amount);
4069
+ const pickup = quotes.filter((q) => q.type === "pickup" /* PICKUP */).sort((a, b) => a.amount - b.amount);
4070
+ return {
4071
+ zoneId: zone.id,
4072
+ options: [...ship, ...pickup],
4073
+ reason: null,
4074
+ message: zone.ships ? null : zone.message?.trim() || null,
4075
+ shipsToCountries
4076
+ };
4077
+ }
4078
+ function findZone(zones, keys) {
4079
+ const byKey = /* @__PURE__ */ new Map();
4080
+ for (const zone of zones) {
4081
+ for (const key of zoneKeys(zone)) if (!byKey.has(key)) byKey.set(key, zone);
4082
+ }
4083
+ for (const key of keys) {
4084
+ const zone = byKey.get(key);
4085
+ if (zone) return zone;
4086
+ }
4087
+ return void 0;
4088
+ }
4089
+ function zoneKeys(zone) {
4090
+ if (zone.kind === "everywhere" /* EVERYWHERE */) return [EVERYWHERE_KEY];
4091
+ return zone.places.map(placeKey).filter((key) => Boolean(key));
4092
+ }
4093
+ function isOffered(option, zone, channel) {
4094
+ if (!option.channels.some((c) => c === channel)) return false;
4095
+ if (option.type === "pickup" /* PICKUP */) return channel !== "pos" /* POS */;
4096
+ return zone.ships;
4097
+ }
4098
+ function priceForTotal(option, itemsTotal) {
4099
+ const tiers = [...option.priceByTotal ?? []].sort((a, b) => a.from - b.from);
4100
+ let price = option.price;
4101
+ for (const tier of tiers) if (itemsTotal >= tier.from) price = tier.price;
4102
+ if (option.freeOver != null && itemsTotal >= option.freeOver) return 0;
4103
+ return price;
4104
+ }
4105
+ function quote(option, zoneId, itemsTotal) {
4106
+ const amount = priceForTotal(option, itemsTotal);
4107
+ const freeOver = option.freeOver ?? null;
4108
+ return {
4109
+ optionId: option.id,
4110
+ zoneId,
4111
+ type: option.type,
4112
+ name: option.name?.trim() || null,
4113
+ amount,
4114
+ amountToFree: freeOver != null && amount > 0 ? freeOver - itemsTotal : null,
4115
+ minDays: option.minDays ?? null,
4116
+ maxDays: option.maxDays ?? null,
4117
+ outletId: option.outletId ?? null
4118
+ };
4119
+ }
4120
+ function countriesShippedTo(zones) {
4121
+ const countries = /* @__PURE__ */ new Set();
4122
+ for (const zone of zones) {
4123
+ if (!zone.ships) continue;
4124
+ for (const key of zoneKeys(zone)) if (key !== EVERYWHERE_KEY) countries.add(key.slice(0, 2));
4125
+ }
4126
+ return [...countries].sort();
4127
+ }
4128
+
4129
+ // shipping/validate.ts
4130
+ function validateShippingZone(zone) {
4131
+ const problems = [...placeProblems(zone)];
4132
+ for (const option of zone.options) problems.push(...optionProblems(option));
4133
+ const reachesWebsite = zone.options.some((option) => option.channels.includes("web" /* WEB */));
4134
+ if (zone.ships && !reachesWebsite) problems.push({ code: "NO_WEBSITE_OPTION" /* NO_WEBSITE_OPTION */ });
4135
+ return problems;
4136
+ }
4137
+ function placeProblems(zone) {
4138
+ if (zone.kind === "everywhere" /* EVERYWHERE */) {
4139
+ return zone.places.length ? [{ code: "INVALID_PLACE" /* INVALID_PLACE */ }] : [];
4140
+ }
4141
+ if (zone.places.length === 0) return [{ code: "NO_PLACES" /* NO_PLACES */ }];
4142
+ if (!zone.places.every((place) => fitsKind(place, zone.kind))) return [{ code: "INVALID_PLACE" /* INVALID_PLACE */ }];
4143
+ const keys = zone.places.map(placeKey);
4144
+ if (keys.some((key) => !key)) return [{ code: "INVALID_PLACE" /* INVALID_PLACE */ }];
4145
+ if (new Set(keys).size !== keys.length) return [{ code: "DUPLICATE_PLACE" /* DUPLICATE_PLACE */ }];
4146
+ return [];
4147
+ }
4148
+ function fitsKind(place, kind) {
4149
+ const hasProvince = Boolean(place.province?.trim());
4150
+ const hasCity = Boolean(place.city?.trim());
4151
+ if (kind === "country" /* COUNTRY */) return !hasProvince && !hasCity;
4152
+ if (kind === "province" /* PROVINCE */) return hasProvince && !hasCity;
4153
+ if (kind === "city" /* CITY */) return hasProvince && hasCity;
4154
+ return false;
4155
+ }
4156
+ var isAmount = (value) => Number.isInteger(value) && value >= 0;
4157
+ var isDays = (value) => value == null || isAmount(value);
4158
+ function optionProblems(option) {
4159
+ const problems = [];
4160
+ const isPickup = option.type === "pickup" /* PICKUP */;
4161
+ if (!isAmount(option.price) || option.freeOver != null && !isAmount(option.freeOver)) {
4162
+ problems.push("INVALID_PRICE" /* INVALID_PRICE */);
4163
+ }
4164
+ if (!isPickup && !option.name?.trim()) problems.push("MISSING_NAME" /* MISSING_NAME */);
4165
+ if (!isDays(option.minDays) || !isDays(option.maxDays) || (option.minDays ?? 0) > (option.maxDays ?? Infinity)) {
4166
+ problems.push("INVALID_DAYS" /* INVALID_DAYS */);
4167
+ }
4168
+ if (!tiersAreValid(option)) problems.push("INVALID_TIERS" /* INVALID_TIERS */);
4169
+ if (option.channels.length === 0) problems.push("NO_CHANNEL" /* NO_CHANNEL */);
4170
+ if (isPickup && !option.outletId) problems.push("PICKUP_WITHOUT_STORE" /* PICKUP_WITHOUT_STORE */);
4171
+ return problems.map((code) => ({ code, optionId: option.id }));
4172
+ }
4173
+ function tiersAreValid(option) {
4174
+ const tiers = option.priceByTotal ?? [];
4175
+ const froms = tiers.map((tier) => tier.from);
4176
+ return tiers.every((tier) => Number.isInteger(tier.from) && tier.from > 0 && isAmount(tier.price)) && new Set(froms).size === froms.length;
4177
+ }
4178
+
3795
4179
  // constants/adyen.constants.ts
3796
4180
  var ADYEN_ROLLOUT_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
3797
4181
  function isAdyenRolloutCountry(alpha2) {
@@ -3840,6 +4224,27 @@ var BNPL_SKIP_REASON = {
3840
4224
  NO_CURRENCY: "no_currency",
3841
4225
  NO_BUSINESS_LINE: "no_business_line"
3842
4226
  };
4227
+
4228
+ // pos-types/active/ProcessorType.ts
4229
+ var ProcessorType = /* @__PURE__ */ ((ProcessorType2) => {
4230
+ ProcessorType2["FINAL_PAY"] = "Terminal";
4231
+ ProcessorType2["TAP_TO_PAY"] = "TapToPay";
4232
+ ProcessorType2["MOTO"] = "Moto";
4233
+ ProcessorType2["CLOUD"] = "Cloud";
4234
+ ProcessorType2["BLUETOOTH"] = "Bluetooth";
4235
+ ProcessorType2["CASH"] = "Cash";
4236
+ ProcessorType2["CUSTOM_PAY"] = "CustomPay";
4237
+ ProcessorType2["VENDARA"] = "Vendara";
4238
+ ProcessorType2["REDEEM"] = "Redeem";
4239
+ ProcessorType2["INTEGRATION"] = "Integration";
4240
+ ProcessorType2["PAYMENT_LINK"] = "PaymentLink";
4241
+ ProcessorType2["ONLINE_PAYMENT"] = "OnlinePayment";
4242
+ ProcessorType2["EXTERNAL"] = "External";
4243
+ return ProcessorType2;
4244
+ })(ProcessorType || {});
4245
+
4246
+ // constants/payment-channel.constants.ts
4247
+ var PAYMENT_CHANNELS = ["inPerson", "online"];
3843
4248
  // Annotate the CommonJS export names for ESM import in node:
3844
4249
  0 && (module.exports = {
3845
4250
  ADYEN_JOB_TITLE_ASSOCIATION_TYPES,
@@ -3859,6 +4264,7 @@ var BNPL_SKIP_REASON = {
3859
4264
  BookingResourceStatus,
3860
4265
  BookingRulesError,
3861
4266
  BookingType,
4267
+ CANADA_PROVINCES,
3862
4268
  CONDITION_OPERATORS,
3863
4269
  COUNTRY_CURRENCIES,
3864
4270
  CURRENCY_CONFIG,
@@ -3875,6 +4281,7 @@ var BNPL_SKIP_REASON = {
3875
4281
  DualWriteStrategy,
3876
4282
  EUFixedRates,
3877
4283
  EUROPE,
4284
+ EVERYWHERE_KEY,
3878
4285
  ExtensionCategory,
3879
4286
  FINANCIAL_INVARIANTS,
3880
4287
  FULFILLMENT_STATES,
@@ -3896,6 +4303,7 @@ var BNPL_SKIP_REASON = {
3896
4303
  OtherFixedRates,
3897
4304
  OwnerType,
3898
4305
  PATH_MODES,
4306
+ PAYMENT_CHANNELS,
3899
4307
  PAYMENT_STATES,
3900
4308
  POS_VALID_INITIAL_STATES,
3901
4309
  PaymentMethod,
@@ -3905,6 +4313,7 @@ var BNPL_SKIP_REASON = {
3905
4313
  PricingLevel,
3906
4314
  PricingPlanEnum,
3907
4315
  PricingRegionEnum,
4316
+ ProcessorType,
3908
4317
  ProductStatus,
3909
4318
  ProductType,
3910
4319
  PublicationAvailability,
@@ -3923,6 +4332,12 @@ var BNPL_SKIP_REASON = {
3923
4332
  SYSTEM_FAMILY_IDS,
3924
4333
  SYSTEM_UNITS,
3925
4334
  SYSTEM_UNIT_IDS,
4335
+ ShippingChannel,
4336
+ ShippingNoOptionReason,
4337
+ ShippingOptionType,
4338
+ ShippingRateType,
4339
+ ShippingZoneError,
4340
+ ShippingZoneKind,
3926
4341
  StationStatus,
3927
4342
  StripeCurrencyCode,
3928
4343
  StripeStatus,
@@ -3930,6 +4345,7 @@ var BNPL_SKIP_REASON = {
3930
4345
  TopMetericsSort,
3931
4346
  UserTypes,
3932
4347
  addAmounts,
4348
+ addressPlaceKeys,
3933
4349
  adyenLegalEntityRequiresStateOrProvince,
3934
4350
  adyenRequiresJobTitle,
3935
4351
  adyenStoreRequiresStateOrProvince,
@@ -4008,25 +4424,37 @@ var BNPL_SKIP_REASON = {
4008
4424
  isSystemFamilyCode,
4009
4425
  isValidQuantity,
4010
4426
  isWhole,
4427
+ listCountries,
4428
+ listProvinces,
4011
4429
  mapToLegacyStatus,
4012
4430
  maxPrecisionFor,
4013
4431
  mergeFragment,
4014
4432
  modifiersSellable,
4015
4433
  multiplyAmount,
4434
+ normalizeAddress,
4435
+ normalizeCityKey,
4436
+ normalizeCountry,
4016
4437
  normalizeMongoIdString,
4438
+ normalizePostCode,
4439
+ normalizeProvince,
4017
4440
  occupancyIn,
4018
4441
  parseAmountToMinorUnits,
4019
4442
  parseCurrencyCode,
4020
4443
  parseStripeCurrencyCode,
4444
+ placeKey,
4021
4445
  planWindow,
4022
4446
  poolDemand,
4023
4447
  poolOf,
4024
4448
  poolShortfall,
4025
4449
  poolStockAt,
4450
+ postCodeMatchesProvince,
4026
4451
  presentAt,
4452
+ priceForTotal,
4453
+ provincesForPostCode,
4027
4454
  removeFragment,
4028
4455
  resolveFamily,
4029
4456
  resolveModifiersForProduct,
4457
+ resolveShipping,
4030
4458
  resolveTemplate,
4031
4459
  resolveUnit,
4032
4460
  roundToPrecision,
@@ -4043,6 +4471,7 @@ var BNPL_SKIP_REASON = {
4043
4471
  validateConfig,
4044
4472
  validateFragmentCompatibility,
4045
4473
  validateOrderStatuses,
4474
+ validateShippingZone,
4046
4475
  violatesFinancialInvariant,
4047
4476
  windowEndsAt,
4048
4477
  withinPresence