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