@01.software/sdk 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +375 -2
  2. package/MIGRATION.md +89 -10
  3. package/README.md +451 -109
  4. package/dist/{server-nXOezi4b.d.cts → catalog-mappers-sIshKNb3.d.cts} +14 -3
  5. package/dist/{server-nXOezi4b.d.ts → catalog-mappers-sIshKNb3.d.ts} +14 -3
  6. package/dist/client.cjs +2680 -345
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.d.cts +10 -7
  9. package/dist/client.d.ts +10 -7
  10. package/dist/client.js +2680 -345
  11. package/dist/client.js.map +1 -1
  12. package/dist/{collection-client-U70KizLf.d.cts → collection-client-BSo7VXQE.d.cts} +8 -5
  13. package/dist/{collection-client-gWsA7BVP.d.ts → collection-client-Ckfusuee.d.ts} +8 -5
  14. package/dist/{const-_WWHU-gX.d.ts → const-BAG0MH0u.d.cts} +13 -10
  15. package/dist/{const-BBynifk0.d.cts → const-CaPq2AE4.d.ts} +13 -10
  16. package/dist/errors.cjs +74 -1
  17. package/dist/errors.cjs.map +1 -1
  18. package/dist/errors.d.cts +38 -1
  19. package/dist/errors.d.ts +38 -1
  20. package/dist/errors.js +74 -1
  21. package/dist/errors.js.map +1 -1
  22. package/dist/{index-DPi5NWU8.d.ts → index-BNICJxBL.d.ts} +4 -4
  23. package/dist/{index-Dg4Y6Aq7.d.cts → index-YGrZrxNn.d.cts} +4 -4
  24. package/dist/index.cjs +2741 -368
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +18 -19
  27. package/dist/index.d.ts +18 -19
  28. package/dist/index.js +2741 -368
  29. package/dist/index.js.map +1 -1
  30. package/dist/{payload-types-DLxkB7Mv.d.cts → payload-types-CJZuXcgF.d.cts} +6873 -4208
  31. package/dist/{payload-types-DLxkB7Mv.d.ts → payload-types-CJZuXcgF.d.ts} +6873 -4208
  32. package/dist/query.cjs +550 -101
  33. package/dist/query.cjs.map +1 -1
  34. package/dist/query.d.cts +43 -45
  35. package/dist/query.d.ts +43 -45
  36. package/dist/query.js +550 -101
  37. package/dist/query.js.map +1 -1
  38. package/dist/realtime.cjs.map +1 -1
  39. package/dist/realtime.d.cts +2 -2
  40. package/dist/realtime.d.ts +2 -2
  41. package/dist/realtime.js.map +1 -1
  42. package/dist/server.cjs +2252 -444
  43. package/dist/server.cjs.map +1 -1
  44. package/dist/server.d.cts +11 -10
  45. package/dist/server.d.ts +11 -10
  46. package/dist/server.js +2252 -444
  47. package/dist/server.js.map +1 -1
  48. package/dist/storefront-cache.cjs +65 -1
  49. package/dist/storefront-cache.cjs.map +1 -1
  50. package/dist/storefront-cache.js +65 -1
  51. package/dist/storefront-cache.js.map +1 -1
  52. package/dist/types-BC6rVmJa.d.ts +47 -0
  53. package/dist/{types-B9lGhZlB.d.ts → types-BlOvjoTX.d.ts} +1095 -504
  54. package/dist/{types-Bpx5sYKo.d.cts → types-C4WuJfw7.d.cts} +1095 -504
  55. package/dist/types-D5p7-m1l.d.cts +47 -0
  56. package/dist/ui/canvas/server.cjs +244 -2
  57. package/dist/ui/canvas/server.cjs.map +1 -1
  58. package/dist/ui/canvas/server.d.cts +27 -1
  59. package/dist/ui/canvas/server.d.ts +27 -1
  60. package/dist/ui/canvas/server.js +244 -2
  61. package/dist/ui/canvas/server.js.map +1 -1
  62. package/dist/ui/canvas.cjs +419 -103
  63. package/dist/ui/canvas.cjs.map +1 -1
  64. package/dist/ui/canvas.d.cts +19 -7
  65. package/dist/ui/canvas.d.ts +19 -7
  66. package/dist/ui/canvas.js +419 -103
  67. package/dist/ui/canvas.js.map +1 -1
  68. package/dist/ui/form.d.cts +1 -1
  69. package/dist/ui/form.d.ts +1 -1
  70. package/dist/ui/video.d.cts +1 -1
  71. package/dist/ui/video.d.ts +1 -1
  72. package/dist/webhook.cjs +2 -1
  73. package/dist/webhook.cjs.map +1 -1
  74. package/dist/webhook.d.cts +4 -4
  75. package/dist/webhook.d.ts +4 -4
  76. package/dist/webhook.js +2 -1
  77. package/dist/webhook.js.map +1 -1
  78. package/package.json +12 -11
  79. package/dist/types-B1ngKbWI.d.cts +0 -33
  80. package/dist/types-BiKNBwRA.d.ts +0 -33
package/dist/index.cjs CHANGED
@@ -23,11 +23,11 @@ __export(src_exports, {
23
23
  ApiError: () => ApiError,
24
24
  AuthError: () => AuthError,
25
25
  COLLECTIONS: () => COLLECTIONS,
26
+ COMMERCE_ERROR_CODES: () => COMMERCE_ERROR_CODES,
26
27
  COMMERCE_NOTIFICATION_EVENTS: () => COMMERCE_NOTIFICATION_EVENTS,
27
28
  COMMERCE_NOTIFICATION_EVENT_TYPE: () => COMMERCE_NOTIFICATION_EVENT_TYPE,
28
29
  COMMERCE_NOTIFICATION_OPERATION: () => COMMERCE_NOTIFICATION_OPERATION,
29
30
  CUSTOMER_PASSWORD_RESET_OPERATION: () => CUSTOMER_PASSWORD_RESET_OPERATION,
30
- CartApi: () => CartApi,
31
31
  CommerceClient: () => CommerceClient,
32
32
  CommunityClient: () => CommunityClient,
33
33
  ConfigError: () => ConfigError,
@@ -35,10 +35,12 @@ __export(src_exports, {
35
35
  ContentClient: () => ContentClient,
36
36
  CustomerAuth: () => CustomerAuth,
37
37
  CustomerNamespace: () => CustomerNamespace,
38
+ CustomerOAuth: () => CustomerOAuth,
38
39
  EventsClient: () => EventsClient,
39
40
  GoneError: () => GoneError,
40
41
  IMAGE_SIZES: () => IMAGE_SIZES,
41
42
  INTERNAL_COLLECTIONS: () => INTERNAL_COLLECTIONS,
43
+ MAX_CART_LINE_ADMISSIONS: () => MAX_CART_LINE_ADMISSIONS,
42
44
  NetworkError: () => NetworkError,
43
45
  NotFoundError: () => NotFoundError,
44
46
  ORDER_CHANGED_EVENT_TYPE: () => ORDER_CHANGED_EVENT_TYPE,
@@ -56,6 +58,7 @@ __export(src_exports, {
56
58
  TimeoutError: () => TimeoutError,
57
59
  UsageLimitError: () => UsageLimitError,
58
60
  ValidationError: () => ValidationError,
61
+ assertCommerceIdempotencyKey: () => assertCommerceIdempotencyKey,
59
62
  buildProductHref: () => buildProductHref,
60
63
  buildProductListingCard: () => buildProductListingCard,
61
64
  buildProductListingGroupProjection: () => buildProductListingGroupProjection,
@@ -66,6 +69,7 @@ __export(src_exports, {
66
69
  createAuthError: () => createAuthError,
67
70
  createClient: () => createClient2,
68
71
  createCommerceEmailWebhookHandler: () => createCommerceEmailWebhookHandler,
72
+ createCommerceIdempotencyKey: () => createCommerceIdempotencyKey,
69
73
  createCommerceNotificationWebhookHandler: () => createCommerceNotificationWebhookHandler,
70
74
  createConflictError: () => createConflictError,
71
75
  createCustomerAuthWebhookHandler: () => createCustomerAuthWebhookHandler,
@@ -96,7 +100,9 @@ __export(src_exports, {
96
100
  handleWebhook: () => handleWebhook,
97
101
  isApiError: () => isApiError,
98
102
  isAuthError: () => isAuthError,
103
+ isCommerceIdempotencyKey: () => isCommerceIdempotencyKey,
99
104
  isCommerceNotificationWebhookEvent: () => isCommerceNotificationWebhookEvent,
105
+ isCommerceSDKError: () => isCommerceSDKError,
100
106
  isConfigError: () => isConfigError,
101
107
  isConflictError: () => isConflictError,
102
108
  isCustomerPasswordResetWebhookEvent: () => isCustomerPasswordResetWebhookEvent,
@@ -167,10 +173,136 @@ var SDKError = class extends Error {
167
173
  details: this.details,
168
174
  userMessage: this.userMessage,
169
175
  suggestion: this.suggestion,
170
- ...this.requestId !== void 0 && { requestId: this.requestId }
176
+ ...this.requestId !== void 0 && { requestId: this.requestId },
177
+ ...this.kind !== void 0 && { kind: this.kind },
178
+ ...this.reason !== void 0 && { reason: this.reason },
179
+ ...this.rawReason !== void 0 && { rawReason: this.rawReason },
180
+ ...this.retryable !== void 0 && { retryable: this.retryable },
181
+ ...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
171
182
  };
172
183
  }
173
184
  };
185
+ var COMMERCE_ERROR_CODES = [
186
+ "validation_failed",
187
+ "unauthorized",
188
+ "forbidden",
189
+ "token_expired",
190
+ "origin_not_allowed",
191
+ "server_credentials_required",
192
+ "not_found",
193
+ "conflict",
194
+ "cart_revision_conflict",
195
+ "rate_limit_exceeded",
196
+ "usage_limit_exceeded",
197
+ "service_unavailable",
198
+ "idempotency_conflict",
199
+ "idempotency_in_progress",
200
+ "cart_not_active",
201
+ "cart_locked",
202
+ "cart_empty",
203
+ "cart_market_unavailable",
204
+ "cart_market_mismatch",
205
+ "checkout_not_open",
206
+ "payment_slot_held",
207
+ "reservation_expired",
208
+ "payment_session_not_cancelable",
209
+ "provider_identity_mismatch",
210
+ "provider_unavailable",
211
+ "lock_timeout",
212
+ "price_changed",
213
+ "pricing_fact_in_use",
214
+ "insufficient_stock",
215
+ "market_not_found",
216
+ "market_shipping_currency_unsupported",
217
+ "missing_market_rate",
218
+ "missing_shipping_amount",
219
+ "no_enabled_payment_provider",
220
+ "product_market_unavailable",
221
+ "unsupported_currency",
222
+ "missing_price_row",
223
+ "payment_provider_currency_unsupported",
224
+ "discount_code_not_found",
225
+ "discount_not_started",
226
+ "discount_expired",
227
+ "discount_usage_limit",
228
+ "discount_per_customer_limit",
229
+ "discount_customer_required",
230
+ "discount_first_order_only",
231
+ "discount_customer_not_eligible",
232
+ "discount_customer_excluded",
233
+ "discount_items_required",
234
+ "discount_product_not_eligible",
235
+ "discount_product_excluded",
236
+ "discount_min_order_amount",
237
+ "discount_currency_scope_required",
238
+ "discount_allocation_method_unsupported",
239
+ "currency_mismatch"
240
+ ];
241
+ var COMMERCE_ERROR_CODE_SET = new Set(
242
+ COMMERCE_ERROR_CODES
243
+ );
244
+ var COMMERCE_ERROR_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
245
+ "error",
246
+ "reason",
247
+ "requestId",
248
+ "retryable",
249
+ "details"
250
+ ]);
251
+ function isPlainRecord(value) {
252
+ return typeof value === "object" && value !== null && !Array.isArray(value);
253
+ }
254
+ function commerceProtocolError(issue, trustedRequestId) {
255
+ return createApiError(
256
+ "Invalid canonical commerce error response.",
257
+ 502,
258
+ { protocol: "commerce-error-envelope", issue },
259
+ "The server returned an incompatible commerce error response.",
260
+ "Verify that the Console commerce contract is deployed before using this SDK version.",
261
+ trustedRequestId
262
+ );
263
+ }
264
+ function parseCommerceErrorEnvelope(body, headerRequestId) {
265
+ if (!isPlainRecord(body)) {
266
+ throw commerceProtocolError("expected_object", headerRequestId);
267
+ }
268
+ if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {
269
+ throw commerceProtocolError("unexpected_field", headerRequestId);
270
+ }
271
+ if (typeof body.error !== "string" || body.error.length === 0 || typeof body.reason !== "string" || body.reason.length === 0 || typeof body.requestId !== "string" || body.requestId.length === 0 || body.retryable !== void 0 && typeof body.retryable !== "boolean" || body.details !== void 0 && !isPlainRecord(body.details)) {
272
+ throw commerceProtocolError("invalid_field", headerRequestId);
273
+ }
274
+ if (headerRequestId && headerRequestId !== body.requestId) {
275
+ throw commerceProtocolError("request_id_mismatch", headerRequestId);
276
+ }
277
+ return {
278
+ error: body.error,
279
+ reason: body.reason,
280
+ requestId: body.requestId,
281
+ retryable: body.retryable === true,
282
+ ...body.details === void 0 ? {} : { details: body.details }
283
+ };
284
+ }
285
+ function enhanceCommerceError(error, body, headerRequestId) {
286
+ const envelope = parseCommerceErrorEnvelope(body, headerRequestId);
287
+ const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason);
288
+ Object.assign(error, {
289
+ code: envelope.reason,
290
+ kind: "commerce",
291
+ reason: known ? envelope.reason : "unknown_commerce_error",
292
+ ...known ? {} : { rawReason: envelope.reason },
293
+ requestId: envelope.requestId,
294
+ retryable: envelope.retryable,
295
+ details: envelope.details
296
+ });
297
+ return error;
298
+ }
299
+ function isCommerceSDKError(error) {
300
+ if (!(error instanceof SDKError) || error.kind !== "commerce") return false;
301
+ if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
302
+ return false;
303
+ }
304
+ return error.reason === "unknown_commerce_error" ? typeof error.rawReason === "string" : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === void 0;
305
+ }
174
306
  var NetworkError = class extends SDKError {
175
307
  constructor(message, status, details, userMessage, suggestion) {
176
308
  super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
@@ -409,6 +541,7 @@ var NON_RETRYABLE_STATUSES = [400, 401, 403, 404, 409, 422];
409
541
  var SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
410
542
  var DEFAULT_MAX_RETRIES = 3;
411
543
  var STOREFRONT_BROWSER_MAX_RETRIES = 1;
544
+ var MAX_AUTOMATIC_RETRY_AFTER_SECONDS = 5 * 60;
412
545
  function debugLog(debug, type, message, data) {
413
546
  if (!debug) return;
414
547
  const shouldLog = debug === true || type === "request" && debug.logRequests || type === "response" && debug.logResponses || type === "error" && debug.logErrors;
@@ -523,116 +656,129 @@ function attachRequestId(err, id) {
523
656
  }
524
657
  function parseRetryAfter(response) {
525
658
  const raw = response.headers.get("Retry-After");
526
- if (!raw) return void 0;
527
- return parseInt(raw, 10) || void 0;
659
+ if (!raw) return { permitsAutomaticRetry: true };
660
+ const trimmed = raw.trim();
661
+ let seconds;
662
+ if (/^\d+$/.test(trimmed)) {
663
+ seconds = Number(trimmed);
664
+ if (!Number.isSafeInteger(seconds)) {
665
+ return { permitsAutomaticRetry: false };
666
+ }
667
+ } else {
668
+ const retryAt = Date.parse(trimmed);
669
+ if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
670
+ seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
671
+ }
672
+ return {
673
+ seconds,
674
+ permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
675
+ };
528
676
  }
529
- function mapResponseToError(status, parsed, details, requestId, retryAfter) {
677
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
530
678
  const errorDetails = {
531
679
  ...details,
532
680
  ...parsed.errors && { errors: parsed.errors },
533
- ...parsed.body && { body: parsed.body }
681
+ ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
534
682
  };
535
683
  const suggestion = getParsedErrorSuggestion(status, parsed);
684
+ const finalize = (error) => {
685
+ const withRequestId = attachRequestId(error, requestId);
686
+ if (retryAfter !== void 0) {
687
+ Object.assign(withRequestId, { retryAfter });
688
+ }
689
+ return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
690
+ };
536
691
  if (status === 400 || status === 422) {
537
- return attachRequestId(
692
+ return finalize(
538
693
  createValidationError(
539
694
  parsed.errorMessage,
540
695
  errorDetails,
541
696
  parsed.userMessage,
542
697
  suggestion,
543
698
  status
544
- ),
545
- requestId
699
+ )
546
700
  );
547
701
  }
548
702
  if (status === 401) {
549
- return attachRequestId(
703
+ return finalize(
550
704
  createAuthError(
551
705
  parsed.errorMessage,
552
706
  errorDetails,
553
707
  parsed.userMessage,
554
708
  suggestion
555
- ),
556
- requestId
709
+ )
557
710
  );
558
711
  }
559
712
  if (status === 403) {
560
- return attachRequestId(
713
+ return finalize(
561
714
  createPermissionError(
562
715
  parsed.errorMessage,
563
716
  errorDetails,
564
717
  parsed.userMessage,
565
718
  suggestion
566
- ),
567
- requestId
719
+ )
568
720
  );
569
721
  }
570
722
  if (status === 404) {
571
- return attachRequestId(
723
+ return finalize(
572
724
  createNotFoundError(
573
725
  parsed.errorMessage,
574
726
  errorDetails,
575
727
  parsed.userMessage,
576
728
  suggestion
577
- ),
578
- requestId
729
+ )
579
730
  );
580
731
  }
581
732
  if (status === 409) {
582
- return attachRequestId(
733
+ return finalize(
583
734
  createConflictError(
584
735
  parsed.errorMessage,
585
736
  errorDetails,
586
737
  parsed.userMessage,
587
738
  suggestion
588
- ),
589
- requestId
739
+ )
590
740
  );
591
741
  }
592
742
  if (status === 410) {
593
- return attachRequestId(
743
+ return finalize(
594
744
  createGoneError(
595
745
  parsed.errorMessage,
596
746
  errorDetails,
597
747
  parsed.userMessage,
598
748
  suggestion
599
- ),
600
- requestId
749
+ )
601
750
  );
602
751
  }
603
752
  if (status === 429) {
604
- return attachRequestId(
753
+ return finalize(
605
754
  createRateLimitError(
606
755
  parsed.errorMessage,
607
756
  retryAfter,
608
757
  errorDetails,
609
758
  parsed.userMessage,
610
759
  suggestion
611
- ),
612
- requestId
760
+ )
613
761
  );
614
762
  }
615
763
  if (status === 503) {
616
- return attachRequestId(
764
+ return finalize(
617
765
  createServiceUnavailableError(
618
766
  parsed.errorMessage,
619
767
  retryAfter,
620
768
  errorDetails,
621
769
  parsed.userMessage,
622
770
  suggestion
623
- ),
624
- requestId
771
+ )
625
772
  );
626
773
  }
627
- return attachRequestId(
774
+ return finalize(
628
775
  createNetworkError(
629
776
  parsed.errorMessage,
630
777
  status,
631
778
  errorDetails,
632
779
  parsed.userMessage,
633
780
  suggestion
634
- ),
635
- requestId
781
+ )
636
782
  );
637
783
  }
638
784
  async function httpFetch(url, options) {
@@ -645,6 +791,7 @@ async function httpFetch(url, options) {
645
791
  debug,
646
792
  retry,
647
793
  onUnauthorized,
794
+ errorFamily,
648
795
  ...requestInit
649
796
  } = options || {};
650
797
  const baseUrl = resolveApiUrl(apiUrl);
@@ -697,6 +844,8 @@ async function httpFetch(url, options) {
697
844
  headers: redactSensitiveHeaders(response.headers)
698
845
  });
699
846
  if (!response.ok) {
847
+ const parsed = await parseErrorBody(response);
848
+ const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
700
849
  if (isUsageLimitExceededResponse(response)) {
701
850
  const limit = parseInt(
702
851
  response.headers.get("X-Usage-Limit") || "0",
@@ -710,7 +859,7 @@ async function httpFetch(url, options) {
710
859
  response.headers.get("X-Usage-Remaining") || "0",
711
860
  10
712
861
  );
713
- throw attachRequestId(
862
+ const usageError = attachRequestId(
714
863
  createUsageLimitError(
715
864
  `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
716
865
  { limit, current, remaining },
@@ -724,9 +873,9 @@ async function httpFetch(url, options) {
724
873
  ),
725
874
  requestId
726
875
  );
876
+ throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
727
877
  }
728
- const parsed = await parseErrorBody(response);
729
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
878
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
730
879
  hasRetried401 = true;
731
880
  try {
732
881
  const newToken = await onUnauthorized();
@@ -748,13 +897,18 @@ async function httpFetch(url, options) {
748
897
  parsed,
749
898
  details,
750
899
  requestId,
751
- retryAfter
900
+ retryAfter.seconds,
901
+ errorFamily
752
902
  );
753
903
  const method2 = (requestInit.method || "GET").toUpperCase();
754
904
  const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
755
- if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
905
+ const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
906
+ if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
756
907
  lastError = error;
757
- const retryDelay = retryConfig.retryDelay(attempt);
908
+ const retryDelay = Math.max(
909
+ retryConfig.retryDelay(attempt),
910
+ (retryAfter.seconds ?? 0) * 1e3
911
+ );
758
912
  debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
759
913
  await delay(retryDelay);
760
914
  continue;
@@ -824,87 +978,45 @@ async function httpFetch(url, options) {
824
978
  throw lastError ?? new NetworkError("Request failed after retries");
825
979
  }
826
980
 
827
- // src/core/api/endpoints.ts
828
- var COMMERCE_ENDPOINTS = {
829
- orders: {
830
- create: "/api/orders/create",
831
- update: "/api/orders/update",
832
- confirmPayment: "/api/orders/confirm-payment",
833
- byPayment: "/api/orders/by-payment",
834
- cancel: "/api/orders/cancel",
835
- resolveCancelRefund: "/api/orders/resolve-cancel-refund",
836
- checkout: "/api/orders/checkout",
837
- createFulfillment: "/api/orders/create-fulfillment",
838
- updateFulfillment: "/api/orders/update-fulfillment"
839
- },
840
- transactions: {
841
- update: "/api/transactions/update"
842
- },
843
- returns: {
844
- create: "/api/returns/create",
845
- update: "/api/returns/update",
846
- returnRefund: "/api/returns/return-refund"
847
- },
848
- fulfillmentOrders: {
849
- prepare: "/api/fulfillment-orders/prepare-fulfillment-order"
850
- },
851
- fulfillments: {
852
- bulkImport: "/api/fulfillments/bulk-import"
853
- },
854
- carts: {
855
- mine: "/api/carts/mine",
856
- merge: "/api/carts/merge",
857
- addItem: "/api/carts/add-item",
858
- updateItem: "/api/carts/update-item",
859
- removeItem: "/api/carts/remove-item",
860
- applyDiscount: "/api/carts/apply-discount",
861
- removeDiscount: "/api/carts/remove-discount",
862
- clear: "/api/carts/clear"
863
- },
864
- products: {
865
- stockCheck: "/api/products/stock-check",
866
- stockSnapshot: "/api/products/stock",
867
- listingGroups: "/api/products/listing-groups",
868
- listingGroupsCatalog: "/api/products/listing-groups/catalog",
869
- listingGroupsQuery: "/api/products/listing-groups/query",
870
- listingGroupsQueryCatalog: "/api/products/listing-groups/query/catalog",
871
- detail: "/api/products/detail",
872
- detailCatalog: "/api/products/detail/catalog",
873
- upsert: "/api/products/upsert"
874
- }
875
- };
876
- var COMMERCE_ENDPOINT_PATHS = Object.values(
877
- COMMERCE_ENDPOINTS
878
- ).flatMap((group) => Object.values(group));
879
- var MEMBERSHIP_ENDPOINTS = {
880
- subscribe: "/api/memberships/subscribe",
881
- cancel: (id) => `/api/memberships/${id}/cancel`,
882
- me: "/api/memberships/me"
883
- };
884
-
885
981
  // src/core/internal/utils/query-string.ts
886
- function productDetailQuery(params) {
887
- const search = new URLSearchParams();
888
- if ("slug" in params) {
889
- search.set("slug", params.slug);
890
- } else {
891
- search.set("id", params.id);
982
+ function normalizedMarket(value) {
983
+ const market = value?.trim();
984
+ return market || void 0;
985
+ }
986
+ function appendProductLocaleSearchParams(search, options) {
987
+ if (options?.locale) search.set("locale", options.locale);
988
+ if (options?.fallbackLocale !== void 0) {
989
+ search.set(
990
+ "fallbackLocale",
991
+ options.fallbackLocale === false ? "none" : options.fallbackLocale
992
+ );
892
993
  }
893
- return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
894
994
  }
895
- function productDetailCatalogQuery(params) {
995
+ function productDetailSearchParams(params) {
896
996
  const search = new URLSearchParams();
897
997
  if ("slug" in params) {
898
998
  search.set("slug", params.slug);
899
999
  } else {
900
1000
  search.set("id", params.id);
901
1001
  }
902
- return `${COMMERCE_ENDPOINTS.products.detailCatalog}?${search}`;
1002
+ const market = normalizedMarket(params.market);
1003
+ if (market) search.set("market", market);
1004
+ appendProductLocaleSearchParams(search, params);
1005
+ return search.toString();
903
1006
  }
904
- function listingGroupsCatalogQuery(params) {
905
- return `${COMMERCE_ENDPOINTS.products.listingGroupsCatalog}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
1007
+ function listingGroupsSearchParams(params) {
1008
+ const ids = params.productIds.map(encodeURIComponent).join(",");
1009
+ const search = new URLSearchParams();
1010
+ const market = normalizedMarket(params.market);
1011
+ if (market) search.set("market", market);
1012
+ appendProductLocaleSearchParams(search, params);
1013
+ const query = search.toString();
1014
+ return `ids=${ids}${query ? `&${query}` : ""}`;
906
1015
  }
907
1016
  function appendListingGroupsQuerySearchParams(search, options) {
1017
+ const market = normalizedMarket(options?.market);
1018
+ if (market) search.set("market", market);
1019
+ appendProductLocaleSearchParams(search, options);
908
1020
  if (options?.page != null) search.set("page", String(options.page));
909
1021
  if (options?.limit != null) search.set("limit", String(options.limit));
910
1022
  if (options?.sort != null) {
@@ -915,20 +1027,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
915
1027
  search.set("whereJson", JSON.stringify(options.where));
916
1028
  }
917
1029
  }
918
- function listingGroupsQueryUrl(options) {
1030
+ function listingPageSearchParams(options) {
919
1031
  const search = new URLSearchParams();
920
1032
  appendListingGroupsQuerySearchParams(search, options);
921
- const query = search.toString();
922
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
923
- }
924
- function listingGroupsQueryCatalogUrl(options) {
925
- const search = new URLSearchParams();
926
- appendListingGroupsQuerySearchParams(search, options);
927
- const query = search.toString();
928
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQueryCatalog}${query ? `?${query}` : ""}`;
1033
+ return search.toString();
929
1034
  }
930
- function stockSnapshotQuery(params) {
931
- return `${COMMERCE_ENDPOINTS.products.stockSnapshot}?variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
1035
+ function stockSnapshotSearchParams(params) {
1036
+ return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
932
1037
  }
933
1038
 
934
1039
  // src/core/collection/http-client.ts
@@ -971,10 +1076,15 @@ var HttpClient = class {
971
1076
  throw err;
972
1077
  }
973
1078
  }
974
- buildUrl(endpoint, options) {
975
- if (!options) return endpoint;
976
- const queryString = (0, import_qs_esm.stringify)(options, { addQueryPrefix: true });
977
- return queryString ? `${endpoint}${queryString}` : endpoint;
1079
+ buildUrl(endpoint2, options) {
1080
+ if (!options) return endpoint2;
1081
+ const { fallbackLocale, ...rest } = options;
1082
+ const queryOptions = fallbackLocale === void 0 ? rest : {
1083
+ ...rest,
1084
+ "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
1085
+ };
1086
+ const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
1087
+ return queryString ? `${endpoint2}${queryString}` : endpoint2;
978
1088
  }
979
1089
  assertJsonResponse(response) {
980
1090
  const contentType = response.headers.get("content-type");
@@ -1123,39 +1233,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
1123
1233
  from(collection) {
1124
1234
  return new ReadOnlyCollectionQueryBuilder(this, collection);
1125
1235
  }
1126
- async requestFind(endpoint, options) {
1127
- const url = this.buildUrl(endpoint, options);
1236
+ async requestFind(endpoint2, options) {
1237
+ const url = this.buildUrl(endpoint2, options);
1128
1238
  const response = await this.fetchWithTracking(url, {
1129
1239
  ...this.defaultOptions,
1130
1240
  method: "GET"
1131
1241
  });
1132
1242
  return this.parseFindResponse(response);
1133
1243
  }
1134
- async requestFindEndpoint(endpoint, data) {
1135
- const response = await this.fetchWithTracking(endpoint, {
1244
+ async requestFindEndpoint(endpoint2, data) {
1245
+ const response = await this.fetchWithTracking(endpoint2, {
1136
1246
  ...this.defaultOptions,
1137
1247
  method: "POST",
1138
1248
  body: data ? JSON.stringify(data) : void 0
1139
1249
  });
1140
1250
  return this.parseFindResponse(response);
1141
1251
  }
1142
- async requestFindEndpointGet(endpoint) {
1143
- const response = await this.fetchWithTracking(endpoint, {
1252
+ async requestFindEndpointGet(endpoint2) {
1253
+ const response = await this.fetchWithTracking(endpoint2, {
1144
1254
  ...this.defaultOptions,
1145
1255
  method: "GET"
1146
1256
  });
1147
1257
  return this.parseFindResponse(response);
1148
1258
  }
1149
- async requestFindById(endpoint, options) {
1150
- const url = this.buildUrl(endpoint, options);
1259
+ async requestFindById(endpoint2, options) {
1260
+ const url = this.buildUrl(endpoint2, options);
1151
1261
  const response = await this.fetchWithTracking(url, {
1152
1262
  ...this.defaultOptions,
1153
1263
  method: "GET"
1154
1264
  });
1155
1265
  return this.parseDocumentResponse(response);
1156
1266
  }
1157
- async requestCount(endpoint, options) {
1158
- const url = this.buildUrl(endpoint, options);
1267
+ async requestCount(endpoint2, options) {
1268
+ const url = this.buildUrl(endpoint2, options);
1159
1269
  const response = await this.fetchWithTracking(url, {
1160
1270
  ...this.defaultOptions,
1161
1271
  method: "GET"
@@ -1165,53 +1275,339 @@ var ReadOnlyCollectionClient = class extends HttpClient {
1165
1275
  };
1166
1276
 
1167
1277
  // src/core/api/parse-response.ts
1168
- async function parseApiResponse(response, endpoint) {
1169
- let data;
1278
+ async function parseApiResponse(response, endpoint2, options = {}) {
1279
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
1280
+ return void 0;
1281
+ }
1282
+ let parsed;
1170
1283
  try {
1171
- data = await response.json();
1284
+ parsed = await response.json();
1172
1285
  } catch {
1173
1286
  throw createApiError(
1174
- `Invalid JSON response from ${endpoint}`,
1287
+ `Invalid JSON response from ${endpoint2}`,
1175
1288
  response.status,
1176
1289
  void 0,
1177
1290
  "Server returned an invalid response.",
1178
1291
  "Check if the API endpoint is available."
1179
1292
  );
1180
1293
  }
1294
+ if (parsed === null || typeof parsed !== "object") {
1295
+ return parsed;
1296
+ }
1297
+ const data = parsed;
1181
1298
  if (data.error) {
1182
1299
  const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1183
1300
  const reason = typeof data.reason === "string" ? data.reason : void 0;
1184
1301
  const requestId = response.headers.get("x-request-id") ?? void 0;
1185
- const retryAfterRaw = response.headers.get("Retry-After");
1186
- const retryAfter = retryAfterRaw ? parseInt(retryAfterRaw, 10) || void 0 : void 0;
1302
+ const retryAfter = parseRetryAfter(response).seconds;
1303
+ let error;
1187
1304
  if (reason === "validation_failed") {
1188
- throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
1189
- }
1190
- if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1191
- throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
1305
+ error = createValidationError(errorMessage, data, errorMessage);
1306
+ } else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1307
+ error = createAuthError(errorMessage, data, errorMessage);
1308
+ } else if (reason === "forbidden") {
1309
+ error = createPermissionError(errorMessage, data, errorMessage);
1310
+ } else if (reason === "rate_limit_exceeded") {
1311
+ error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
1312
+ } else if (reason === "not_found") {
1313
+ error = createNotFoundError(errorMessage, data, errorMessage);
1314
+ } else if (reason === "conflict") {
1315
+ error = createConflictError(errorMessage, data, errorMessage);
1316
+ } else {
1317
+ error = createApiError(
1318
+ errorMessage,
1319
+ response.status,
1320
+ data,
1321
+ errorMessage,
1322
+ "An error occurred while processing the request."
1323
+ );
1192
1324
  }
1193
- if (reason === "forbidden") {
1194
- throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1325
+ const withRequestId = attachRequestId(error, requestId);
1326
+ if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
1327
+ throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
1328
+ }
1329
+ return data;
1330
+ }
1331
+
1332
+ // ../../internal/http-contracts/src/index.ts
1333
+ var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1334
+ var operation = (collection, method, path) => Object.freeze({
1335
+ [operationBrand]: true,
1336
+ collection,
1337
+ method,
1338
+ path
1339
+ });
1340
+ var COMMERCE_ENDPOINT_OPERATIONS = {
1341
+ products: {
1342
+ detail: operation("products", "get", "/detail"),
1343
+ detailCatalog: operation("products", "get", "/detail/catalog"),
1344
+ listingGroups: operation("products", "get", "/listing-groups"),
1345
+ listingGroupsCatalog: operation(
1346
+ "products",
1347
+ "get",
1348
+ "/listing-groups/catalog"
1349
+ ),
1350
+ listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
1351
+ listingGroupsQueryGet: operation(
1352
+ "products",
1353
+ "get",
1354
+ "/listing-groups/query"
1355
+ ),
1356
+ listingGroupsQueryCatalog: operation(
1357
+ "products",
1358
+ "get",
1359
+ "/listing-groups/query/catalog"
1360
+ ),
1361
+ stockCheck: operation("products", "post", "/stock-check"),
1362
+ stockSnapshot: operation("products", "get", "/stock"),
1363
+ upsert: operation("products", "post", "/upsert")
1364
+ },
1365
+ orders: {
1366
+ create: operation("orders", "post", "/create"),
1367
+ update: operation("orders", "post", "/update"),
1368
+ confirmPayment: operation("orders", "post", "/confirm-payment"),
1369
+ byPayment: operation("orders", "get", "/by-payment"),
1370
+ cancel: operation("orders", "post", "/cancel"),
1371
+ resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1372
+ checkout: operation("orders", "post", "/checkout"),
1373
+ createFulfillment: operation("orders", "post", "/create-fulfillment"),
1374
+ updateFulfillment: operation("orders", "post", "/update-fulfillment")
1375
+ },
1376
+ checkouts: {
1377
+ detail: operation("checkouts", "post", "/detail"),
1378
+ query: operation("checkouts", "post", "/query")
1379
+ },
1380
+ transactions: {
1381
+ update: operation("transactions", "post", "/update")
1382
+ },
1383
+ returns: {
1384
+ create: operation("returns", "post", "/create"),
1385
+ update: operation("returns", "post", "/update"),
1386
+ returnRefund: operation("returns", "post", "/return-refund")
1387
+ },
1388
+ fulfillmentOrders: {
1389
+ prepare: operation(
1390
+ "fulfillment-orders",
1391
+ "post",
1392
+ "/prepare-fulfillment-order"
1393
+ )
1394
+ },
1395
+ fulfillments: {
1396
+ bulkImport: operation("fulfillments", "post", "/bulk-import")
1397
+ },
1398
+ carts: {
1399
+ create: operation("carts", "post", "/create"),
1400
+ retrieve: operation("carts", "post", "/retrieve"),
1401
+ mine: operation("carts", "post", "/mine"),
1402
+ merge: operation("carts", "post", "/merge"),
1403
+ addItem: operation("carts", "post", "/add-item"),
1404
+ updateItem: operation("carts", "post", "/update-item"),
1405
+ removeItem: operation("carts", "post", "/remove-item"),
1406
+ updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
1407
+ updateAttributes: operation("carts", "post", "/update-attributes"),
1408
+ clear: operation("carts", "post", "/clear")
1409
+ },
1410
+ paymentSessions: {
1411
+ create: operation("payment-sessions", "post", "/create"),
1412
+ retrieve: operation("payment-sessions", "post", "/retrieve"),
1413
+ cancel: operation("payment-sessions", "post", "/cancel"),
1414
+ server: {
1415
+ create: operation("payment-sessions", "post", "/server/create"),
1416
+ retrieve: operation("payment-sessions", "post", "/server/retrieve"),
1417
+ cancel: operation("payment-sessions", "post", "/server/cancel"),
1418
+ confirm: operation("payment-sessions", "post", "/server/confirm")
1419
+ },
1420
+ custom: {
1421
+ create: operation("orders", "post", "/custom-payment-sessions"),
1422
+ confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
1195
1423
  }
1196
- if (reason === "rate_limit_exceeded") {
1197
- throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1424
+ },
1425
+ shippingPolicies: {
1426
+ calculate: operation("shipping-policies", "post", "/calculate")
1427
+ },
1428
+ discounts: {
1429
+ validate: operation("discounts", "post", "/validate")
1430
+ }
1431
+ };
1432
+ var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1433
+ subscribe: operation(null, "post", "/memberships/subscribe"),
1434
+ cancel: operation(null, "post", "/memberships/:id/cancel"),
1435
+ me: operation(null, "get", "/memberships/me")
1436
+ };
1437
+ var EVENTS_ENDPOINT_OPERATIONS = {
1438
+ occurrences: {
1439
+ range: operation("event-occurrences", "get", "/range"),
1440
+ admissionAvailability: operation(
1441
+ "event-occurrences",
1442
+ "get",
1443
+ "/admission-availability"
1444
+ )
1445
+ }
1446
+ };
1447
+ function resolveOperationTemplate(descriptor) {
1448
+ return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
1449
+ }
1450
+ function resolveOperationPath(descriptor, options) {
1451
+ const path = resolveOperationTemplate(descriptor).replace(
1452
+ /:([A-Za-z][A-Za-z0-9_]*)/g,
1453
+ (_, key) => {
1454
+ const value = options?.pathParams?.[key];
1455
+ if (value === void 0) {
1456
+ throw new TypeError(`Missing path parameter: ${key}`);
1457
+ }
1458
+ return encodeURIComponent(value);
1198
1459
  }
1199
- if (reason === "not_found") {
1200
- throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1460
+ );
1461
+ const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
1462
+ if (unresolved) {
1463
+ throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
1464
+ }
1465
+ const query = options?.query?.toString().replace(/^\?/, "");
1466
+ return query ? `${path}?${query}` : path;
1467
+ }
1468
+ function resolveOperationMethod(descriptor) {
1469
+ return descriptor.method.toUpperCase();
1470
+ }
1471
+
1472
+ // src/core/api/endpoints.ts
1473
+ var endpoint = (method, path) => ({ method, path });
1474
+ var sharedEndpoint = (descriptor) => descriptor;
1475
+ function resolveOperationMethod2(descriptor) {
1476
+ return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1477
+ }
1478
+ function resolveOperationPath2(descriptor, options) {
1479
+ if ("collection" in descriptor) {
1480
+ return resolveOperationPath(descriptor, options);
1481
+ }
1482
+ const query = options?.query?.toString().replace(/^\?/, "");
1483
+ return query ? `${descriptor.path}?${query}` : descriptor.path;
1484
+ }
1485
+ var COMMERCE_ENDPOINTS = {
1486
+ products: {
1487
+ detail: endpoint("GET", "/api/products/detail"),
1488
+ detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1489
+ listingGroups: endpoint("GET", "/api/products/listing-groups"),
1490
+ listingGroupsCatalog: endpoint(
1491
+ "GET",
1492
+ "/api/products/listing-groups/catalog"
1493
+ ),
1494
+ listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1495
+ listingGroupsQueryCatalog: endpoint(
1496
+ "GET",
1497
+ "/api/products/listing-groups/query/catalog"
1498
+ ),
1499
+ stockCheck: endpoint("POST", "/api/products/stock-check"),
1500
+ stockSnapshot: endpoint("GET", "/api/products/stock"),
1501
+ upsert: endpoint("POST", "/api/products/upsert")
1502
+ },
1503
+ orders: {
1504
+ update: endpoint("POST", "/api/orders/update"),
1505
+ byPayment: endpoint("GET", "/api/orders/by-payment"),
1506
+ cancel: endpoint("POST", "/api/orders/cancel"),
1507
+ resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1508
+ createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1509
+ updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1510
+ },
1511
+ checkouts: {
1512
+ create: endpoint("POST", "/api/orders/checkout"),
1513
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1514
+ server: {
1515
+ create: endpoint("POST", "/api/orders/checkout"),
1516
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1517
+ query: endpoint("POST", "/api/checkouts/query")
1201
1518
  }
1202
- if (reason === "conflict") {
1203
- throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1519
+ },
1520
+ returns: {
1521
+ create: endpoint("POST", "/api/returns/create"),
1522
+ update: endpoint("POST", "/api/returns/update"),
1523
+ returnRefund: endpoint("POST", "/api/returns/return-refund")
1524
+ },
1525
+ fulfillmentOrders: {
1526
+ prepare: endpoint(
1527
+ "POST",
1528
+ "/api/fulfillment-orders/prepare-fulfillment-order"
1529
+ )
1530
+ },
1531
+ fulfillments: {
1532
+ bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1533
+ },
1534
+ carts: {
1535
+ create: endpoint("POST", "/api/carts/create"),
1536
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1537
+ mine: endpoint("POST", "/api/carts/mine"),
1538
+ merge: endpoint("POST", "/api/carts/merge"),
1539
+ server: {
1540
+ // Server credentials are an authorization lane, not a second Cart
1541
+ // transport. These must stay bound to the registered shared operations.
1542
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
1543
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1544
+ mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
1545
+ merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
1546
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1547
+ updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
1548
+ removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
1549
+ updateDiscountCodes: sharedEndpoint(
1550
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
1551
+ ),
1552
+ updateAttributes: sharedEndpoint(
1553
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
1554
+ ),
1555
+ clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
1556
+ },
1557
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1558
+ updateItem: endpoint("POST", "/api/carts/update-item"),
1559
+ removeItem: endpoint("POST", "/api/carts/remove-item"),
1560
+ updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
1561
+ updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
1562
+ clear: endpoint("POST", "/api/carts/clear")
1563
+ },
1564
+ paymentSessions: {
1565
+ create: endpoint("POST", "/api/payment-sessions/create"),
1566
+ retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
1567
+ cancel: endpoint("POST", "/api/payment-sessions/cancel"),
1568
+ server: {
1569
+ create: endpoint("POST", "/api/payment-sessions/server/create"),
1570
+ retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
1571
+ cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
1572
+ confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
1204
1573
  }
1205
- throw attachRequestId(
1206
- createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1207
- requestId
1208
- );
1574
+ },
1575
+ shippingPolicies: {
1576
+ calculate: endpoint("POST", "/api/shipping-policies/calculate")
1209
1577
  }
1210
- return data;
1578
+ };
1579
+ function isCommerceEndpointDescriptor(value) {
1580
+ if (!value || typeof value !== "object") return false;
1581
+ const candidate = value;
1582
+ return typeof candidate.method === "string" && typeof candidate.path === "string";
1583
+ }
1584
+ function flattenEndpointPaths(value) {
1585
+ if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1586
+ if (!value || typeof value !== "object") return [];
1587
+ return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1588
+ }
1589
+ function flattenEndpointDescriptors(value) {
1590
+ if (isCommerceEndpointDescriptor(value)) return [value];
1591
+ if (!value || typeof value !== "object") return [];
1592
+ return Object.values(value).flatMap(
1593
+ (entry) => flattenEndpointDescriptors(entry)
1594
+ );
1211
1595
  }
1596
+ var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1597
+ var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1598
+ var MEMBERSHIP_ENDPOINTS = {
1599
+ subscribe: "/api/memberships/subscribe",
1600
+ cancel: (id) => `/api/memberships/${id}/cancel`,
1601
+ me: "/api/memberships/me"
1602
+ };
1603
+ var MEMBERSHIP_ENDPOINT_PATHS = [
1604
+ MEMBERSHIP_ENDPOINTS.subscribe,
1605
+ MEMBERSHIP_ENDPOINTS.cancel(":id"),
1606
+ MEMBERSHIP_ENDPOINTS.me
1607
+ ];
1212
1608
 
1213
1609
  // src/core/api/customer-scoped-api.ts
1214
- var CustomerScopedApi = class {
1610
+ var CustomerScopedTransport = class {
1215
1611
  constructor(apiName, options) {
1216
1612
  if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
1217
1613
  throw createConfigError(
@@ -1229,10 +1625,10 @@ var CustomerScopedApi = class {
1229
1625
  this.onUnauthorized = options.onUnauthorized;
1230
1626
  this.onRequestId = options.onRequestId;
1231
1627
  }
1232
- async request(endpoint, options) {
1628
+ async request(endpoint2, options) {
1233
1629
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1234
1630
  try {
1235
- const response = await httpFetch(endpoint, {
1631
+ const response = await httpFetch(endpoint2, {
1236
1632
  method: options.method,
1237
1633
  apiUrl: this.apiUrl,
1238
1634
  publishableKey: this.publishableKey,
@@ -1242,10 +1638,13 @@ var CustomerScopedApi = class {
1242
1638
  ...options.body !== void 0 && {
1243
1639
  body: JSON.stringify(options.body)
1244
1640
  },
1245
- ...options.headers && { headers: options.headers }
1641
+ ...options.headers && { headers: options.headers },
1642
+ ...options.errorFamily && { errorFamily: options.errorFamily }
1246
1643
  });
1247
1644
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1248
- return parseApiResponse(response, endpoint);
1645
+ return parseApiResponse(response, endpoint2, {
1646
+ errorFamily: options.errorFamily
1647
+ });
1249
1648
  } catch (err) {
1250
1649
  const id = err instanceof SDKError ? err.requestId ?? null : null;
1251
1650
  this.onRequestId?.(id);
@@ -1253,6 +1652,26 @@ var CustomerScopedApi = class {
1253
1652
  }
1254
1653
  }
1255
1654
  };
1655
+ var CustomerScopedApi = class {
1656
+ constructor(apiName, options) {
1657
+ this.transport = new CustomerScopedTransport(apiName, options);
1658
+ }
1659
+ requestEndpoint(endpoint2, body, options) {
1660
+ return this.transport.request(resolveOperationPath2(endpoint2, options), {
1661
+ method: resolveOperationMethod2(endpoint2),
1662
+ body,
1663
+ headers: options?.headers
1664
+ });
1665
+ }
1666
+ };
1667
+ var RawCustomerScopedApi = class {
1668
+ constructor(apiName, options) {
1669
+ this.transport = new CustomerScopedTransport(apiName, options);
1670
+ }
1671
+ request(endpoint2, options) {
1672
+ return this.transport.request(endpoint2, options);
1673
+ }
1674
+ };
1256
1675
 
1257
1676
  // src/core/community/community-client.ts
1258
1677
  var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
@@ -1263,7 +1682,7 @@ function unwrapPayloadDoc(value) {
1263
1682
  }
1264
1683
  return value;
1265
1684
  }
1266
- var CommunityClient = class extends CustomerScopedApi {
1685
+ var CommunityClient = class extends RawCustomerScopedApi {
1267
1686
  constructor(options) {
1268
1687
  super("CommunityClient", { ...options, requiresCredential: false });
1269
1688
  }
@@ -1307,11 +1726,11 @@ var CommunityClient = class extends CustomerScopedApi {
1307
1726
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1308
1727
  return `/api/comments/public?${urlParams.toString()}`;
1309
1728
  }
1310
- async execute(endpoint, method, body) {
1311
- return this.request(endpoint, { method, body });
1729
+ async execute(endpoint2, method, body) {
1730
+ return this.request(endpoint2, { method, body });
1312
1731
  }
1313
- async executeDoc(endpoint, method, body) {
1314
- const response = await this.execute(endpoint, method, body);
1732
+ async executeDoc(endpoint2, method, body) {
1733
+ const response = await this.execute(endpoint2, method, body);
1315
1734
  return unwrapPayloadDoc(response);
1316
1735
  }
1317
1736
  createPost(params) {
@@ -1547,56 +1966,1538 @@ var CommunityClient = class extends CustomerScopedApi {
1547
1966
  body
1548
1967
  );
1549
1968
  }
1550
- };
1551
-
1552
- // src/core/content/content-client.ts
1553
- var PublicContentApi = class extends CustomerScopedApi {
1554
- get(endpoint) {
1555
- return this.request(endpoint, { method: "GET" });
1556
- }
1557
- };
1558
- function appendCommonParams(search, options, defaultSort) {
1559
- search.set("sort", options?.sort ?? defaultSort);
1560
- if (options?.page != null) search.set("page", String(options.page));
1561
- if (options?.limit != null) search.set("limit", String(options.limit));
1562
- }
1563
- function linksListPath(options) {
1564
- const search = new URLSearchParams();
1565
- appendCommonParams(search, options, "-publishedAt,-createdAt");
1566
- if (options?.categoryId) search.set("categoryId", options.categoryId);
1567
- if (options?.categorySlug) {
1568
- search.set("categorySlug", options.categorySlug);
1569
- }
1570
- if (options?.tagId) search.set("tagId", options.tagId);
1571
- if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
1572
- if (options?.featured != null) search.set("featured", String(options.featured));
1573
- return `/api/links/storefront?${search}`;
1574
- }
1575
- function galleryItemsListPath(options) {
1576
- const search = new URLSearchParams();
1577
- appendCommonParams(search, options, "manual");
1578
- if (options?.galleryId) search.set("galleryId", options.galleryId);
1579
- if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
1580
- return `/api/gallery-items/storefront?${search}`;
1969
+ };
1970
+
1971
+ // src/core/content/content-client.ts
1972
+ var PublicContentApi = class extends RawCustomerScopedApi {
1973
+ get(endpoint2) {
1974
+ return this.request(endpoint2, { method: "GET" });
1975
+ }
1976
+ };
1977
+ function appendCommonParams(search, options, defaultSort) {
1978
+ search.set("sort", options?.sort ?? defaultSort);
1979
+ if (options?.page != null) search.set("page", String(options.page));
1980
+ if (options?.limit != null) search.set("limit", String(options.limit));
1981
+ }
1982
+ function linksListPath(options) {
1983
+ const search = new URLSearchParams();
1984
+ appendCommonParams(search, options, "-publishedAt,-createdAt");
1985
+ if (options?.categoryId) search.set("categoryId", options.categoryId);
1986
+ if (options?.categorySlug) {
1987
+ search.set("categorySlug", options.categorySlug);
1988
+ }
1989
+ if (options?.tagId) search.set("tagId", options.tagId);
1990
+ if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
1991
+ if (options?.featured != null)
1992
+ search.set("featured", String(options.featured));
1993
+ return `/api/links/storefront?${search}`;
1994
+ }
1995
+ function galleryItemsListPath(options) {
1996
+ const search = new URLSearchParams();
1997
+ appendCommonParams(search, options, "manual");
1998
+ if (options?.galleryId) search.set("galleryId", options.galleryId);
1999
+ if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
2000
+ return `/api/gallery-items/storefront?${search}`;
2001
+ }
2002
+ var ContentClient = class {
2003
+ constructor(options) {
2004
+ const api = new PublicContentApi("ContentClient", {
2005
+ publishableKey: options.publishableKey,
2006
+ apiUrl: options.apiUrl,
2007
+ onRequestId: options.onRequestId,
2008
+ requiresCredential: false
2009
+ });
2010
+ this.links = {
2011
+ list: (params) => api.get(linksListPath(params))
2012
+ };
2013
+ this.galleryItems = {
2014
+ list: (params) => api.get(
2015
+ galleryItemsListPath(params)
2016
+ )
2017
+ };
2018
+ }
2019
+ };
2020
+
2021
+ // src/core/api/canonical-response.ts
2022
+ var CART_STATUSES = ["active", "completed", "abandoned"];
2023
+ var MAX_CART_LINE_QUANTITY = 99;
2024
+ var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
2025
+ var MAX_COMMERCE_ADDRESS_LENGTH = 500;
2026
+ var MAX_COMMERCE_EMAIL_LENGTH = 254;
2027
+ var MAX_COMMERCE_PHONE_LENGTH = 32;
2028
+ var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
2029
+ var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
2030
+ var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
2031
+ var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
2032
+ var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
2033
+ var ORDER_FINANCIAL_STATUSES = [
2034
+ "pending",
2035
+ "authorized",
2036
+ "expired",
2037
+ "partially_paid",
2038
+ "paid",
2039
+ "canceled",
2040
+ "partially_refunded",
2041
+ "refunded",
2042
+ "reconciliation_required"
2043
+ ];
2044
+ var ORDER_FULFILLMENT_STATUSES = [
2045
+ "unfulfilled",
2046
+ "in_progress",
2047
+ "on_hold",
2048
+ "partially_fulfilled",
2049
+ "shipped",
2050
+ "fulfilled",
2051
+ "canceled"
2052
+ ];
2053
+ var ORDER_RETURN_STATUSES = [
2054
+ "no_return",
2055
+ "return_requested",
2056
+ "in_progress",
2057
+ "returned"
2058
+ ];
2059
+ var ORDER_CONFIRMATION_STATUSES = ["unconfirmed", "confirmed"];
2060
+ var ORDER_PRIMARY_DISPLAY_STATUSES = [
2061
+ "pending",
2062
+ "paid",
2063
+ "canceled",
2064
+ "refunded",
2065
+ "preparing",
2066
+ "shipped",
2067
+ "delivered",
2068
+ "confirmed"
2069
+ ];
2070
+ var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
2071
+ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2072
+ var PAYMENT_PROVIDERS = ["toss"];
2073
+ var PAYMENT_PROVIDER_STATUSES = [
2074
+ "requires_payment_method",
2075
+ "requires_action",
2076
+ "requires_confirmation",
2077
+ "initializing",
2078
+ "processing",
2079
+ "authorized",
2080
+ "canceling",
2081
+ "unknown",
2082
+ "captured",
2083
+ "failed",
2084
+ "canceled"
2085
+ ];
2086
+ var PAYMENT_FAILURE_REASONS = [
2087
+ "payment_declined",
2088
+ "authentication_failed",
2089
+ "authorization_expired",
2090
+ "payment_method_unavailable",
2091
+ "provider_terminal_failure",
2092
+ "unknown_provider_terminal_failure"
2093
+ ];
2094
+ var CART_WARNING_CODES = [
2095
+ "DISCOUNT_CODE_NOT_HONOURED",
2096
+ "DISCOUNT_CURRENTLY_INACTIVE",
2097
+ "DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
2098
+ "DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
2099
+ "DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
2100
+ "DISCOUNT_NO_ENTITLED_LINE_ITEMS",
2101
+ "DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
2102
+ "DISCOUNT_NOT_FOUND",
2103
+ "DISCOUNT_PURCHASE_NOT_IN_RANGE",
2104
+ "DISCOUNT_USAGE_LIMIT_REACHED",
2105
+ "MERCHANDISE_NOT_ENOUGH_STOCK",
2106
+ "MERCHANDISE_OUT_OF_STOCK"
2107
+ ];
2108
+ function invalidCanonicalResponse(resource, details) {
2109
+ throw createApiError(
2110
+ `Invalid canonical ${resource} response.`,
2111
+ 502,
2112
+ { resource, ...details },
2113
+ `The server returned an incompatible ${resource} response.`,
2114
+ "Verify that the Console commerce contract is deployed before using this SDK version."
2115
+ );
2116
+ }
2117
+ function fail(resource, path, expected) {
2118
+ invalidCanonicalResponse(resource, { path, expected });
2119
+ }
2120
+ function record(value, resource, path) {
2121
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2122
+ fail(resource, path, "object");
2123
+ }
2124
+ return value;
2125
+ }
2126
+ function exact(value, required, optional, resource, path) {
2127
+ for (const key of required) {
2128
+ if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
2129
+ }
2130
+ const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
2131
+ const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2132
+ if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2133
+ }
2134
+ function string(value, resource, path) {
2135
+ if (typeof value !== "string" || value.length === 0) {
2136
+ fail(resource, path, "non-empty string");
2137
+ }
2138
+ return value;
2139
+ }
2140
+ function boundedString(value, maxLength, resource, path, allowEmpty = false) {
2141
+ if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
2142
+ fail(
2143
+ resource,
2144
+ path,
2145
+ `${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
2146
+ );
2147
+ }
2148
+ return value;
2149
+ }
2150
+ function nullableString(value, resource, path) {
2151
+ if (value !== null && typeof value !== "string") {
2152
+ fail(resource, path, "string or null");
2153
+ }
2154
+ }
2155
+ function cartLineQuantity(value, resource, path) {
2156
+ const quantity = positiveInteger(value, resource, path);
2157
+ if (quantity > MAX_CART_LINE_QUANTITY) {
2158
+ fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
2159
+ }
2160
+ return quantity;
2161
+ }
2162
+ function boolean(value, resource, path) {
2163
+ if (typeof value !== "boolean") fail(resource, path, "boolean");
2164
+ }
2165
+ function safeMinor(value, resource, path) {
2166
+ if (!Number.isSafeInteger(value) || value < 0) {
2167
+ fail(resource, path, "non-negative safe integer");
2168
+ }
2169
+ return value;
2170
+ }
2171
+ function positiveInteger(value, resource, path) {
2172
+ if (!Number.isSafeInteger(value) || value <= 0) {
2173
+ fail(resource, path, "positive safe integer");
2174
+ }
2175
+ return value;
2176
+ }
2177
+ function enumValue(value, values, resource, path) {
2178
+ if (typeof value !== "string" || !values.includes(value)) {
2179
+ fail(resource, path, values.join(" | "));
2180
+ }
2181
+ return value;
2182
+ }
2183
+ function timestamp(value, resource, path) {
2184
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
2185
+ fail(resource, path, "ISO 8601 timestamp with offset");
2186
+ }
2187
+ }
2188
+ function currency(value, resource, path) {
2189
+ if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
2190
+ fail(resource, path, "three-letter uppercase currency code");
2191
+ }
2192
+ }
2193
+ function array(value, resource, path) {
2194
+ if (!Array.isArray(value)) fail(resource, path, "array");
2195
+ return value;
2196
+ }
2197
+ function optionalNullableNumber(value, resource, path) {
2198
+ if (value !== void 0 && value !== null && typeof value !== "number") {
2199
+ fail(resource, path, "number or null");
2200
+ }
2201
+ }
2202
+ function validateMediaSize(value, resource, path) {
2203
+ const item = record(value, resource, path);
2204
+ exact(
2205
+ item,
2206
+ [],
2207
+ ["width", "height", "mimeType", "filename", "url"],
2208
+ resource,
2209
+ path
2210
+ );
2211
+ optionalNullableNumber(item.width, resource, `${path}.width`);
2212
+ optionalNullableNumber(item.height, resource, `${path}.height`);
2213
+ for (const key of ["mimeType", "filename", "url"]) {
2214
+ if (item[key] !== void 0)
2215
+ nullableString(item[key], resource, `${path}.${key}`);
2216
+ }
2217
+ }
2218
+ function validateMedia(value, resource, path) {
2219
+ if (typeof value === "string") return;
2220
+ const media = record(value, resource, path);
2221
+ exact(
2222
+ media,
2223
+ [],
2224
+ ["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
2225
+ resource,
2226
+ path
2227
+ );
2228
+ if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
2229
+ fail(resource, `${path}.id`, "string, number, or null");
2230
+ }
2231
+ for (const key of ["alt", "mimeType", "filename", "url"]) {
2232
+ if (media[key] !== void 0)
2233
+ nullableString(media[key], resource, `${path}.${key}`);
2234
+ }
2235
+ optionalNullableNumber(media.width, resource, `${path}.width`);
2236
+ optionalNullableNumber(media.height, resource, `${path}.height`);
2237
+ if (media.sizes !== void 0) {
2238
+ const sizes = record(media.sizes, resource, `${path}.sizes`);
2239
+ Object.entries(sizes).forEach(
2240
+ ([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
2241
+ );
2242
+ }
2243
+ }
2244
+ function validateReference(value, resource, path) {
2245
+ const ref = record(value, resource, path);
2246
+ exact(ref, ["id", "title", "handle", "image"], [], resource, path);
2247
+ string(ref.id, resource, `${path}.id`);
2248
+ string(ref.title, resource, `${path}.title`);
2249
+ if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
2250
+ if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
2251
+ }
2252
+ function validateAdmission(value, resource, path) {
2253
+ const admission = record(value, resource, path);
2254
+ exact(
2255
+ admission,
2256
+ ["eventId", "occurrenceId", "admissionTypeId"],
2257
+ [],
2258
+ resource,
2259
+ path
2260
+ );
2261
+ string(admission.eventId, resource, `${path}.eventId`);
2262
+ string(admission.occurrenceId, resource, `${path}.occurrenceId`);
2263
+ string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
2264
+ }
2265
+ function compareAdmissions(left, right) {
2266
+ for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
2267
+ if (left[field] < right[field]) return -1;
2268
+ if (left[field] > right[field]) return 1;
2269
+ }
2270
+ return 0;
2271
+ }
2272
+ function validateAdmissions(value, resource, path) {
2273
+ const admissions = array(value, resource, path);
2274
+ if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
2275
+ let prior;
2276
+ admissions.forEach((admission, index) => {
2277
+ validateAdmission(admission, resource, `${path}[${index}]`);
2278
+ const item = admission;
2279
+ const comparison = prior ? compareAdmissions(item, prior) : void 0;
2280
+ if (comparison !== void 0 && comparison <= 0) {
2281
+ fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
2282
+ }
2283
+ prior = item;
2284
+ });
2285
+ }
2286
+ function validateAttributes(value, resource, path) {
2287
+ const attributes = array(value, resource, path);
2288
+ if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
2289
+ const keys = /* @__PURE__ */ new Set();
2290
+ attributes.forEach((value2, index) => {
2291
+ const itemPath = `${path}[${index}]`;
2292
+ const attribute = record(value2, resource, itemPath);
2293
+ exact(attribute, ["key", "value"], [], resource, itemPath);
2294
+ const key = string(attribute.key, resource, `${itemPath}.key`);
2295
+ if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
2296
+ fail(
2297
+ resource,
2298
+ `${itemPath}.key`,
2299
+ "unique, non-reserved key of at most 40 characters"
2300
+ );
2301
+ }
2302
+ keys.add(key);
2303
+ if (typeof attribute.value !== "string" || attribute.value.length > 500) {
2304
+ fail(resource, `${itemPath}.value`, "string of at most 500 characters");
2305
+ }
2306
+ });
2307
+ }
2308
+ function validateCustomer(value, resource, path) {
2309
+ const customer = record(value, resource, path);
2310
+ exact(customer, ["email"], ["name", "phone"], resource, path);
2311
+ const email = boundedString(
2312
+ customer.email,
2313
+ MAX_COMMERCE_EMAIL_LENGTH,
2314
+ resource,
2315
+ `${path}.email`
2316
+ );
2317
+ if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
2318
+ email
2319
+ )) {
2320
+ fail(resource, `${path}.email`, "email address");
2321
+ }
2322
+ if (customer.name !== void 0)
2323
+ boundedString(
2324
+ customer.name,
2325
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2326
+ resource,
2327
+ `${path}.name`
2328
+ );
2329
+ if (customer.phone !== void 0)
2330
+ boundedString(
2331
+ customer.phone,
2332
+ MAX_COMMERCE_PHONE_LENGTH,
2333
+ resource,
2334
+ `${path}.phone`
2335
+ );
2336
+ }
2337
+ function validateShippingAddress(value, resource, path) {
2338
+ const address = record(value, resource, path);
2339
+ exact(
2340
+ address,
2341
+ ["recipientName", "phone", "postalCode", "address", "detailAddress"],
2342
+ ["countryCode", "regionCode", "deliveryMessage"],
2343
+ resource,
2344
+ path
2345
+ );
2346
+ boundedString(
2347
+ address.recipientName,
2348
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2349
+ resource,
2350
+ `${path}.recipientName`
2351
+ );
2352
+ boundedString(
2353
+ address.phone,
2354
+ MAX_COMMERCE_PHONE_LENGTH,
2355
+ resource,
2356
+ `${path}.phone`
2357
+ );
2358
+ boundedString(
2359
+ address.postalCode,
2360
+ MAX_COMMERCE_POSTAL_CODE_LENGTH,
2361
+ resource,
2362
+ `${path}.postalCode`
2363
+ );
2364
+ for (const key of ["address", "detailAddress"]) {
2365
+ boundedString(
2366
+ address[key],
2367
+ MAX_COMMERCE_ADDRESS_LENGTH,
2368
+ resource,
2369
+ `${path}.${key}`
2370
+ );
2371
+ }
2372
+ if (address.countryCode !== void 0) {
2373
+ if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
2374
+ fail(resource, `${path}.countryCode`, "two-letter country code");
2375
+ }
2376
+ }
2377
+ if (address.regionCode !== void 0) {
2378
+ if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
2379
+ fail(
2380
+ resource,
2381
+ `${path}.regionCode`,
2382
+ "trimmed string of at most 64 characters"
2383
+ );
2384
+ }
2385
+ }
2386
+ if (address.deliveryMessage !== void 0) {
2387
+ boundedString(
2388
+ address.deliveryMessage,
2389
+ MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
2390
+ resource,
2391
+ `${path}.deliveryMessage`,
2392
+ true
2393
+ );
2394
+ }
2395
+ }
2396
+ function validateOrderReference(value, resource, path) {
2397
+ const order = record(value, resource, path);
2398
+ exact(order, ["id", "orderNumber"], [], resource, path);
2399
+ string(order.id, resource, `${path}.id`);
2400
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2401
+ }
2402
+ function validateIntegrationMetadata(value, resource, path) {
2403
+ const metadata = record(value, resource, path);
2404
+ if (Object.keys(metadata).length > 50)
2405
+ fail(resource, path, "at most 50 entries");
2406
+ Object.entries(metadata).forEach(([key, entry]) => {
2407
+ if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
2408
+ fail(resource, `${path}.${key}`, "valid metadata key");
2409
+ }
2410
+ if (typeof entry !== "string" || entry.length > 500) {
2411
+ fail(resource, `${path}.${key}`, "string of at most 500 characters");
2412
+ }
2413
+ });
2414
+ }
2415
+ function validateCartItem(value, resource, path) {
2416
+ const item = record(value, resource, path);
2417
+ exact(
2418
+ item,
2419
+ [
2420
+ "id",
2421
+ "product",
2422
+ "variant",
2423
+ "admissions",
2424
+ "quantity",
2425
+ "unitPriceMinor",
2426
+ "discountMinor",
2427
+ "estimatedLineTotalMinor",
2428
+ "requiresShipping"
2429
+ ],
2430
+ [],
2431
+ resource,
2432
+ path
2433
+ );
2434
+ string(item.id, resource, `${path}.id`);
2435
+ validateReference(item.product, resource, `${path}.product`);
2436
+ validateReference(item.variant, resource, `${path}.variant`);
2437
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2438
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2439
+ const unitPrice = safeMinor(
2440
+ item.unitPriceMinor,
2441
+ resource,
2442
+ `${path}.unitPriceMinor`
2443
+ );
2444
+ const discount = safeMinor(
2445
+ item.discountMinor,
2446
+ resource,
2447
+ `${path}.discountMinor`
2448
+ );
2449
+ const estimatedLineTotal = safeMinor(
2450
+ item.estimatedLineTotalMinor,
2451
+ resource,
2452
+ `${path}.estimatedLineTotalMinor`
2453
+ );
2454
+ const quantity = item.quantity;
2455
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2456
+ if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
2457
+ fail(
2458
+ resource,
2459
+ `${path}.estimatedLineTotalMinor`,
2460
+ "unitPriceMinor * quantity - discountMinor"
2461
+ );
2462
+ }
2463
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2464
+ }
2465
+ function validatePublicCart(value, resource = "Cart") {
2466
+ const cart = record(value, resource, "$");
2467
+ exact(
2468
+ cart,
2469
+ [
2470
+ "id",
2471
+ "status",
2472
+ "revision",
2473
+ "currency",
2474
+ "market",
2475
+ "subtotalMinor",
2476
+ "discountMinor",
2477
+ "estimatedTotalMinor",
2478
+ "discountCodes",
2479
+ "attributes",
2480
+ "items",
2481
+ "expiresAt",
2482
+ "createdAt",
2483
+ "updatedAt"
2484
+ ],
2485
+ [],
2486
+ resource,
2487
+ "$"
2488
+ );
2489
+ string(cart.id, resource, "$.id");
2490
+ enumValue(cart.status, CART_STATUSES, resource, "$.status");
2491
+ safeMinor(cart.revision, resource, "$.revision");
2492
+ currency(cart.currency, resource, "$.currency");
2493
+ const market = record(cart.market, resource, "$.market");
2494
+ exact(market, ["id", "handle", "name"], [], resource, "$.market");
2495
+ for (const key of ["id", "handle", "name"])
2496
+ string(market[key], resource, `$.market.${key}`);
2497
+ const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
2498
+ const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
2499
+ const estimatedTotal = safeMinor(
2500
+ cart.estimatedTotalMinor,
2501
+ resource,
2502
+ "$.estimatedTotalMinor"
2503
+ );
2504
+ array(cart.discountCodes, resource, "$.discountCodes").forEach(
2505
+ (value2, index) => {
2506
+ const itemPath = `$.discountCodes[${index}]`;
2507
+ const code = record(value2, resource, itemPath);
2508
+ exact(code, ["code", "applicable"], [], resource, itemPath);
2509
+ boundedString(
2510
+ code.code,
2511
+ MAX_CART_DISCOUNT_CODE_LENGTH,
2512
+ resource,
2513
+ `${itemPath}.code`
2514
+ );
2515
+ boolean(code.applicable, resource, `${itemPath}.applicable`);
2516
+ }
2517
+ );
2518
+ validateAttributes(cart.attributes, resource, "$.attributes");
2519
+ const items = array(cart.items, resource, "$.items");
2520
+ items.forEach(
2521
+ (item, index) => validateCartItem(item, resource, `$.items[${index}]`)
2522
+ );
2523
+ const expectedSubtotal = items.reduce((total, value2) => {
2524
+ const item = value2;
2525
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2526
+ }, 0n);
2527
+ const expectedDiscount = items.reduce((total, value2) => {
2528
+ const item = value2;
2529
+ return total + BigInt(item.discountMinor);
2530
+ }, 0n);
2531
+ if (BigInt(subtotal) !== expectedSubtotal) {
2532
+ fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
2533
+ }
2534
+ if (BigInt(discount) !== expectedDiscount) {
2535
+ fail(resource, "$.discountMinor", "sum of cart line discounts");
2536
+ }
2537
+ if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
2538
+ fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
2539
+ }
2540
+ timestamp(cart.expiresAt, resource, "$.expiresAt");
2541
+ timestamp(cart.createdAt, resource, "$.createdAt");
2542
+ timestamp(cart.updatedAt, resource, "$.updatedAt");
2543
+ return value;
2544
+ }
2545
+ function validateWarnings(value, resource, path) {
2546
+ array(value, resource, path).forEach((value2, index) => {
2547
+ const itemPath = `${path}[${index}]`;
2548
+ const warning = record(value2, resource, itemPath);
2549
+ exact(warning, ["code", "message", "target"], [], resource, itemPath);
2550
+ enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
2551
+ string(warning.message, resource, `${itemPath}.message`);
2552
+ string(warning.target, resource, `${itemPath}.target`);
2553
+ });
2554
+ }
2555
+ function validateCartMutationResult(value) {
2556
+ const result = record(value, "Cart mutation result", "$");
2557
+ exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
2558
+ validatePublicCart(result.cart);
2559
+ validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
2560
+ return value;
2561
+ }
2562
+ function validateCreateCartResult(value) {
2563
+ const result = record(value, "Cart create result", "$");
2564
+ exact(
2565
+ result,
2566
+ ["cart", "warnings", "cartToken"],
2567
+ [],
2568
+ "Cart create result",
2569
+ "$"
2570
+ );
2571
+ const cart = record(result.cart, "Cart create result", "$.cart");
2572
+ validatePublicCart(cart);
2573
+ if (cart.revision !== 0) {
2574
+ fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
2575
+ }
2576
+ validateWarnings(result.warnings, "Cart create result", "$.warnings");
2577
+ boundedString(
2578
+ result.cartToken,
2579
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2580
+ "Cart create result",
2581
+ "$.cartToken"
2582
+ );
2583
+ return value;
2584
+ }
2585
+ function validateCartMineResult(value) {
2586
+ const result = record(value, "Cart mine result", "$");
2587
+ exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
2588
+ if (result.cart === null || result.cartToken === null) {
2589
+ if (result.cart !== null || result.cartToken !== null) {
2590
+ fail("Cart mine result", "$", "cart and cartToken must both be null");
2591
+ }
2592
+ } else {
2593
+ validatePublicCart(result.cart);
2594
+ boundedString(
2595
+ result.cartToken,
2596
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2597
+ "Cart mine result",
2598
+ "$.cartToken"
2599
+ );
2600
+ }
2601
+ return value;
2602
+ }
2603
+ function validateCartMergeResult(value) {
2604
+ const result = record(value, "Cart merge result", "$");
2605
+ exact(
2606
+ result,
2607
+ ["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
2608
+ [],
2609
+ "Cart merge result",
2610
+ "$"
2611
+ );
2612
+ validatePublicCart(result.cart);
2613
+ validateWarnings(result.warnings, "Cart merge result", "$.warnings");
2614
+ boundedString(
2615
+ result.cartToken,
2616
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2617
+ "Cart merge result",
2618
+ "$.cartToken"
2619
+ );
2620
+ const resolution = enumValue(
2621
+ result.resolution,
2622
+ ["unchanged", "claimed", "merged"],
2623
+ "Cart merge result",
2624
+ "$.resolution"
2625
+ );
2626
+ boolean(result.merged, "Cart merge result", "$.merged");
2627
+ boolean(result.claimed, "Cart merge result", "$.claimed");
2628
+ const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
2629
+ if (result.merged !== expected[0] || result.claimed !== expected[1]) {
2630
+ fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
2631
+ }
2632
+ return value;
2633
+ }
2634
+ function validatePublicOrderItem(value, resource, path) {
2635
+ const item = record(value, resource, path);
2636
+ exact(
2637
+ item,
2638
+ [
2639
+ "id",
2640
+ "product",
2641
+ "variant",
2642
+ "productTitle",
2643
+ "variantTitle",
2644
+ "sku",
2645
+ "admissions",
2646
+ "quantity",
2647
+ "unitPriceMinor",
2648
+ "discountMinor",
2649
+ "lineTotalMinor",
2650
+ "requiresShipping"
2651
+ ],
2652
+ [],
2653
+ resource,
2654
+ path
2655
+ );
2656
+ string(item.id, resource, `${path}.id`);
2657
+ if (item.product !== null) {
2658
+ validateReference(item.product, resource, `${path}.product`);
2659
+ }
2660
+ if (item.variant !== null) {
2661
+ validateReference(item.variant, resource, `${path}.variant`);
2662
+ }
2663
+ string(item.productTitle, resource, `${path}.productTitle`);
2664
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2665
+ nullableString(item.sku, resource, `${path}.sku`);
2666
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2667
+ const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
2668
+ const unitPrice = safeMinor(
2669
+ item.unitPriceMinor,
2670
+ resource,
2671
+ `${path}.unitPriceMinor`
2672
+ );
2673
+ const discount = safeMinor(
2674
+ item.discountMinor,
2675
+ resource,
2676
+ `${path}.discountMinor`
2677
+ );
2678
+ const lineTotal = safeMinor(
2679
+ item.lineTotalMinor,
2680
+ resource,
2681
+ `${path}.lineTotalMinor`
2682
+ );
2683
+ const expected = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2684
+ if (expected < 0n || BigInt(lineTotal) !== expected) {
2685
+ fail(
2686
+ resource,
2687
+ `${path}.lineTotalMinor`,
2688
+ "unitPriceMinor * quantity - discountMinor"
2689
+ );
2690
+ }
2691
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2692
+ }
2693
+ function validatePublicOrderAt(value, resource, path) {
2694
+ const order = record(value, resource, path);
2695
+ exact(
2696
+ order,
2697
+ [
2698
+ "id",
2699
+ "orderNumber",
2700
+ "amounts",
2701
+ "market",
2702
+ "customerSnapshot",
2703
+ "shippingAddress",
2704
+ "attributes",
2705
+ "items",
2706
+ "financialStatus",
2707
+ "fulfillmentStatus",
2708
+ "returnStatus",
2709
+ "confirmationStatus",
2710
+ "primaryDisplayStatus",
2711
+ "placedAt",
2712
+ "createdAt",
2713
+ "updatedAt"
2714
+ ],
2715
+ [],
2716
+ resource,
2717
+ path
2718
+ );
2719
+ string(order.id, resource, `${path}.id`);
2720
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2721
+ const amounts = record(order.amounts, resource, `${path}.amounts`);
2722
+ exact(
2723
+ amounts,
2724
+ [
2725
+ "currency",
2726
+ "subtotalMinor",
2727
+ "shippingMinor",
2728
+ "discountMinor",
2729
+ "totalMinor",
2730
+ "refundedMinor",
2731
+ "currentTotalMinor"
2732
+ ],
2733
+ [],
2734
+ resource,
2735
+ `${path}.amounts`
2736
+ );
2737
+ currency(amounts.currency, resource, `${path}.amounts.currency`);
2738
+ const subtotal = safeMinor(
2739
+ amounts.subtotalMinor,
2740
+ resource,
2741
+ `${path}.amounts.subtotalMinor`
2742
+ );
2743
+ const shipping = safeMinor(
2744
+ amounts.shippingMinor,
2745
+ resource,
2746
+ `${path}.amounts.shippingMinor`
2747
+ );
2748
+ const discount = safeMinor(
2749
+ amounts.discountMinor,
2750
+ resource,
2751
+ `${path}.amounts.discountMinor`
2752
+ );
2753
+ const total = safeMinor(
2754
+ amounts.totalMinor,
2755
+ resource,
2756
+ `${path}.amounts.totalMinor`
2757
+ );
2758
+ const refunded = safeMinor(
2759
+ amounts.refundedMinor,
2760
+ resource,
2761
+ `${path}.amounts.refundedMinor`
2762
+ );
2763
+ const current = safeMinor(
2764
+ amounts.currentTotalMinor,
2765
+ resource,
2766
+ `${path}.amounts.currentTotalMinor`
2767
+ );
2768
+ const expectedTotal = BigInt(subtotal) + BigInt(shipping) - BigInt(discount);
2769
+ if (expectedTotal < 0n || BigInt(total) !== expectedTotal) {
2770
+ fail(
2771
+ resource,
2772
+ `${path}.amounts.totalMinor`,
2773
+ "subtotalMinor + shippingMinor - discountMinor"
2774
+ );
2775
+ }
2776
+ if (BigInt(total) - BigInt(refunded) < 0n || current !== total - refunded) {
2777
+ fail(
2778
+ resource,
2779
+ `${path}.amounts.currentTotalMinor`,
2780
+ "totalMinor - refundedMinor"
2781
+ );
2782
+ }
2783
+ if (order.market !== null) {
2784
+ const market = record(order.market, resource, `${path}.market`);
2785
+ exact(market, ["id", "handle", "name"], [], resource, `${path}.market`);
2786
+ for (const key of ["id", "handle", "name"]) {
2787
+ string(market[key], resource, `${path}.market.${key}`);
2788
+ }
2789
+ }
2790
+ validateCustomer(order.customerSnapshot, resource, `${path}.customerSnapshot`);
2791
+ if (order.shippingAddress !== null) {
2792
+ validateShippingAddress(
2793
+ order.shippingAddress,
2794
+ resource,
2795
+ `${path}.shippingAddress`
2796
+ );
2797
+ }
2798
+ validateAttributes(order.attributes, resource, `${path}.attributes`);
2799
+ const items = array(order.items, resource, `${path}.items`);
2800
+ if (items.length === 0) fail(resource, `${path}.items`, "non-empty array");
2801
+ items.forEach(
2802
+ (item, index) => validatePublicOrderItem(item, resource, `${path}.items[${index}]`)
2803
+ );
2804
+ const expectedSubtotal = items.reduce((sum, value2) => {
2805
+ const item = value2;
2806
+ return sum + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2807
+ }, 0n);
2808
+ const expectedDiscount = items.reduce((sum, value2) => {
2809
+ const item = value2;
2810
+ return sum + BigInt(item.discountMinor);
2811
+ }, 0n);
2812
+ if (BigInt(subtotal) !== expectedSubtotal) {
2813
+ fail(resource, `${path}.amounts.subtotalMinor`, "sum of line subtotals");
2814
+ }
2815
+ if (BigInt(discount) !== expectedDiscount) {
2816
+ fail(resource, `${path}.amounts.discountMinor`, "sum of line discounts");
2817
+ }
2818
+ enumValue(
2819
+ order.financialStatus,
2820
+ ORDER_FINANCIAL_STATUSES,
2821
+ resource,
2822
+ `${path}.financialStatus`
2823
+ );
2824
+ enumValue(
2825
+ order.fulfillmentStatus,
2826
+ ORDER_FULFILLMENT_STATUSES,
2827
+ resource,
2828
+ `${path}.fulfillmentStatus`
2829
+ );
2830
+ enumValue(
2831
+ order.returnStatus,
2832
+ ORDER_RETURN_STATUSES,
2833
+ resource,
2834
+ `${path}.returnStatus`
2835
+ );
2836
+ enumValue(
2837
+ order.confirmationStatus,
2838
+ ORDER_CONFIRMATION_STATUSES,
2839
+ resource,
2840
+ `${path}.confirmationStatus`
2841
+ );
2842
+ enumValue(
2843
+ order.primaryDisplayStatus,
2844
+ ORDER_PRIMARY_DISPLAY_STATUSES,
2845
+ resource,
2846
+ `${path}.primaryDisplayStatus`
2847
+ );
2848
+ timestamp(order.placedAt, resource, `${path}.placedAt`);
2849
+ timestamp(order.createdAt, resource, `${path}.createdAt`);
2850
+ timestamp(order.updatedAt, resource, `${path}.updatedAt`);
2851
+ }
2852
+ function nullablePositiveInteger(value, resource, path) {
2853
+ if (value !== null) positiveInteger(value, resource, path);
2854
+ }
2855
+ function validatePublicOrderList(value) {
2856
+ const resource = "Order list";
2857
+ const result = record(value, resource, "$");
2858
+ exact(
2859
+ result,
2860
+ [
2861
+ "docs",
2862
+ "totalDocs",
2863
+ "limit",
2864
+ "totalPages",
2865
+ "page",
2866
+ "pagingCounter",
2867
+ "hasPrevPage",
2868
+ "hasNextPage",
2869
+ "prevPage",
2870
+ "nextPage"
2871
+ ],
2872
+ [],
2873
+ resource,
2874
+ "$"
2875
+ );
2876
+ array(result.docs, resource, "$.docs").forEach(
2877
+ (order, index) => validatePublicOrderAt(order, resource, `$.docs[${index}]`)
2878
+ );
2879
+ safeMinor(result.totalDocs, resource, "$.totalDocs");
2880
+ positiveInteger(result.limit, resource, "$.limit");
2881
+ safeMinor(result.totalPages, resource, "$.totalPages");
2882
+ positiveInteger(result.page, resource, "$.page");
2883
+ positiveInteger(result.pagingCounter, resource, "$.pagingCounter");
2884
+ boolean(result.hasPrevPage, resource, "$.hasPrevPage");
2885
+ boolean(result.hasNextPage, resource, "$.hasNextPage");
2886
+ nullablePositiveInteger(result.prevPage, resource, "$.prevPage");
2887
+ nullablePositiveInteger(result.nextPage, resource, "$.nextPage");
2888
+ return value;
2889
+ }
2890
+ function validateCheckoutItem(value, resource, path) {
2891
+ const item = record(value, resource, path);
2892
+ exact(
2893
+ item,
2894
+ [
2895
+ "id",
2896
+ "product",
2897
+ "variant",
2898
+ "productTitle",
2899
+ "variantTitle",
2900
+ "sku",
2901
+ "admissions",
2902
+ "quantity",
2903
+ "unitPriceMinor",
2904
+ "discountMinor",
2905
+ "lineTotalMinor",
2906
+ "requiresShipping"
2907
+ ],
2908
+ [],
2909
+ resource,
2910
+ path
2911
+ );
2912
+ string(item.id, resource, `${path}.id`);
2913
+ validateReference(item.product, resource, `${path}.product`);
2914
+ validateReference(item.variant, resource, `${path}.variant`);
2915
+ string(item.productTitle, resource, `${path}.productTitle`);
2916
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2917
+ nullableString(item.sku, resource, `${path}.sku`);
2918
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2919
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2920
+ const unitPrice = safeMinor(
2921
+ item.unitPriceMinor,
2922
+ resource,
2923
+ `${path}.unitPriceMinor`
2924
+ );
2925
+ const discount = safeMinor(
2926
+ item.discountMinor,
2927
+ resource,
2928
+ `${path}.discountMinor`
2929
+ );
2930
+ const lineTotal = safeMinor(
2931
+ item.lineTotalMinor,
2932
+ resource,
2933
+ `${path}.lineTotalMinor`
2934
+ );
2935
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
2936
+ if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
2937
+ fail(
2938
+ resource,
2939
+ `${path}.lineTotalMinor`,
2940
+ "unitPriceMinor * quantity - discountMinor"
2941
+ );
2942
+ }
2943
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2944
+ }
2945
+ function validateCheckoutAmounts(value, resource, path) {
2946
+ const amounts = record(value, resource, path);
2947
+ exact(
2948
+ amounts,
2949
+ [
2950
+ "currency",
2951
+ "subtotalMinor",
2952
+ "shippingMinor",
2953
+ "discountMinor",
2954
+ "totalMinor"
2955
+ ],
2956
+ [],
2957
+ resource,
2958
+ path
2959
+ );
2960
+ currency(amounts.currency, resource, `${path}.currency`);
2961
+ const subtotal = safeMinor(
2962
+ amounts.subtotalMinor,
2963
+ resource,
2964
+ `${path}.subtotalMinor`
2965
+ );
2966
+ const shipping = safeMinor(
2967
+ amounts.shippingMinor,
2968
+ resource,
2969
+ `${path}.shippingMinor`
2970
+ );
2971
+ const discount = safeMinor(
2972
+ amounts.discountMinor,
2973
+ resource,
2974
+ `${path}.discountMinor`
2975
+ );
2976
+ const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
2977
+ if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
2978
+ fail(
2979
+ resource,
2980
+ `${path}.totalMinor`,
2981
+ "subtotalMinor + shippingMinor - discountMinor"
2982
+ );
2983
+ }
2984
+ }
2985
+ function validatePaymentSessionReference(value, resource, path) {
2986
+ const session = record(value, resource, path);
2987
+ exact(session, ["id", "provider", "providerStatus"], [], resource, path);
2988
+ string(session.id, resource, `${path}.id`);
2989
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
2990
+ enumValue(
2991
+ session.providerStatus,
2992
+ PAYMENT_PROVIDER_STATUSES,
2993
+ resource,
2994
+ `${path}.providerStatus`
2995
+ );
2996
+ }
2997
+ function checkoutVariantKeys(status, placedVia) {
2998
+ const base = [
2999
+ "id",
3000
+ "amounts",
3001
+ "items",
3002
+ "customerSnapshot",
3003
+ "shippingAddress",
3004
+ "attributes",
3005
+ "expiresAt",
3006
+ "createdAt",
3007
+ "updatedAt",
3008
+ "status",
3009
+ "paymentState",
3010
+ "order"
3011
+ ];
3012
+ if (status === "open") return { required: base, optional: [] };
3013
+ if (status === "abandoned") {
3014
+ return {
3015
+ required: [...base, "abandonedAt", "abandonedReason"],
3016
+ optional: []
3017
+ };
3018
+ }
3019
+ return placedVia === "late_capture" ? {
3020
+ required: [
3021
+ ...base,
3022
+ "placedAt",
3023
+ "placedVia",
3024
+ "abandonedAt",
3025
+ "abandonedReason"
3026
+ ],
3027
+ optional: []
3028
+ } : { required: [...base, "placedAt"], optional: [] };
3029
+ }
3030
+ function validateCheckoutCore(value, resource, list, server) {
3031
+ const checkout = record(value, resource, "$");
3032
+ const status = enumValue(
3033
+ checkout.status,
3034
+ CHECKOUT_STATUSES,
3035
+ resource,
3036
+ "$.status"
3037
+ );
3038
+ const keys = checkoutVariantKeys(status, checkout.placedVia);
3039
+ if (list) {
3040
+ keys.required = keys.required.filter(
3041
+ (key) => !["items", "shippingAddress", "attributes"].includes(key)
3042
+ );
3043
+ keys.required.push("clientReferenceId");
3044
+ } else if (server) {
3045
+ keys.required.push("clientReferenceId", "integrationMetadata");
3046
+ }
3047
+ exact(checkout, keys.required, keys.optional, resource, "$");
3048
+ string(checkout.id, resource, "$.id");
3049
+ validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
3050
+ if (!list) {
3051
+ const items = array(checkout.items, resource, "$.items");
3052
+ if (items.length === 0) fail(resource, "$.items", "non-empty array");
3053
+ items.forEach(
3054
+ (item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
3055
+ );
3056
+ const expectedSubtotal = items.reduce((total, value2) => {
3057
+ const item = value2;
3058
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
3059
+ }, 0n);
3060
+ const expectedDiscount = items.reduce((total, value2) => {
3061
+ const item = value2;
3062
+ return total + BigInt(item.discountMinor);
3063
+ }, 0n);
3064
+ const amounts = checkout.amounts;
3065
+ if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
3066
+ fail(
3067
+ resource,
3068
+ "$.amounts.subtotalMinor",
3069
+ "sum of undiscounted checkout line totals"
3070
+ );
3071
+ }
3072
+ if (BigInt(amounts.discountMinor) !== expectedDiscount) {
3073
+ fail(
3074
+ resource,
3075
+ "$.amounts.discountMinor",
3076
+ "sum of checkout line discounts"
3077
+ );
3078
+ }
3079
+ if (checkout.shippingAddress !== null) {
3080
+ validateShippingAddress(
3081
+ checkout.shippingAddress,
3082
+ resource,
3083
+ "$.shippingAddress"
3084
+ );
3085
+ }
3086
+ validateAttributes(checkout.attributes, resource, "$.attributes");
3087
+ }
3088
+ validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
3089
+ timestamp(checkout.expiresAt, resource, "$.expiresAt");
3090
+ timestamp(checkout.createdAt, resource, "$.createdAt");
3091
+ timestamp(checkout.updatedAt, resource, "$.updatedAt");
3092
+ const paymentState = record(checkout.paymentState, resource, "$.paymentState");
3093
+ exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
3094
+ if (status === "open") {
3095
+ if (paymentState.activePaymentSession !== null) {
3096
+ validatePaymentSessionReference(
3097
+ paymentState.activePaymentSession,
3098
+ resource,
3099
+ "$.paymentState.activePaymentSession"
3100
+ );
3101
+ }
3102
+ if (checkout.order !== null)
3103
+ fail(resource, "$.order", "null for open Checkout");
3104
+ } else {
3105
+ if (paymentState.activePaymentSession !== null) {
3106
+ fail(
3107
+ resource,
3108
+ "$.paymentState.activePaymentSession",
3109
+ "null for spent Checkout"
3110
+ );
3111
+ }
3112
+ if (status === "placed") {
3113
+ timestamp(checkout.placedAt, resource, "$.placedAt");
3114
+ validateOrderReference(checkout.order, resource, "$.order");
3115
+ if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
3116
+ fail(resource, "$.placedVia", "late_capture");
3117
+ }
3118
+ if (checkout.placedVia === "late_capture") {
3119
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
3120
+ enumValue(
3121
+ checkout.abandonedReason,
3122
+ ABANDONED_REASONS,
3123
+ resource,
3124
+ "$.abandonedReason"
3125
+ );
3126
+ }
3127
+ } else {
3128
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
3129
+ enumValue(
3130
+ checkout.abandonedReason,
3131
+ ABANDONED_REASONS,
3132
+ resource,
3133
+ "$.abandonedReason"
3134
+ );
3135
+ if (checkout.order !== null)
3136
+ fail(resource, "$.order", "null for abandoned Checkout");
3137
+ }
3138
+ }
3139
+ if (list || server) {
3140
+ if (checkout.clientReferenceId !== null) {
3141
+ boundedString(
3142
+ checkout.clientReferenceId,
3143
+ MAX_COMMERCE_RESOURCE_ID_LENGTH,
3144
+ resource,
3145
+ "$.clientReferenceId"
3146
+ );
3147
+ }
3148
+ }
3149
+ if (server)
3150
+ validateIntegrationMetadata(
3151
+ checkout.integrationMetadata,
3152
+ resource,
3153
+ "$.integrationMetadata"
3154
+ );
3155
+ }
3156
+ function validatePublicCheckout(value) {
3157
+ validateCheckoutCore(value, "Checkout", false, false);
3158
+ return value;
3159
+ }
3160
+ function validateServerCheckout(value) {
3161
+ validateCheckoutCore(value, "Server Checkout", false, true);
3162
+ return value;
3163
+ }
3164
+ function validateCreateCheckoutResult(value, server) {
3165
+ const resource = server ? "Server Checkout create result" : "Checkout create result";
3166
+ const result = record(value, resource, "$");
3167
+ exact(result, ["checkout", "checkoutToken"], [], resource, "$");
3168
+ if (server) validateServerCheckout(result.checkout);
3169
+ else validatePublicCheckout(result.checkout);
3170
+ boundedString(
3171
+ result.checkoutToken,
3172
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3173
+ resource,
3174
+ "$.checkoutToken"
3175
+ );
3176
+ return value;
3177
+ }
3178
+ function validateCheckoutQueryResult(value) {
3179
+ const result = record(value, "Checkout query result", "$");
3180
+ exact(
3181
+ result,
3182
+ ["data", "hasMore", "nextCursor"],
3183
+ [],
3184
+ "Checkout query result",
3185
+ "$"
3186
+ );
3187
+ array(result.data, "Checkout query result", "$.data").forEach(
3188
+ (item) => validateCheckoutCore(item, "Checkout list item", true, false)
3189
+ );
3190
+ boolean(result.hasMore, "Checkout query result", "$.hasMore");
3191
+ if (result.nextCursor !== null)
3192
+ boundedString(
3193
+ result.nextCursor,
3194
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3195
+ "Checkout query result",
3196
+ "$.nextCursor"
3197
+ );
3198
+ if (result.hasMore === true && result.nextCursor === null) {
3199
+ fail(
3200
+ "Checkout query result",
3201
+ "$.nextCursor",
3202
+ "non-null when hasMore is true"
3203
+ );
3204
+ }
3205
+ return value;
3206
+ }
3207
+ function validateMoney(value, resource, path) {
3208
+ const money = record(value, resource, path);
3209
+ exact(money, ["amountMinor", "currency"], [], resource, path);
3210
+ safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3211
+ currency(money.currency, resource, `${path}.currency`);
3212
+ }
3213
+ function validateCaptureEvidence(value, resource, path) {
3214
+ const evidence = record(value, resource, path);
3215
+ exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
3216
+ safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
3217
+ currency(evidence.currency, resource, `${path}.currency`);
3218
+ timestamp(evidence.observedAt, resource, `${path}.observedAt`);
3219
+ }
3220
+ function validateNoReconciliation(value, resource, path) {
3221
+ const reconciliation = record(value, resource, path);
3222
+ exact(reconciliation, ["status"], [], resource, path);
3223
+ if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
3224
+ }
3225
+ function validateRequiredReconciliation(value, allowed, resource, path) {
3226
+ const reconciliation = record(value, resource, path);
3227
+ exact(reconciliation, ["status", "reasons"], [], resource, path);
3228
+ if (reconciliation.status !== "required")
3229
+ fail(resource, `${path}.status`, "required");
3230
+ const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
3231
+ if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
3232
+ let previous = -1;
3233
+ reasons.forEach((reason, index) => {
3234
+ const current = allowed.indexOf(reason);
3235
+ if (current < 0 || current <= previous) {
3236
+ fail(
3237
+ resource,
3238
+ `${path}.reasons[${index}]`,
3239
+ "unique canonical-sorted reconciliation reason"
3240
+ );
3241
+ }
3242
+ previous = current;
3243
+ });
3244
+ }
3245
+ function validateNextAction(value, resource, path) {
3246
+ const action = record(value, resource, path);
3247
+ exact(
3248
+ action,
3249
+ [
3250
+ "type",
3251
+ "clientKey",
3252
+ "paymentMethodVariantKey",
3253
+ "agreementVariantKey",
3254
+ "providerOrderId",
3255
+ "providerCustomerKey",
3256
+ "orderName"
3257
+ ],
3258
+ ["customerName", "customerEmail"],
3259
+ resource,
3260
+ path
3261
+ );
3262
+ if (action.type !== "toss_widget")
3263
+ fail(resource, `${path}.type`, "toss_widget");
3264
+ for (const key of [
3265
+ "clientKey",
3266
+ "paymentMethodVariantKey",
3267
+ "agreementVariantKey"
3268
+ ]) {
3269
+ boundedString(action[key], 255, resource, `${path}.${key}`);
3270
+ }
3271
+ string(action.providerOrderId, resource, `${path}.providerOrderId`);
3272
+ string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
3273
+ boundedString(
3274
+ action.orderName,
3275
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3276
+ resource,
3277
+ `${path}.orderName`
3278
+ );
3279
+ if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
3280
+ fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
3281
+ }
3282
+ if (action.providerCustomerKey !== "ANONYMOUS" && !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
3283
+ action.providerCustomerKey
3284
+ )) {
3285
+ fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
3286
+ }
3287
+ if (action.customerName !== void 0)
3288
+ boundedString(
3289
+ action.customerName,
3290
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3291
+ resource,
3292
+ `${path}.customerName`
3293
+ );
3294
+ if (action.customerEmail !== void 0)
3295
+ validateCustomer({ email: action.customerEmail }, resource, path);
3296
+ }
3297
+ function validatePublicPaymentSession(value) {
3298
+ const resource = "PaymentSession";
3299
+ const session = record(value, resource, "$");
3300
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
3301
+ const status = enumValue(
3302
+ session.providerStatus,
3303
+ PAYMENT_PROVIDER_STATUSES,
3304
+ resource,
3305
+ "$.providerStatus"
3306
+ );
3307
+ const common = [
3308
+ "id",
3309
+ "money",
3310
+ "expiresAt",
3311
+ "sessionRole",
3312
+ "provider",
3313
+ "providerStatus",
3314
+ "presentationStatus",
3315
+ "finalizationStatus",
3316
+ "reconciliation",
3317
+ "order"
3318
+ ];
3319
+ const optional = [];
3320
+ if (status === "requires_payment_method" || status === "requires_action")
3321
+ optional.push("nextAction");
3322
+ else if (status === "captured") common.push("providerEvidence");
3323
+ else if (status === "failed") common.push("failure");
3324
+ else if (status === "canceled") common.push("cancellationReason");
3325
+ exact(session, common, optional, resource, "$");
3326
+ string(session.id, resource, "$.id");
3327
+ validateMoney(session.money, resource, "$.money");
3328
+ if (session.expiresAt !== null)
3329
+ timestamp(session.expiresAt, resource, "$.expiresAt");
3330
+ if (status === "requires_payment_method" || status === "requires_action") {
3331
+ if (session.sessionRole === "active") {
3332
+ if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
3333
+ fail(resource, "$", "actionable active not-ready state");
3334
+ }
3335
+ if (!("nextAction" in session))
3336
+ fail(resource, "$.nextAction", "required field");
3337
+ validateNextAction(session.nextAction, resource, "$.nextAction");
3338
+ } else if (session.sessionRole === "residual") {
3339
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3340
+ fail(resource, "$", "suppressed residual not-ready state");
3341
+ }
3342
+ if ("nextAction" in session)
3343
+ fail(resource, "$.nextAction", "absent for suppressed state");
3344
+ } else fail(resource, "$.sessionRole", "active | residual");
3345
+ validateNoReconciliation(
3346
+ session.reconciliation,
3347
+ resource,
3348
+ "$.reconciliation"
3349
+ );
3350
+ if (session.order !== null) fail(resource, "$.order", "null");
3351
+ } else if ([
3352
+ "requires_confirmation",
3353
+ "initializing",
3354
+ "processing",
3355
+ "authorized",
3356
+ "canceling"
3357
+ ].includes(status)) {
3358
+ enumValue(
3359
+ session.sessionRole,
3360
+ ["active", "residual"],
3361
+ resource,
3362
+ "$.sessionRole"
3363
+ );
3364
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3365
+ fail(resource, "$", "suppressed not-ready state");
3366
+ }
3367
+ validateNoReconciliation(
3368
+ session.reconciliation,
3369
+ resource,
3370
+ "$.reconciliation"
3371
+ );
3372
+ if (session.order !== null) fail(resource, "$.order", "null");
3373
+ } else if (status === "unknown") {
3374
+ enumValue(
3375
+ session.sessionRole,
3376
+ ["active", "residual"],
3377
+ resource,
3378
+ "$.sessionRole"
3379
+ );
3380
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3381
+ fail(resource, "$", "suppressed not-ready state");
3382
+ }
3383
+ validateRequiredReconciliation(
3384
+ session.reconciliation,
3385
+ ["provider_outcome_unknown"],
3386
+ resource,
3387
+ "$.reconciliation"
3388
+ );
3389
+ if (session.order !== null) fail(resource, "$.order", "null");
3390
+ } else if (status === "captured") {
3391
+ validateCaptureEvidence(
3392
+ session.providerEvidence,
3393
+ resource,
3394
+ "$.providerEvidence"
3395
+ );
3396
+ if (session.presentationStatus !== "suppressed")
3397
+ fail(resource, "$.presentationStatus", "suppressed");
3398
+ if (session.finalizationStatus === "pending") {
3399
+ enumValue(
3400
+ session.sessionRole,
3401
+ ["canonical_candidate", "residual"],
3402
+ resource,
3403
+ "$.sessionRole"
3404
+ );
3405
+ if (session.order !== null)
3406
+ fail(resource, "$.order", "null for pending finalization");
3407
+ const reconciliation = record(
3408
+ session.reconciliation,
3409
+ resource,
3410
+ "$.reconciliation"
3411
+ );
3412
+ if (reconciliation.status === "none")
3413
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3414
+ else
3415
+ validateRequiredReconciliation(
3416
+ reconciliation,
3417
+ [
3418
+ "local_commit_ambiguous",
3419
+ "amount_mismatch",
3420
+ "currency_mismatch",
3421
+ "excess_capture_pending_order"
3422
+ ],
3423
+ resource,
3424
+ "$.reconciliation"
3425
+ );
3426
+ } else if (session.finalizationStatus === "committed") {
3427
+ validateOrderReference(session.order, resource, "$.order");
3428
+ const reconciliation = record(
3429
+ session.reconciliation,
3430
+ resource,
3431
+ "$.reconciliation"
3432
+ );
3433
+ if (reconciliation.status === "none") {
3434
+ enumValue(
3435
+ session.sessionRole,
3436
+ ["canonical", "historical"],
3437
+ resource,
3438
+ "$.sessionRole"
3439
+ );
3440
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3441
+ } else {
3442
+ enumValue(
3443
+ session.sessionRole,
3444
+ ["canonical", "residual"],
3445
+ resource,
3446
+ "$.sessionRole"
3447
+ );
3448
+ validateRequiredReconciliation(
3449
+ reconciliation,
3450
+ [
3451
+ "inventory_unavailable",
3452
+ "admission_unavailable",
3453
+ "amount_mismatch",
3454
+ "currency_mismatch",
3455
+ "excess_capture",
3456
+ "late_capture",
3457
+ "cross_checkout_duplicate"
3458
+ ],
3459
+ resource,
3460
+ "$.reconciliation"
3461
+ );
3462
+ }
3463
+ } else fail(resource, "$.finalizationStatus", "pending | committed");
3464
+ } else if (status === "failed") {
3465
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3466
+ fail(resource, "$", "historical suppressed failed state");
3467
+ }
3468
+ validateNoReconciliation(
3469
+ session.reconciliation,
3470
+ resource,
3471
+ "$.reconciliation"
3472
+ );
3473
+ const failure = record(session.failure, resource, "$.failure");
3474
+ exact(failure, ["reason"], ["message"], resource, "$.failure");
3475
+ enumValue(
3476
+ failure.reason,
3477
+ PAYMENT_FAILURE_REASONS,
3478
+ resource,
3479
+ "$.failure.reason"
3480
+ );
3481
+ if (failure.message !== void 0)
3482
+ string(failure.message, resource, "$.failure.message");
3483
+ } else {
3484
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3485
+ fail(resource, "$", "historical suppressed canceled state");
3486
+ }
3487
+ validateNoReconciliation(
3488
+ session.reconciliation,
3489
+ resource,
3490
+ "$.reconciliation"
3491
+ );
3492
+ enumValue(
3493
+ session.cancellationReason,
3494
+ ["expired", "customer", "operator", "provider"],
3495
+ resource,
3496
+ "$.cancellationReason"
3497
+ );
3498
+ }
3499
+ return value;
1581
3500
  }
1582
- var ContentClient = class {
1583
- constructor(options) {
1584
- const api = new PublicContentApi("ContentClient", {
1585
- publishableKey: options.publishableKey,
1586
- apiUrl: options.apiUrl,
1587
- onRequestId: options.onRequestId,
1588
- requiresCredential: false
1589
- });
1590
- this.links = {
1591
- list: (params) => api.get(linksListPath(params))
1592
- };
1593
- this.galleryItems = {
1594
- list: (params) => api.get(
1595
- galleryItemsListPath(params)
1596
- )
1597
- };
1598
- }
1599
- };
1600
3501
 
1601
3502
  // src/core/customer/customer-auth.ts
1602
3503
  var DEFAULT_TIMEOUT2 = 15e3;
@@ -1615,8 +3516,10 @@ var CustomerAuth = class {
1615
3516
  const persist = options?.persist ?? true;
1616
3517
  if (persist) {
1617
3518
  const key = typeof persist === "string" ? persist : "customer-token";
3519
+ const refreshKey = `${key}:refresh`;
1618
3520
  const isBrowser = typeof window !== "undefined";
1619
3521
  this.token = isBrowser ? safeGetItem(key) : null;
3522
+ this.refreshTokenValue = isBrowser ? safeGetItem(refreshKey) : null;
1620
3523
  this.onTokenChange = isBrowser ? (token) => {
1621
3524
  try {
1622
3525
  if (token) localStorage.setItem(key, token);
@@ -1624,9 +3527,18 @@ var CustomerAuth = class {
1624
3527
  } catch {
1625
3528
  }
1626
3529
  } : void 0;
3530
+ this.onRefreshTokenChange = isBrowser ? (refreshToken) => {
3531
+ try {
3532
+ if (refreshToken) localStorage.setItem(refreshKey, refreshToken);
3533
+ else localStorage.removeItem(refreshKey);
3534
+ } catch {
3535
+ }
3536
+ } : void 0;
1627
3537
  } else {
1628
3538
  this.token = options?.token ?? null;
3539
+ this.refreshTokenValue = options?.refreshToken ?? null;
1629
3540
  this.onTokenChange = options?.onTokenChange;
3541
+ this.onRefreshTokenChange = options?.onRefreshTokenChange;
1630
3542
  }
1631
3543
  }
1632
3544
  /**
@@ -1650,13 +3562,17 @@ var CustomerAuth = class {
1650
3562
  }
1651
3563
  );
1652
3564
  this.setToken(result.token);
3565
+ if (result.refreshToken) this.setRefreshToken(result.refreshToken);
1653
3566
  return result;
1654
3567
  }
1655
3568
  /**
1656
- * Refresh the current token. Requires a valid (non-expired) token.
3569
+ * Refresh the current token. Uses a refresh token when available, otherwise
3570
+ * falls back to the legacy bearer-token compatibility path.
1657
3571
  */
1658
3572
  async refreshToken() {
1659
- if (!this.token) throw new ApiError("Not authenticated", 401);
3573
+ if (!this.refreshTokenValue && !this.token) {
3574
+ throw new ApiError("Not authenticated", 401);
3575
+ }
1660
3576
  if (this.refreshPromise) return this.refreshPromise;
1661
3577
  this.refreshPromise = this._doRefreshToken();
1662
3578
  try {
@@ -1666,14 +3582,19 @@ var CustomerAuth = class {
1666
3582
  }
1667
3583
  }
1668
3584
  async _doRefreshToken() {
3585
+ const init = this.refreshTokenValue ? {
3586
+ method: "POST",
3587
+ body: JSON.stringify({ refreshToken: this.refreshTokenValue })
3588
+ } : {
3589
+ method: "POST",
3590
+ headers: { Authorization: `Bearer ${this.token}` }
3591
+ };
1669
3592
  const result = await this.requestJson(
1670
3593
  "/api/customers/refresh",
1671
- {
1672
- method: "POST",
1673
- headers: { Authorization: `Bearer ${this.token}` }
1674
- }
3594
+ init
1675
3595
  );
1676
3596
  this.setToken(result.token);
3597
+ if (result.refreshToken) this.setRefreshToken(result.refreshToken);
1677
3598
  return result;
1678
3599
  }
1679
3600
  /**
@@ -1681,6 +3602,7 @@ var CustomerAuth = class {
1681
3602
  */
1682
3603
  logout() {
1683
3604
  this.setToken(null);
3605
+ this.setRefreshToken(null);
1684
3606
  }
1685
3607
  /**
1686
3608
  * Get the current authenticated customer's profile
@@ -1756,25 +3678,28 @@ var CustomerAuth = class {
1756
3678
  const params = new URLSearchParams();
1757
3679
  if (options?.page) params.set("page", String(options.page));
1758
3680
  if (options?.limit) params.set("limit", String(options.limit));
1759
- if (options?.displayFinancialStatus) {
1760
- params.set("displayFinancialStatus", options.displayFinancialStatus);
3681
+ if (options?.financialStatus) {
3682
+ params.set("financialStatus", options.financialStatus);
1761
3683
  }
1762
- if (options?.displayFulfillmentStatus) {
1763
- params.set("displayFulfillmentStatus", options.displayFulfillmentStatus);
3684
+ if (options?.fulfillmentStatus) {
3685
+ params.set("fulfillmentStatus", options.fulfillmentStatus);
1764
3686
  }
1765
3687
  if (options?.returnStatus) params.set("returnStatus", options.returnStatus);
3688
+ if (options?.confirmationStatus) {
3689
+ params.set("confirmationStatus", options.confirmationStatus);
3690
+ }
1766
3691
  if (options?.primaryDisplayStatus) {
1767
3692
  params.set("primaryDisplayStatus", options.primaryDisplayStatus);
1768
3693
  }
1769
- if (options?.returnDisplayStatus) {
1770
- params.set("returnDisplayStatus", options.returnDisplayStatus);
1771
- }
1772
- if (options?.status) params.set("status", options.status);
1773
3694
  const qs = params.toString();
1774
- return this.requestJson(`/api/customers/me/orders${qs ? `?${qs}` : ""}`, {
1775
- method: "GET",
1776
- headers: { Authorization: `Bearer ${this.token}` }
1777
- });
3695
+ const result = await this.requestJson(
3696
+ `/api/customers/me/orders${qs ? `?${qs}` : ""}`,
3697
+ {
3698
+ method: "GET",
3699
+ headers: { Authorization: `Bearer ${this.token}` }
3700
+ }
3701
+ );
3702
+ return validatePublicOrderList(result);
1778
3703
  }
1779
3704
  /**
1780
3705
  * Get the current token (or null if not authenticated)
@@ -1782,6 +3707,12 @@ var CustomerAuth = class {
1782
3707
  getToken() {
1783
3708
  return this.token;
1784
3709
  }
3710
+ /**
3711
+ * Get the current refresh token (or null if unavailable)
3712
+ */
3713
+ getRefreshToken() {
3714
+ return this.refreshTokenValue;
3715
+ }
1785
3716
  /**
1786
3717
  * Set the token manually (e.g. from SSR)
1787
3718
  */
@@ -1789,6 +3720,13 @@ var CustomerAuth = class {
1789
3720
  this.token = token;
1790
3721
  this.onTokenChange?.(token);
1791
3722
  }
3723
+ /**
3724
+ * Set the refresh token manually (e.g. from SSR cookie)
3725
+ */
3726
+ setRefreshToken(refreshToken) {
3727
+ this.refreshTokenValue = refreshToken;
3728
+ this.onRefreshTokenChange?.(refreshToken);
3729
+ }
1792
3730
  /**
1793
3731
  * Check if the customer is currently authenticated
1794
3732
  */
@@ -1817,91 +3755,362 @@ var CustomerAuth = class {
1817
3755
  }
1818
3756
  };
1819
3757
 
3758
+ // src/core/customer/customer-oauth.ts
3759
+ var DEFAULT_SCOPES = ["openid", "profile", "email"];
3760
+ var DEFAULT_TIMEOUT3 = 15e3;
3761
+ function issuerUrl(issuer, path) {
3762
+ const base = resolveApiUrl(issuer);
3763
+ return new URL(path, base.endsWith("/") ? base : `${base}/`).toString();
3764
+ }
3765
+ function randomBase64Url(bytes) {
3766
+ const buffer = new Uint8Array(bytes);
3767
+ crypto.getRandomValues(buffer);
3768
+ let binary = "";
3769
+ for (const value of buffer) {
3770
+ binary += String.fromCharCode(value);
3771
+ }
3772
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
3773
+ }
3774
+ async function sha256Base64Url(value) {
3775
+ const data = new TextEncoder().encode(value);
3776
+ const digest = await crypto.subtle.digest("SHA-256", data);
3777
+ let binary = "";
3778
+ for (const byte of new Uint8Array(digest)) {
3779
+ binary += String.fromCharCode(byte);
3780
+ }
3781
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
3782
+ }
3783
+ function normalizeToken(body) {
3784
+ if (body.token_type !== "Bearer") {
3785
+ throw new Error("Unsupported customer OAuth token type");
3786
+ }
3787
+ return {
3788
+ accessToken: body.access_token,
3789
+ expiresAt: Date.now() + body.expires_in * 1e3,
3790
+ expiresIn: body.expires_in,
3791
+ ...body.id_token ? { idToken: body.id_token } : {},
3792
+ refreshToken: body.refresh_token,
3793
+ ...body.scope ? { scope: body.scope } : {},
3794
+ tokenType: "Bearer"
3795
+ };
3796
+ }
3797
+ var CustomerOAuth = class {
3798
+ constructor(config) {
3799
+ if (!config.clientId) throw new Error("customer OAuth clientId is required");
3800
+ if (!config.issuer) throw new Error("customer OAuth issuer is required");
3801
+ this.clientId = config.clientId;
3802
+ this.issuer = config.issuer;
3803
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT3;
3804
+ }
3805
+ async createAuthorizationUrl(input) {
3806
+ const codeVerifier = randomBase64Url(48);
3807
+ const codeChallenge = await sha256Base64Url(codeVerifier);
3808
+ const state = randomBase64Url(32);
3809
+ const nonce = randomBase64Url(32);
3810
+ const scopes = input.scopes ?? DEFAULT_SCOPES;
3811
+ const url = new URL(issuerUrl(this.issuer, "customer-oauth/authorize"));
3812
+ url.searchParams.set("response_type", "code");
3813
+ url.searchParams.set("client_id", this.clientId);
3814
+ url.searchParams.set("redirect_uri", input.redirectUri);
3815
+ url.searchParams.set("scope", scopes.join(" "));
3816
+ url.searchParams.set("state", state);
3817
+ url.searchParams.set("nonce", nonce);
3818
+ url.searchParams.set("code_challenge", codeChallenge);
3819
+ url.searchParams.set("code_challenge_method", "S256");
3820
+ return {
3821
+ authorizationUrl: url.toString(),
3822
+ codeChallenge,
3823
+ codeVerifier,
3824
+ nonce,
3825
+ returnTo: input.returnTo ?? null,
3826
+ state
3827
+ };
3828
+ }
3829
+ parseCallback(callbackUrl, options) {
3830
+ const url = new URL(callbackUrl);
3831
+ const error = url.searchParams.get("error");
3832
+ if (error) {
3833
+ throw new Error(
3834
+ url.searchParams.get("error_description") ?? `OAuth error: ${error}`
3835
+ );
3836
+ }
3837
+ const code = url.searchParams.get("code");
3838
+ const state = url.searchParams.get("state");
3839
+ if (!code || !state) throw new Error("OAuth callback is missing code/state");
3840
+ if (state !== options.expectedState) throw new Error("OAuth state mismatch");
3841
+ return { code, state };
3842
+ }
3843
+ async exchangeCode(input) {
3844
+ const body = new URLSearchParams({
3845
+ client_id: this.clientId,
3846
+ code: input.code,
3847
+ code_verifier: input.codeVerifier,
3848
+ grant_type: "authorization_code",
3849
+ redirect_uri: input.redirectUri
3850
+ });
3851
+ return this.tokenRequest(body);
3852
+ }
3853
+ async refresh(input) {
3854
+ const body = new URLSearchParams({
3855
+ client_id: this.clientId,
3856
+ grant_type: "refresh_token",
3857
+ refresh_token: input.refreshToken
3858
+ });
3859
+ return this.tokenRequest(body);
3860
+ }
3861
+ async logout(input) {
3862
+ const body = { client_id: this.clientId };
3863
+ if (input.refreshToken) body.refresh_token = input.refreshToken;
3864
+ if (input.postLogoutRedirectUri) {
3865
+ body.post_logout_redirect_uri = input.postLogoutRedirectUri;
3866
+ }
3867
+ const response = await httpFetch("/customer-oauth/logout", {
3868
+ apiUrl: this.issuer,
3869
+ method: "POST",
3870
+ body: JSON.stringify(body),
3871
+ headers: { "Content-Type": "application/json" },
3872
+ timeout: this.timeout,
3873
+ retry: { maxRetries: 0 }
3874
+ });
3875
+ return parseApiResponse(
3876
+ response,
3877
+ "/customer-oauth/logout"
3878
+ );
3879
+ }
3880
+ verifyIdToken() {
3881
+ throw new Error(
3882
+ "Customer OAuth ID token verification is not implemented; treat idToken as opaque."
3883
+ );
3884
+ }
3885
+ async tokenRequest(body) {
3886
+ const response = await httpFetch("/api/customer-oauth/token", {
3887
+ apiUrl: this.issuer,
3888
+ method: "POST",
3889
+ body,
3890
+ headers: {
3891
+ "Content-Type": "application/x-www-form-urlencoded"
3892
+ },
3893
+ timeout: this.timeout,
3894
+ retry: { maxRetries: 0 }
3895
+ });
3896
+ return normalizeToken(
3897
+ await parseApiResponse(
3898
+ response,
3899
+ "/api/customer-oauth/token"
3900
+ )
3901
+ );
3902
+ }
3903
+ };
3904
+
1820
3905
  // src/core/customer/customer-namespace.ts
1821
3906
  var CustomerNamespace = class {
1822
3907
  constructor(publishableKey, options, apiUrl) {
1823
3908
  this.auth = new CustomerAuth(publishableKey, options, apiUrl);
3909
+ if (options?.oauth) {
3910
+ this.oauth = new CustomerOAuth(options.oauth);
3911
+ }
1824
3912
  }
1825
3913
  };
1826
3914
 
3915
+ // src/core/api/commerce-idempotency.ts
3916
+ var UUID_V4_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
3917
+ var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
3918
+ function isCommerceIdempotencyKey(value) {
3919
+ return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
3920
+ }
3921
+ function assertCommerceIdempotencyKey(value) {
3922
+ if (isCommerceIdempotencyKey(value)) return;
3923
+ throw createValidationError(
3924
+ "idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
3925
+ { field: "idempotencyKey" }
3926
+ );
3927
+ }
3928
+ function createCommerceIdempotencyKey() {
3929
+ return globalThis.crypto.randomUUID();
3930
+ }
3931
+
1827
3932
  // src/core/api/cart-api.ts
3933
+ var MAX_CART_LINE_ADMISSIONS = 32;
1828
3934
  var CartApi = class extends CustomerScopedApi {
1829
3935
  constructor(options) {
1830
3936
  super("CartApi", { ...options, requiresCredential: false });
3937
+ this.serverTransport = Boolean(options.secretKey);
1831
3938
  }
1832
- async execute(endpoint, method, body) {
1833
- return this.request(endpoint, { method, body });
3939
+ endpoint(key) {
3940
+ return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
1834
3941
  }
1835
- /**
1836
- * Create a cart and receive its `cartToken`. Store the token and pass it to
1837
- * every subsequent cart operation.
1838
- */
1839
- createCart(params = {}) {
1840
- return this.execute("/api/carts/create", "POST", params);
3942
+ execute(endpoint2, body, idempotencyKey) {
3943
+ return this.requestEndpoint(endpoint2, body, {
3944
+ ...idempotencyKey && {
3945
+ headers: { "X-Idempotency-Key": idempotencyKey }
3946
+ }
3947
+ });
1841
3948
  }
1842
- getCart(cartToken) {
1843
- return this.execute("/api/carts/get", "POST", { cartToken });
3949
+ create(params = {}) {
3950
+ return this.execute(this.endpoint("create"), params).then(
3951
+ (value) => validateCreateCartResult(value)
3952
+ );
1844
3953
  }
1845
- merge(params) {
1846
- return this.execute(
1847
- COMMERCE_ENDPOINTS.carts.merge,
1848
- "POST",
1849
- params
3954
+ retrieve(params) {
3955
+ return this.execute(this.endpoint("retrieve"), params).then(
3956
+ (value) => validatePublicCart(value)
1850
3957
  );
1851
3958
  }
1852
- /**
1853
- * Resolve the authenticated customer's active cart by JWT (no `cartToken`
1854
- * required). Returns the cart and its capability handle, or both `null` when
1855
- * the customer has no active cart. Requires a customer token.
1856
- */
1857
- mine() {
1858
- return this.execute(
1859
- COMMERCE_ENDPOINTS.carts.mine,
1860
- "POST",
1861
- {}
3959
+ mine(params = {}) {
3960
+ const endpoint2 = this.endpoint("mine");
3961
+ return this.execute(endpoint2, params).then(
3962
+ (value) => validateCartMineResult(value)
3963
+ );
3964
+ }
3965
+ merge(params) {
3966
+ const { idempotencyKey, ...body } = params;
3967
+ assertCommerceIdempotencyKey(idempotencyKey);
3968
+ const endpoint2 = this.endpoint("merge");
3969
+ return this.execute(endpoint2, body, idempotencyKey).then(
3970
+ (value) => validateCartMergeResult(value)
1862
3971
  );
1863
3972
  }
1864
3973
  addItem(params) {
1865
- return this.execute(
1866
- COMMERCE_ENDPOINTS.carts.addItem,
1867
- "POST",
1868
- params
3974
+ return this.mutate(this.endpoint("addItem"), params);
3975
+ }
3976
+ mutate(endpoint2, params) {
3977
+ const { idempotencyKey, ...body } = params;
3978
+ assertCommerceIdempotencyKey(idempotencyKey);
3979
+ return this.execute(endpoint2, body, idempotencyKey).then(
3980
+ (value) => validateCartMutationResult(value)
1869
3981
  );
1870
3982
  }
1871
3983
  updateItem(params) {
1872
- return this.execute(
1873
- COMMERCE_ENDPOINTS.carts.updateItem,
1874
- "POST",
1875
- params
1876
- );
3984
+ return this.mutate(this.endpoint("updateItem"), params);
1877
3985
  }
1878
3986
  removeItem(params) {
1879
- return this.execute(
1880
- COMMERCE_ENDPOINTS.carts.removeItem,
1881
- "POST",
1882
- params
3987
+ return this.mutate(this.endpoint("removeItem"), params);
3988
+ }
3989
+ clear(params) {
3990
+ return this.mutate(this.endpoint("clear"), params);
3991
+ }
3992
+ updateDiscountCodes(params) {
3993
+ return this.mutate(this.endpoint("updateDiscountCodes"), params);
3994
+ }
3995
+ updateAttributes(params) {
3996
+ return this.mutate(this.endpoint("updateAttributes"), params);
3997
+ }
3998
+ };
3999
+
4000
+ // src/core/api/checkout-api.ts
4001
+ var CheckoutApi = class extends CustomerScopedApi {
4002
+ constructor(options) {
4003
+ super("CheckoutApi", { ...options, requiresCredential: false });
4004
+ }
4005
+ post(endpoint2, body, idempotencyKey) {
4006
+ return this.requestEndpoint(endpoint2, body, {
4007
+ ...idempotencyKey && {
4008
+ headers: { "X-Idempotency-Key": idempotencyKey }
4009
+ }
4010
+ });
4011
+ }
4012
+ async publicCheckout(result) {
4013
+ return validatePublicCheckout(await result);
4014
+ }
4015
+ async serverCheckout(result) {
4016
+ return validateServerCheckout(await result);
4017
+ }
4018
+ async createResult(result) {
4019
+ return validateCreateCheckoutResult(
4020
+ await result,
4021
+ false
1883
4022
  );
1884
4023
  }
1885
- applyDiscount(params) {
1886
- return this.execute(
1887
- COMMERCE_ENDPOINTS.carts.applyDiscount,
1888
- "POST",
1889
- params
4024
+ async createServerResult(result) {
4025
+ return validateCreateCheckoutResult(
4026
+ await result,
4027
+ true
1890
4028
  );
1891
4029
  }
1892
- removeDiscount(params) {
1893
- return this.execute(
1894
- COMMERCE_ENDPOINTS.carts.removeDiscount,
1895
- "POST",
1896
- params
4030
+ create(params) {
4031
+ const { idempotencyKey, ...body } = params;
4032
+ assertCommerceIdempotencyKey(idempotencyKey);
4033
+ return this.createResult(
4034
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
1897
4035
  );
1898
4036
  }
1899
- clearCart(params) {
1900
- return this.execute(
1901
- COMMERCE_ENDPOINTS.carts.clear,
1902
- "POST",
4037
+ createServer(params) {
4038
+ const { idempotencyKey, ...body } = params;
4039
+ assertCommerceIdempotencyKey(idempotencyKey);
4040
+ return this.createServerResult(
4041
+ this.post(
4042
+ COMMERCE_ENDPOINTS.checkouts.server.create,
4043
+ body,
4044
+ idempotencyKey
4045
+ )
4046
+ );
4047
+ }
4048
+ retrieve(params) {
4049
+ return this.publicCheckout(
4050
+ this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
4051
+ );
4052
+ }
4053
+ retrieveServer(params) {
4054
+ return this.serverCheckout(
4055
+ this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
4056
+ );
4057
+ }
4058
+ async query(params = {}) {
4059
+ const result = await this.post(
4060
+ COMMERCE_ENDPOINTS.checkouts.server.query,
1903
4061
  params
1904
4062
  );
4063
+ return validateCheckoutQueryResult(result);
4064
+ }
4065
+ };
4066
+
4067
+ // src/core/api/payment-session-api.ts
4068
+ var PaymentSessionApi = class extends CustomerScopedApi {
4069
+ constructor(options) {
4070
+ super("PaymentSessionApi", { ...options, requiresCredential: false });
4071
+ this.serverTransport = Boolean(options.secretKey);
4072
+ }
4073
+ post(endpoint2, body, idempotencyKey) {
4074
+ return this.requestEndpoint(endpoint2, body, {
4075
+ ...idempotencyKey && {
4076
+ headers: { "X-Idempotency-Key": idempotencyKey }
4077
+ }
4078
+ });
4079
+ }
4080
+ async paymentSession(result) {
4081
+ return validatePublicPaymentSession(await result);
4082
+ }
4083
+ create(params) {
4084
+ const { idempotencyKey, ...body } = params;
4085
+ assertCommerceIdempotencyKey(idempotencyKey);
4086
+ return this.paymentSession(
4087
+ this.post(
4088
+ this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
4089
+ body,
4090
+ idempotencyKey
4091
+ )
4092
+ );
4093
+ }
4094
+ retrieve(params) {
4095
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4096
+ return this.paymentSession(this.post(endpoint2, params));
4097
+ }
4098
+ cancel(params) {
4099
+ const { idempotencyKey, ...body } = params;
4100
+ assertCommerceIdempotencyKey(idempotencyKey);
4101
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4102
+ return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
4103
+ }
4104
+ confirm(params) {
4105
+ const { idempotencyKey, ...body } = params;
4106
+ assertCommerceIdempotencyKey(idempotencyKey);
4107
+ return this.paymentSession(
4108
+ this.post(
4109
+ COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
4110
+ body,
4111
+ idempotencyKey
4112
+ )
4113
+ );
1905
4114
  }
1906
4115
  };
1907
4116
 
@@ -2904,9 +5113,13 @@ function resolveVariantIdForCompleteSelection(matrix, selectedByOptionId) {
2904
5113
  return getExactSelectedVariantEntry(matrix, normalized, matchingVariantEntries)?.id ?? null;
2905
5114
  }
2906
5115
  function buildSelectionPrice(variants) {
2907
- const { min, max } = getMinMax(variants.map((variant) => variant.price));
5116
+ const { min, max } = getMinMax(
5117
+ variants.map((variant) => variant.resolvedPrice?.amount ?? variant.price)
5118
+ );
2908
5119
  const { min: compareAtMin, max: compareAtMax } = getMinMax(
2909
- variants.map((variant) => variant.compareAtPrice)
5120
+ variants.map(
5121
+ (variant) => variant.resolvedPrice?.compareAtPrice ?? variant.compareAtPrice
5122
+ )
2910
5123
  );
2911
5124
  return {
2912
5125
  min,
@@ -2966,8 +5179,8 @@ function buildSelectionStock(selectedVariant, matchingVariants) {
2966
5179
  return {
2967
5180
  availableForSale: getVariantAvailableForSale(selectedVariant),
2968
5181
  isUnlimited: selectedVariant.isUnlimited,
2969
- stock: selectedVariant.stock,
2970
- reservedStock: selectedVariant.reservedStock,
5182
+ stock: "stock" in selectedVariant ? selectedVariant.stock : null,
5183
+ reservedStock: "reservedStock" in selectedVariant ? selectedVariant.reservedStock : null,
2971
5184
  availableStock
2972
5185
  };
2973
5186
  }
@@ -3349,6 +5562,9 @@ function compareVariantOrder(a, b) {
3349
5562
  }
3350
5563
  function getVariantAvailableForSale(variant) {
3351
5564
  if (variant.isActive === false) return false;
5565
+ if (typeof variant.availableForSale === "boolean") {
5566
+ return variant.availableForSale;
5567
+ }
3352
5568
  if (variant.isUnlimited) return true;
3353
5569
  if (variant.inventoryPolicy === "continue") return true;
3354
5570
  return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
@@ -3462,7 +5678,7 @@ function buildProductListingCard(item, options = {}) {
3462
5678
  { listing: { selectionHintVariant } },
3463
5679
  options
3464
5680
  ),
3465
- title: product.title,
5681
+ title: product.title ?? "",
3466
5682
  representativeVariant,
3467
5683
  primaryImage: listingPrimaryMedia,
3468
5684
  priceRange,
@@ -3649,6 +5865,11 @@ function productDetailResultFromError(error) {
3649
5865
  if (!reason) return void 0;
3650
5866
  return { found: false, reason };
3651
5867
  }
5868
+ var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
5869
+ var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
5870
+ "priceRange.minVariantPrice.amount",
5871
+ "priceRange.maxVariantPrice.amount"
5872
+ ]);
3652
5873
  function nonEmpty(values) {
3653
5874
  return values?.length ? values : void 0;
3654
5875
  }
@@ -3696,14 +5917,34 @@ function buildProductListingPageWhere(params) {
3696
5917
  if (clauses.length === 1) return clauses[0];
3697
5918
  return { and: clauses };
3698
5919
  }
3699
- function buildProductListingPageUrl(params) {
5920
+ function productListingPageUsesBasePriceSort(sort) {
5921
+ const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
5922
+ return values.some(
5923
+ (value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
5924
+ );
5925
+ }
5926
+ function assertMarketListingPageQuerySupported(params) {
5927
+ if (!params.market?.trim()) return;
5928
+ const priceFilter = params.filters?.price;
5929
+ if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
5930
+ throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
5931
+ }
5932
+ }
5933
+ function buildProductListingPageRequest(params) {
5934
+ assertMarketListingPageQuerySupported(params);
3700
5935
  const options = {
5936
+ market: params.market,
5937
+ locale: params.locale,
5938
+ fallbackLocale: params.fallbackLocale,
3701
5939
  page: params.page,
3702
5940
  limit: params.limit,
3703
5941
  sort: params.sort,
3704
5942
  where: buildProductListingPageWhere(params)
3705
5943
  };
3706
- return params.mode === "full" ? listingGroupsQueryUrl(options) : listingGroupsQueryCatalogUrl(options);
5944
+ return {
5945
+ operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
5946
+ query: listingPageSearchParams(options)
5947
+ };
3707
5948
  }
3708
5949
  function withProductListingCards(response, options) {
3709
5950
  return {
@@ -3720,30 +5961,15 @@ function isProductUpsertFieldValidationErrorBody(value) {
3720
5961
  return typeof body.error === "string" && typeof body.field === "string" && (reason === PRODUCT_UPSERT_UNKNOWN_FIELD_REASON || reason === PRODUCT_UPSERT_READONLY_FIELD_REASON);
3721
5962
  }
3722
5963
 
3723
- // src/core/api/order-api.ts
3724
- function idempotencyRequestOptions(idempotencyKey) {
3725
- return idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0;
3726
- }
3727
- function splitIdempotencyKey(params) {
3728
- const { idempotencyKey, ...body } = params;
3729
- return { body, idempotencyKey };
3730
- }
3731
-
3732
5964
  // src/core/commerce/commerce-client.ts
3733
5965
  var BrowserCommerceApi = class extends CustomerScopedApi {
3734
- post(endpoint, body, requestOptions) {
3735
- return this.request(endpoint, {
3736
- method: "POST",
3737
- body,
3738
- headers: requestOptions?.headers
3739
- });
3740
- }
3741
- get(endpoint) {
3742
- return this.request(endpoint, { method: "GET" });
5966
+ requestEndpoint(endpoint2, body, options) {
5967
+ return super.requestEndpoint(endpoint2, body, options);
3743
5968
  }
3744
5969
  };
3745
5970
  var CommerceClient = class {
3746
5971
  constructor(options) {
5972
+ this.market = options.market;
3747
5973
  const cartApi = new CartApi({
3748
5974
  publishableKey: options.publishableKey,
3749
5975
  apiUrl: options.apiUrl,
@@ -3751,6 +5977,20 @@ var CommerceClient = class {
3751
5977
  onUnauthorized: options.onUnauthorized,
3752
5978
  onRequestId: options.onRequestId
3753
5979
  });
5980
+ const checkoutApi = new CheckoutApi({
5981
+ publishableKey: options.publishableKey,
5982
+ apiUrl: options.apiUrl,
5983
+ customerToken: options.customerToken,
5984
+ onUnauthorized: options.onUnauthorized,
5985
+ onRequestId: options.onRequestId
5986
+ });
5987
+ const paymentSessionApi = new PaymentSessionApi({
5988
+ publishableKey: options.publishableKey,
5989
+ apiUrl: options.apiUrl,
5990
+ customerToken: options.customerToken,
5991
+ onUnauthorized: options.onUnauthorized,
5992
+ onRequestId: options.onRequestId
5993
+ });
3754
5994
  const api = new BrowserCommerceApi("CommerceClient", {
3755
5995
  publishableKey: options.publishableKey,
3756
5996
  apiUrl: options.apiUrl,
@@ -3759,29 +5999,42 @@ var CommerceClient = class {
3759
5999
  onRequestId: options.onRequestId
3760
6000
  });
3761
6001
  this.product = {
3762
- stockCheck: (params) => api.post(
3763
- COMMERCE_ENDPOINTS.products.stockCheck,
6002
+ stockCheck: (params) => api.requestEndpoint(
6003
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
3764
6004
  params
3765
6005
  ),
3766
- stockSnapshot: (params) => api.get(stockSnapshotQuery(params)),
3767
- listingGroups: (params) => api.get(
3768
- listingGroupsCatalogQuery(params)
6006
+ stockSnapshot: (params) => api.requestEndpoint(
6007
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
6008
+ void 0,
6009
+ { query: stockSnapshotSearchParams(params) }
6010
+ ),
6011
+ listingGroups: (params) => api.requestEndpoint(
6012
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
6013
+ void 0,
6014
+ { query: listingGroupsSearchParams(this.withMarket(params)) }
3769
6015
  ),
3770
- listingGroupsCatalog: (params) => api.get(
3771
- listingGroupsCatalogQuery(params)
6016
+ listingGroupsCatalog: (params) => api.requestEndpoint(
6017
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
6018
+ void 0,
6019
+ { query: listingGroupsSearchParams(this.withMarket(params)) }
3772
6020
  ),
3773
6021
  listingPage: async (params = {}) => {
3774
6022
  const catalogParams = {
3775
6023
  ...params,
3776
6024
  mode: "catalog"
3777
6025
  };
3778
- const response = await api.get(buildProductListingPageUrl(catalogParams));
3779
- return withProductListingCards(response, catalogParams);
6026
+ const request = buildProductListingPageRequest(
6027
+ this.withMarket(catalogParams)
6028
+ );
6029
+ const response = await api.requestEndpoint(request.operation, void 0, { query: request.query });
6030
+ return withProductListingCards(response, this.withMarket(catalogParams));
3780
6031
  },
3781
6032
  detail: async (params) => {
3782
6033
  try {
3783
- const product = await api.get(
3784
- productDetailQuery(params)
6034
+ const product = await api.requestEndpoint(
6035
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
6036
+ void 0,
6037
+ { query: productDetailSearchParams(this.withMarket(params)) }
3785
6038
  );
3786
6039
  return { found: true, product };
3787
6040
  } catch (err) {
@@ -3792,8 +6045,10 @@ var CommerceClient = class {
3792
6045
  },
3793
6046
  detailCatalog: async (params) => {
3794
6047
  try {
3795
- const product = await api.get(
3796
- productDetailCatalogQuery(params)
6048
+ const product = await api.requestEndpoint(
6049
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
6050
+ void 0,
6051
+ { query: productDetailSearchParams(this.withMarket(params)) }
3797
6052
  );
3798
6053
  return { found: true, product };
3799
6054
  } catch (err) {
@@ -3803,39 +6058,51 @@ var CommerceClient = class {
3803
6058
  }
3804
6059
  }
3805
6060
  };
3806
- this.cart = {
3807
- create: cartApi.createCart.bind(cartApi),
3808
- get: cartApi.getCart.bind(cartApi),
6061
+ this.carts = {
6062
+ create: (params) => cartApi.create(this.withMarket(params ?? {})),
6063
+ retrieve: cartApi.retrieve.bind(cartApi),
3809
6064
  addItem: cartApi.addItem.bind(cartApi),
3810
6065
  updateItem: cartApi.updateItem.bind(cartApi),
3811
6066
  removeItem: cartApi.removeItem.bind(cartApi),
3812
- applyDiscount: cartApi.applyDiscount.bind(cartApi),
3813
- removeDiscount: cartApi.removeDiscount.bind(cartApi),
3814
- clear: cartApi.clearCart.bind(cartApi),
6067
+ updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
6068
+ updateAttributes: cartApi.updateAttributes.bind(cartApi),
6069
+ clear: cartApi.clear.bind(cartApi),
3815
6070
  merge: cartApi.merge.bind(cartApi),
3816
6071
  mine: cartApi.mine.bind(cartApi)
3817
6072
  };
3818
6073
  this.orders = {
3819
- checkout: (params) => {
3820
- const { body, idempotencyKey } = splitIdempotencyKey(params);
3821
- return api.post(
3822
- "/api/orders/checkout",
3823
- body,
3824
- idempotencyRequestOptions(idempotencyKey)
3825
- );
3826
- },
3827
6074
  listMine: (params) => options.customerAuth.getMyOrders(params)
3828
6075
  };
6076
+ this.checkouts = {
6077
+ create: checkoutApi.create.bind(checkoutApi),
6078
+ retrieve: checkoutApi.retrieve.bind(checkoutApi)
6079
+ };
6080
+ this.paymentSessions = {
6081
+ create: paymentSessionApi.create.bind(paymentSessionApi),
6082
+ retrieve: (params) => paymentSessionApi.retrieve(params),
6083
+ cancel: (params) => paymentSessionApi.cancel(params)
6084
+ };
3829
6085
  this.discounts = {
3830
- validate: (params) => api.post("/api/discounts/validate", params)
6086
+ validate: (params) => api.requestEndpoint(
6087
+ COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
6088
+ params
6089
+ )
3831
6090
  };
3832
6091
  this.shipping = {
3833
- calculate: (params) => api.post(
3834
- "/api/shipping-policies/calculate",
6092
+ calculate: (params) => api.requestEndpoint(
6093
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
3835
6094
  params
3836
6095
  )
3837
6096
  };
3838
6097
  }
6098
+ getDefaultMarket() {
6099
+ return this.market;
6100
+ }
6101
+ withMarket(params) {
6102
+ const defaultMarket = this.market?.trim();
6103
+ if (!defaultMarket || params.market?.trim()) return params;
6104
+ return { ...params, market: defaultMarket };
6105
+ }
3839
6106
  };
3840
6107
 
3841
6108
  // src/core/events/events-client.ts
@@ -3855,7 +6122,17 @@ var EventsClient = class {
3855
6122
  getRange(params) {
3856
6123
  return this.execute(
3857
6124
  buildRangeEndpoint(params),
3858
- "GET",
6125
+ resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
6126
+ void 0,
6127
+ { useCustomerAuth: false }
6128
+ );
6129
+ }
6130
+ getAdmissionAvailability(params) {
6131
+ return this.execute(
6132
+ buildAdmissionAvailabilityEndpoint(params),
6133
+ resolveOperationMethod(
6134
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
6135
+ ),
3859
6136
  void 0,
3860
6137
  { useCustomerAuth: false }
3861
6138
  );
@@ -3884,11 +6161,11 @@ var EventsClient = class {
3884
6161
  { useCustomerAuth: false }
3885
6162
  );
3886
6163
  }
3887
- async execute(endpoint, method, body, options = {}) {
6164
+ async execute(endpoint2, method, body, options = {}) {
3888
6165
  const useCustomerAuth = options.useCustomerAuth === true;
3889
6166
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
3890
6167
  try {
3891
- const response = await httpFetch(endpoint, {
6168
+ const response = await httpFetch(endpoint2, {
3892
6169
  method,
3893
6170
  apiUrl: this.apiUrl,
3894
6171
  publishableKey: this.publishableKey,
@@ -3897,7 +6174,7 @@ var EventsClient = class {
3897
6174
  ...body !== void 0 && { body: JSON.stringify(body) }
3898
6175
  });
3899
6176
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
3900
- return parseApiResponse(response, endpoint);
6177
+ return parseApiResponse(response, endpoint2);
3901
6178
  } catch (err) {
3902
6179
  const id = err instanceof SDKError ? err.requestId ?? null : null;
3903
6180
  this.onRequestId?.(id);
@@ -3936,7 +6213,17 @@ function buildRangeEndpoint(params) {
3936
6213
  appendValues(urlParams, "categorySlug", params.categorySlug);
3937
6214
  appendValues(urlParams, "tag", params.tag);
3938
6215
  appendValues(urlParams, "tagSlug", params.tagSlug);
3939
- return `/api/event-occurrences/range?${urlParams.toString()}`;
6216
+ return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
6217
+ query: urlParams
6218
+ });
6219
+ }
6220
+ function buildAdmissionAvailabilityEndpoint(params) {
6221
+ const urlParams = new URLSearchParams();
6222
+ urlParams.set("occurrence", params.occurrence);
6223
+ return resolveOperationPath(
6224
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
6225
+ { query: urlParams }
6226
+ );
3940
6227
  }
3941
6228
  function formatDateParam(value) {
3942
6229
  return value instanceof Date ? value.toISOString() : value;
@@ -3949,15 +6236,62 @@ function appendValues(params, key, value) {
3949
6236
  }
3950
6237
  }
3951
6238
 
6239
+ // src/core/market/market-discovery.ts
6240
+ function toMarketDTO(row) {
6241
+ return {
6242
+ id: row.id,
6243
+ handle: row.handle,
6244
+ name: row.name,
6245
+ countryCode: row.countryCode,
6246
+ targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
6247
+ currency: row.currency,
6248
+ isPrimary: row.isPrimary === true,
6249
+ isActive: row.isActive === true
6250
+ };
6251
+ }
6252
+ var MarketDiscovery = class {
6253
+ constructor(read) {
6254
+ this.read = read;
6255
+ }
6256
+ async list() {
6257
+ const res = await this.read({
6258
+ where: { isActive: { equals: true } },
6259
+ limit: 100
6260
+ });
6261
+ if (res.hasNextPage) {
6262
+ console.warn(
6263
+ "[markets.list] more than 100 active markets; results truncated to 100."
6264
+ );
6265
+ }
6266
+ return res.docs.map(toMarketDTO);
6267
+ }
6268
+ async default() {
6269
+ const res = await this.read({
6270
+ where: { isPrimary: { equals: true }, isActive: { equals: true } },
6271
+ limit: 1
6272
+ });
6273
+ const row = res.docs[0];
6274
+ return row ? toMarketDTO(row) : null;
6275
+ }
6276
+ };
6277
+
3952
6278
  // src/core/client/client.ts
3953
6279
  var BrowserMembershipApi = class extends CustomerScopedApi {
3954
6280
  me() {
3955
- return this.request(MEMBERSHIP_ENDPOINTS.me, {
3956
- method: "GET"
3957
- });
6281
+ return this.requestEndpoint(
6282
+ MEMBERSHIP_ENDPOINT_OPERATIONS.me
6283
+ );
6284
+ }
6285
+ cancel(params) {
6286
+ const { id, immediate } = params;
6287
+ return this.requestEndpoint(
6288
+ MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
6289
+ immediate !== void 0 ? { immediate } : {},
6290
+ { pathParams: { id } }
6291
+ );
3958
6292
  }
3959
6293
  };
3960
- var Client = class {
6294
+ var Client = class _Client {
3961
6295
  constructor(options) {
3962
6296
  this.lastRequestId = null;
3963
6297
  const publishableKey = options.publishableKey;
@@ -3989,6 +6323,7 @@ var Client = class {
3989
6323
  this.commerce = new CommerceClient({
3990
6324
  publishableKey: this.config.publishableKey,
3991
6325
  apiUrl: this.config.apiUrl,
6326
+ market: this.config.market,
3992
6327
  customerToken: () => this.customer.auth.getToken(),
3993
6328
  onUnauthorized,
3994
6329
  onRequestId,
@@ -4021,6 +6356,9 @@ var Client = class {
4021
6356
  onRequestId,
4022
6357
  this.config.apiUrl
4023
6358
  );
6359
+ this.markets = new MarketDiscovery(
6360
+ (options2) => this.collections.from("markets").find(options2)
6361
+ );
4024
6362
  const membershipApi = new BrowserMembershipApi("MembershipApi", {
4025
6363
  publishableKey: this.config.publishableKey,
4026
6364
  apiUrl: this.config.apiUrl,
@@ -4029,12 +6367,23 @@ var Client = class {
4029
6367
  onRequestId
4030
6368
  });
4031
6369
  this.memberships = {
4032
- me: membershipApi.me.bind(membershipApi)
6370
+ me: membershipApi.me.bind(membershipApi),
6371
+ cancel: membershipApi.cancel.bind(membershipApi)
4033
6372
  };
4034
6373
  }
4035
6374
  getState() {
4036
6375
  return { ...this.state };
4037
6376
  }
6377
+ withMarket(market) {
6378
+ return new _Client({
6379
+ ...this.config,
6380
+ customer: this.config.customer?.persist === false ? {
6381
+ ...this.config.customer,
6382
+ token: this.customer.auth.getToken() ?? void 0
6383
+ } : this.config.customer,
6384
+ market
6385
+ });
6386
+ }
4038
6387
  getConfig() {
4039
6388
  return { ...this.config };
4040
6389
  }
@@ -4100,6 +6449,7 @@ var COMMERCE_NOTIFICATION_EVENTS = [
4100
6449
  "returnRequested",
4101
6450
  "returnApproved",
4102
6451
  "returnRejected",
6452
+ "returnCanceled",
4103
6453
  "returnCompleted"
4104
6454
  ];
4105
6455
  function isStringOrNumber(value) {
@@ -4188,7 +6538,7 @@ function isCommerceNotificationWebhookEvent(event) {
4188
6538
  if (notification.event === "fulfillmentShipped") {
4189
6539
  return sourceCollection === "fulfillments" && matchesOptionalId(data.fulfillmentId, sourceId) && typeof notification.fulfillmentId === "string" && notification.fulfillmentId.length > 0 && matchesOptionalId(notification.fulfillmentId, sourceId) && matchesOptionalId(data.fulfillmentId, notification.fulfillmentId) && matchesOptionalId(changeSourceId, notification.fulfillmentId);
4190
6540
  }
4191
- if (notification.event === "returnRequested" || notification.event === "returnApproved" || notification.event === "returnRejected" || notification.event === "returnCompleted") {
6541
+ if (notification.event === "returnRequested" || notification.event === "returnApproved" || notification.event === "returnRejected" || notification.event === "returnCanceled" || notification.event === "returnCompleted") {
4192
6542
  return sourceCollection === "returns" && matchesOptionalId(data.returnId, sourceId) && typeof notification.returnId === "string" && notification.returnId.length > 0 && matchesOptionalId(notification.returnId, sourceId) && matchesOptionalId(data.returnId, notification.returnId) && matchesOptionalId(changeSourceId, notification.returnId);
4193
6543
  }
4194
6544
  return false;
@@ -4222,8 +6572,8 @@ function createCommerceEmailWebhookHandler(handlers) {
4222
6572
  function isWebhookCollection(event, collection) {
4223
6573
  return isValidWebhookEvent(event) && event.collection === collection;
4224
6574
  }
4225
- function isWebhookOperation(event, operation) {
4226
- return isValidWebhookEvent(event) && event.operation === operation;
6575
+ function isWebhookOperation(event, operation2) {
6576
+ return isValidWebhookEvent(event) && event.operation === operation2;
4227
6577
  }
4228
6578
  var CUSTOMER_PASSWORD_RESET_OPERATION = "password-reset";
4229
6579
  function isRecord2(value) {
@@ -4250,7 +6600,7 @@ function createCustomerAuthWebhookHandler(handlers) {
4250
6600
  await handlers.unhandled?.(event);
4251
6601
  };
4252
6602
  }
4253
- async function verifySignature(payload, secret, signature, timestamp, deliveryId) {
6603
+ async function verifySignature(payload, secret, signature, timestamp2, deliveryId) {
4254
6604
  const encoder = new TextEncoder();
4255
6605
  const key = await crypto.subtle.importKey(
4256
6606
  "raw",
@@ -4269,12 +6619,12 @@ async function verifySignature(payload, secret, signature, timestamp, deliveryId
4269
6619
  "HMAC",
4270
6620
  key,
4271
6621
  sigBytes,
4272
- encoder.encode(`${timestamp}.${deliveryId}.${payload}`)
6622
+ encoder.encode(`${timestamp2}.${deliveryId}.${payload}`)
4273
6623
  );
4274
6624
  }
4275
- function timestampIsFresh(timestamp, toleranceSeconds) {
4276
- if (!/^\d+$/.test(timestamp)) return false;
4277
- const timestampMs = Number(timestamp);
6625
+ function timestampIsFresh(timestamp2, toleranceSeconds) {
6626
+ if (!/^\d+$/.test(timestamp2)) return false;
6627
+ const timestampMs = Number(timestamp2);
4278
6628
  if (!Number.isFinite(timestampMs)) return false;
4279
6629
  const skewMs = Math.abs(Date.now() - timestampMs);
4280
6630
  return skewMs <= toleranceSeconds * 1e3;
@@ -4284,14 +6634,14 @@ async function handleWebhook(request, handler, options) {
4284
6634
  const rawBody = await request.text();
4285
6635
  if (options?.secret) {
4286
6636
  const signature = request.headers.get("x-webhook-signature") || "";
4287
- const timestamp = request.headers.get("x-webhook-timestamp") || "";
6637
+ const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
4288
6638
  const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
4289
6639
  const toleranceSeconds = options.toleranceSeconds ?? 300;
4290
- const valid = Boolean(timestamp && deliveryId) && timestampIsFresh(timestamp, toleranceSeconds) && await verifySignature(
6640
+ const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(
4291
6641
  rawBody,
4292
6642
  options.secret,
4293
6643
  signature,
4294
- timestamp,
6644
+ timestamp2,
4295
6645
  deliveryId
4296
6646
  );
4297
6647
  if (!valid) {
@@ -4355,12 +6705,21 @@ var INTERNAL_COLLECTIONS = [
4355
6705
  "analytics-event-schemas",
4356
6706
  "subscriptions",
4357
6707
  "billing-history",
6708
+ "usage-rate-cards",
6709
+ "usage-invoices",
4358
6710
  "inventory-reservations",
4359
6711
  "inventory-adjustments",
6712
+ "payment-sessions",
6713
+ "payment-event-inbox",
6714
+ "payment-refund-attempts",
6715
+ "portone-payment-interactions",
4360
6716
  "commerce-notification-intents",
6717
+ "commerce-idempotency-records",
4361
6718
  "product-collection-items",
4362
6719
  "order-status-logs",
6720
+ "fulfillment-events",
4363
6721
  "tenant-commerce-config",
6722
+ "customer-oauth-clients",
4364
6723
  "api-keys",
4365
6724
  "personal-access-tokens",
4366
6725
  "tenant-entitlements",
@@ -4368,12 +6727,18 @@ var INTERNAL_COLLECTIONS = [
4368
6727
  "direct-upload-sessions",
4369
6728
  "webhook-events",
4370
6729
  "webhook-deliveries",
6730
+ "webhook-outbox-deliveries",
4371
6731
  "audit-logs",
4372
6732
  "plans",
4373
6733
  "webhooks",
6734
+ "custom-field-definitions",
4374
6735
  "event-registrations",
6736
+ "event-admission-holds",
6737
+ "event-admission-types",
4375
6738
  "customer-payment-methods",
4376
- "tenant-payment-credentials"
6739
+ "tenant-payment-credentials",
6740
+ "commerce-payment-accounts",
6741
+ "payment-provider-customer-aliases"
4377
6742
  ];
4378
6743
  var COLLECTIONS = [
4379
6744
  "tenants",
@@ -4432,6 +6797,7 @@ var COLLECTIONS = [
4432
6797
  "event-occurrences",
4433
6798
  "event-tags",
4434
6799
  "membership-plans",
6800
+ "membership-plan-prices",
4435
6801
  "customer-memberships"
4436
6802
  ];
4437
6803
  var SERVER_ONLY_COLLECTIONS = [
@@ -4440,9 +6806,14 @@ var SERVER_ONLY_COLLECTIONS = [
4440
6806
  "images",
4441
6807
  "videos",
4442
6808
  "orders",
6809
+ "order-tags",
4443
6810
  "order-items",
4444
6811
  "returns",
4445
6812
  "return-items",
6813
+ "refunds",
6814
+ "refund-line-items",
6815
+ "order-edit-sessions",
6816
+ "order-staged-changes",
4446
6817
  "fulfillment-orders",
4447
6818
  "fulfillment-order-items",
4448
6819
  "fulfillments",
@@ -4455,6 +6826,8 @@ var SERVER_ONLY_COLLECTIONS = [
4455
6826
  "cart-items",
4456
6827
  "checkouts",
4457
6828
  "checkout-items",
6829
+ "draft-orders",
6830
+ "draft-order-items",
4458
6831
  "posts",
4459
6832
  "comments",
4460
6833
  "reactions",
@@ -4850,9 +7223,9 @@ var generateOrderNumber = () => {
4850
7223
  const year = now.getFullYear().toString().slice(-2);
4851
7224
  const month = (now.getMonth() + 1).toString().padStart(2, "0");
4852
7225
  const day = now.getDate().toString().padStart(2, "0");
4853
- const array = new Uint32Array(1);
4854
- globalThis.crypto.getRandomValues(array);
4855
- const random = ((array[0] ?? 0) % 1e6).toString().padStart(6, "0");
7226
+ const array2 = new Uint32Array(1);
7227
+ globalThis.crypto.getRandomValues(array2);
7228
+ const random = ((array2[0] ?? 0) % 1e6).toString().padStart(6, "0");
4856
7229
  return `${year}${month}${day}${random}`;
4857
7230
  };
4858
7231
 
@@ -4903,7 +7276,7 @@ function createAnalytics(config) {
4903
7276
  }, destroy() {
4904
7277
  } };
4905
7278
  }
4906
- const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
7279
+ const endpoint2 = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
4907
7280
  const respectDnt = config.respectDnt !== false;
4908
7281
  function isDntActive() {
4909
7282
  if (!respectDnt) return false;
@@ -4944,10 +7317,10 @@ function createAnalytics(config) {
4944
7317
  try {
4945
7318
  if (typeof navigator.sendBeacon === "function") {
4946
7319
  const blob = new Blob([body], { type: "text/plain" });
4947
- const sent = navigator.sendBeacon(endpoint, blob);
7320
+ const sent = navigator.sendBeacon(endpoint2, blob);
4948
7321
  if (sent) return;
4949
7322
  }
4950
- fetch(endpoint, {
7323
+ fetch(endpoint2, {
4951
7324
  method: "POST",
4952
7325
  keepalive: true,
4953
7326
  headers: { "Content-Type": "application/json" },