@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/client.cjs CHANGED
@@ -56,10 +56,136 @@ var SDKError = class extends Error {
56
56
  details: this.details,
57
57
  userMessage: this.userMessage,
58
58
  suggestion: this.suggestion,
59
- ...this.requestId !== void 0 && { requestId: this.requestId }
59
+ ...this.requestId !== void 0 && { requestId: this.requestId },
60
+ ...this.kind !== void 0 && { kind: this.kind },
61
+ ...this.reason !== void 0 && { reason: this.reason },
62
+ ...this.rawReason !== void 0 && { rawReason: this.rawReason },
63
+ ...this.retryable !== void 0 && { retryable: this.retryable },
64
+ ...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
60
65
  };
61
66
  }
62
67
  };
68
+ var COMMERCE_ERROR_CODES = [
69
+ "validation_failed",
70
+ "unauthorized",
71
+ "forbidden",
72
+ "token_expired",
73
+ "origin_not_allowed",
74
+ "server_credentials_required",
75
+ "not_found",
76
+ "conflict",
77
+ "cart_revision_conflict",
78
+ "rate_limit_exceeded",
79
+ "usage_limit_exceeded",
80
+ "service_unavailable",
81
+ "idempotency_conflict",
82
+ "idempotency_in_progress",
83
+ "cart_not_active",
84
+ "cart_locked",
85
+ "cart_empty",
86
+ "cart_market_unavailable",
87
+ "cart_market_mismatch",
88
+ "checkout_not_open",
89
+ "payment_slot_held",
90
+ "reservation_expired",
91
+ "payment_session_not_cancelable",
92
+ "provider_identity_mismatch",
93
+ "provider_unavailable",
94
+ "lock_timeout",
95
+ "price_changed",
96
+ "pricing_fact_in_use",
97
+ "insufficient_stock",
98
+ "market_not_found",
99
+ "market_shipping_currency_unsupported",
100
+ "missing_market_rate",
101
+ "missing_shipping_amount",
102
+ "no_enabled_payment_provider",
103
+ "product_market_unavailable",
104
+ "unsupported_currency",
105
+ "missing_price_row",
106
+ "payment_provider_currency_unsupported",
107
+ "discount_code_not_found",
108
+ "discount_not_started",
109
+ "discount_expired",
110
+ "discount_usage_limit",
111
+ "discount_per_customer_limit",
112
+ "discount_customer_required",
113
+ "discount_first_order_only",
114
+ "discount_customer_not_eligible",
115
+ "discount_customer_excluded",
116
+ "discount_items_required",
117
+ "discount_product_not_eligible",
118
+ "discount_product_excluded",
119
+ "discount_min_order_amount",
120
+ "discount_currency_scope_required",
121
+ "discount_allocation_method_unsupported",
122
+ "currency_mismatch"
123
+ ];
124
+ var COMMERCE_ERROR_CODE_SET = new Set(
125
+ COMMERCE_ERROR_CODES
126
+ );
127
+ var COMMERCE_ERROR_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
128
+ "error",
129
+ "reason",
130
+ "requestId",
131
+ "retryable",
132
+ "details"
133
+ ]);
134
+ function isPlainRecord(value) {
135
+ return typeof value === "object" && value !== null && !Array.isArray(value);
136
+ }
137
+ function commerceProtocolError(issue, trustedRequestId) {
138
+ return createApiError(
139
+ "Invalid canonical commerce error response.",
140
+ 502,
141
+ { protocol: "commerce-error-envelope", issue },
142
+ "The server returned an incompatible commerce error response.",
143
+ "Verify that the Console commerce contract is deployed before using this SDK version.",
144
+ trustedRequestId
145
+ );
146
+ }
147
+ function parseCommerceErrorEnvelope(body, headerRequestId) {
148
+ if (!isPlainRecord(body)) {
149
+ throw commerceProtocolError("expected_object", headerRequestId);
150
+ }
151
+ if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {
152
+ throw commerceProtocolError("unexpected_field", headerRequestId);
153
+ }
154
+ 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)) {
155
+ throw commerceProtocolError("invalid_field", headerRequestId);
156
+ }
157
+ if (headerRequestId && headerRequestId !== body.requestId) {
158
+ throw commerceProtocolError("request_id_mismatch", headerRequestId);
159
+ }
160
+ return {
161
+ error: body.error,
162
+ reason: body.reason,
163
+ requestId: body.requestId,
164
+ retryable: body.retryable === true,
165
+ ...body.details === void 0 ? {} : { details: body.details }
166
+ };
167
+ }
168
+ function enhanceCommerceError(error, body, headerRequestId) {
169
+ const envelope = parseCommerceErrorEnvelope(body, headerRequestId);
170
+ const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason);
171
+ Object.assign(error, {
172
+ code: envelope.reason,
173
+ kind: "commerce",
174
+ reason: known ? envelope.reason : "unknown_commerce_error",
175
+ ...known ? {} : { rawReason: envelope.reason },
176
+ requestId: envelope.requestId,
177
+ retryable: envelope.retryable,
178
+ details: envelope.details
179
+ });
180
+ return error;
181
+ }
182
+ function isCommerceSDKError(error) {
183
+ if (!(error instanceof SDKError) || error.kind !== "commerce") return false;
184
+ if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
185
+ return false;
186
+ }
187
+ return error.reason === "unknown_commerce_error" ? typeof error.rawReason === "string" : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === void 0;
188
+ }
63
189
  var NetworkError = class extends SDKError {
64
190
  constructor(message, status, details, userMessage, suggestion) {
65
191
  super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
@@ -253,6 +379,7 @@ var NON_RETRYABLE_STATUSES = [400, 401, 403, 404, 409, 422];
253
379
  var SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
254
380
  var DEFAULT_MAX_RETRIES = 3;
255
381
  var STOREFRONT_BROWSER_MAX_RETRIES = 1;
382
+ var MAX_AUTOMATIC_RETRY_AFTER_SECONDS = 5 * 60;
256
383
  function debugLog(debug, type, message, data) {
257
384
  if (!debug) return;
258
385
  const shouldLog = debug === true || type === "request" && debug.logRequests || type === "response" && debug.logResponses || type === "error" && debug.logErrors;
@@ -276,6 +403,11 @@ function redactSensitiveHeaders(headers) {
276
403
  redacted["x-preview-token"]
277
404
  );
278
405
  }
406
+ if (redacted["x-custom-payment-signature"]) {
407
+ redacted["x-custom-payment-signature"] = redactSensitiveHeader(
408
+ redacted["x-custom-payment-signature"]
409
+ );
410
+ }
279
411
  return redacted;
280
412
  }
281
413
  function getErrorSuggestion(status) {
@@ -367,116 +499,129 @@ function attachRequestId(err, id) {
367
499
  }
368
500
  function parseRetryAfter(response) {
369
501
  const raw = response.headers.get("Retry-After");
370
- if (!raw) return void 0;
371
- return parseInt(raw, 10) || void 0;
502
+ if (!raw) return { permitsAutomaticRetry: true };
503
+ const trimmed = raw.trim();
504
+ let seconds;
505
+ if (/^\d+$/.test(trimmed)) {
506
+ seconds = Number(trimmed);
507
+ if (!Number.isSafeInteger(seconds)) {
508
+ return { permitsAutomaticRetry: false };
509
+ }
510
+ } else {
511
+ const retryAt = Date.parse(trimmed);
512
+ if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
513
+ seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
514
+ }
515
+ return {
516
+ seconds,
517
+ permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
518
+ };
372
519
  }
373
- function mapResponseToError(status, parsed, details, requestId, retryAfter) {
520
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
374
521
  const errorDetails = {
375
522
  ...details,
376
523
  ...parsed.errors && { errors: parsed.errors },
377
- ...parsed.body && { body: parsed.body }
524
+ ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
378
525
  };
379
526
  const suggestion = getParsedErrorSuggestion(status, parsed);
527
+ const finalize = (error) => {
528
+ const withRequestId = attachRequestId(error, requestId);
529
+ if (retryAfter !== void 0) {
530
+ Object.assign(withRequestId, { retryAfter });
531
+ }
532
+ return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
533
+ };
380
534
  if (status === 400 || status === 422) {
381
- return attachRequestId(
535
+ return finalize(
382
536
  createValidationError(
383
537
  parsed.errorMessage,
384
538
  errorDetails,
385
539
  parsed.userMessage,
386
540
  suggestion,
387
541
  status
388
- ),
389
- requestId
542
+ )
390
543
  );
391
544
  }
392
545
  if (status === 401) {
393
- return attachRequestId(
546
+ return finalize(
394
547
  createAuthError(
395
548
  parsed.errorMessage,
396
549
  errorDetails,
397
550
  parsed.userMessage,
398
551
  suggestion
399
- ),
400
- requestId
552
+ )
401
553
  );
402
554
  }
403
555
  if (status === 403) {
404
- return attachRequestId(
556
+ return finalize(
405
557
  createPermissionError(
406
558
  parsed.errorMessage,
407
559
  errorDetails,
408
560
  parsed.userMessage,
409
561
  suggestion
410
- ),
411
- requestId
562
+ )
412
563
  );
413
564
  }
414
565
  if (status === 404) {
415
- return attachRequestId(
566
+ return finalize(
416
567
  createNotFoundError(
417
568
  parsed.errorMessage,
418
569
  errorDetails,
419
570
  parsed.userMessage,
420
571
  suggestion
421
- ),
422
- requestId
572
+ )
423
573
  );
424
574
  }
425
575
  if (status === 409) {
426
- return attachRequestId(
576
+ return finalize(
427
577
  createConflictError(
428
578
  parsed.errorMessage,
429
579
  errorDetails,
430
580
  parsed.userMessage,
431
581
  suggestion
432
- ),
433
- requestId
582
+ )
434
583
  );
435
584
  }
436
585
  if (status === 410) {
437
- return attachRequestId(
586
+ return finalize(
438
587
  createGoneError(
439
588
  parsed.errorMessage,
440
589
  errorDetails,
441
590
  parsed.userMessage,
442
591
  suggestion
443
- ),
444
- requestId
592
+ )
445
593
  );
446
594
  }
447
595
  if (status === 429) {
448
- return attachRequestId(
596
+ return finalize(
449
597
  createRateLimitError(
450
598
  parsed.errorMessage,
451
599
  retryAfter,
452
600
  errorDetails,
453
601
  parsed.userMessage,
454
602
  suggestion
455
- ),
456
- requestId
603
+ )
457
604
  );
458
605
  }
459
606
  if (status === 503) {
460
- return attachRequestId(
607
+ return finalize(
461
608
  createServiceUnavailableError(
462
609
  parsed.errorMessage,
463
610
  retryAfter,
464
611
  errorDetails,
465
612
  parsed.userMessage,
466
613
  suggestion
467
- ),
468
- requestId
614
+ )
469
615
  );
470
616
  }
471
- return attachRequestId(
617
+ return finalize(
472
618
  createNetworkError(
473
619
  parsed.errorMessage,
474
620
  status,
475
621
  errorDetails,
476
622
  parsed.userMessage,
477
623
  suggestion
478
- ),
479
- requestId
624
+ )
480
625
  );
481
626
  }
482
627
  async function httpFetch(url, options) {
@@ -489,6 +634,7 @@ async function httpFetch(url, options) {
489
634
  debug,
490
635
  retry,
491
636
  onUnauthorized,
637
+ errorFamily,
492
638
  ...requestInit
493
639
  } = options || {};
494
640
  const baseUrl = resolveApiUrl(apiUrl);
@@ -541,6 +687,8 @@ async function httpFetch(url, options) {
541
687
  headers: redactSensitiveHeaders(response.headers)
542
688
  });
543
689
  if (!response.ok) {
690
+ const parsed = await parseErrorBody(response);
691
+ const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
544
692
  if (isUsageLimitExceededResponse(response)) {
545
693
  const limit = parseInt(
546
694
  response.headers.get("X-Usage-Limit") || "0",
@@ -554,7 +702,7 @@ async function httpFetch(url, options) {
554
702
  response.headers.get("X-Usage-Remaining") || "0",
555
703
  10
556
704
  );
557
- throw attachRequestId(
705
+ const usageError = attachRequestId(
558
706
  createUsageLimitError(
559
707
  `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
560
708
  { limit, current, remaining },
@@ -568,9 +716,9 @@ async function httpFetch(url, options) {
568
716
  ),
569
717
  requestId
570
718
  );
719
+ throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
571
720
  }
572
- const parsed = await parseErrorBody(response);
573
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
721
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
574
722
  hasRetried401 = true;
575
723
  try {
576
724
  const newToken = await onUnauthorized();
@@ -592,13 +740,18 @@ async function httpFetch(url, options) {
592
740
  parsed,
593
741
  details,
594
742
  requestId,
595
- retryAfter
743
+ retryAfter.seconds,
744
+ errorFamily
596
745
  );
597
746
  const method2 = (requestInit.method || "GET").toUpperCase();
598
747
  const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
599
- if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
748
+ const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
749
+ if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
600
750
  lastError = error;
601
- const retryDelay = retryConfig.retryDelay(attempt);
751
+ const retryDelay = Math.max(
752
+ retryConfig.retryDelay(attempt),
753
+ (retryAfter.seconds ?? 0) * 1e3
754
+ );
602
755
  debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
603
756
  await delay(retryDelay);
604
757
  continue;
@@ -668,87 +821,45 @@ async function httpFetch(url, options) {
668
821
  throw lastError ?? new NetworkError("Request failed after retries");
669
822
  }
670
823
 
671
- // src/core/api/endpoints.ts
672
- var COMMERCE_ENDPOINTS = {
673
- orders: {
674
- create: "/api/orders/create",
675
- update: "/api/orders/update",
676
- confirmPayment: "/api/orders/confirm-payment",
677
- byPayment: "/api/orders/by-payment",
678
- cancel: "/api/orders/cancel",
679
- resolveCancelRefund: "/api/orders/resolve-cancel-refund",
680
- checkout: "/api/orders/checkout",
681
- createFulfillment: "/api/orders/create-fulfillment",
682
- updateFulfillment: "/api/orders/update-fulfillment"
683
- },
684
- transactions: {
685
- update: "/api/transactions/update"
686
- },
687
- returns: {
688
- create: "/api/returns/create",
689
- update: "/api/returns/update",
690
- returnRefund: "/api/returns/return-refund"
691
- },
692
- fulfillmentOrders: {
693
- prepare: "/api/fulfillment-orders/prepare-fulfillment-order"
694
- },
695
- fulfillments: {
696
- bulkImport: "/api/fulfillments/bulk-import"
697
- },
698
- carts: {
699
- mine: "/api/carts/mine",
700
- merge: "/api/carts/merge",
701
- addItem: "/api/carts/add-item",
702
- updateItem: "/api/carts/update-item",
703
- removeItem: "/api/carts/remove-item",
704
- applyDiscount: "/api/carts/apply-discount",
705
- removeDiscount: "/api/carts/remove-discount",
706
- clear: "/api/carts/clear"
707
- },
708
- products: {
709
- stockCheck: "/api/products/stock-check",
710
- stockSnapshot: "/api/products/stock",
711
- listingGroups: "/api/products/listing-groups",
712
- listingGroupsCatalog: "/api/products/listing-groups/catalog",
713
- listingGroupsQuery: "/api/products/listing-groups/query",
714
- listingGroupsQueryCatalog: "/api/products/listing-groups/query/catalog",
715
- detail: "/api/products/detail",
716
- detailCatalog: "/api/products/detail/catalog",
717
- upsert: "/api/products/upsert"
718
- }
719
- };
720
- var COMMERCE_ENDPOINT_PATHS = Object.values(
721
- COMMERCE_ENDPOINTS
722
- ).flatMap((group) => Object.values(group));
723
- var MEMBERSHIP_ENDPOINTS = {
724
- subscribe: "/api/memberships/subscribe",
725
- cancel: (id) => `/api/memberships/${id}/cancel`,
726
- me: "/api/memberships/me"
727
- };
728
-
729
824
  // src/core/internal/utils/query-string.ts
730
- function productDetailQuery(params) {
731
- const search = new URLSearchParams();
732
- if ("slug" in params) {
733
- search.set("slug", params.slug);
734
- } else {
735
- search.set("id", params.id);
825
+ function normalizedMarket(value) {
826
+ const market = value?.trim();
827
+ return market || void 0;
828
+ }
829
+ function appendProductLocaleSearchParams(search, options) {
830
+ if (options?.locale) search.set("locale", options.locale);
831
+ if (options?.fallbackLocale !== void 0) {
832
+ search.set(
833
+ "fallbackLocale",
834
+ options.fallbackLocale === false ? "none" : options.fallbackLocale
835
+ );
736
836
  }
737
- return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
738
837
  }
739
- function productDetailCatalogQuery(params) {
838
+ function productDetailSearchParams(params) {
740
839
  const search = new URLSearchParams();
741
840
  if ("slug" in params) {
742
841
  search.set("slug", params.slug);
743
842
  } else {
744
843
  search.set("id", params.id);
745
844
  }
746
- return `${COMMERCE_ENDPOINTS.products.detailCatalog}?${search}`;
845
+ const market = normalizedMarket(params.market);
846
+ if (market) search.set("market", market);
847
+ appendProductLocaleSearchParams(search, params);
848
+ return search.toString();
747
849
  }
748
- function listingGroupsCatalogQuery(params) {
749
- return `${COMMERCE_ENDPOINTS.products.listingGroupsCatalog}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
850
+ function listingGroupsSearchParams(params) {
851
+ const ids = params.productIds.map(encodeURIComponent).join(",");
852
+ const search = new URLSearchParams();
853
+ const market = normalizedMarket(params.market);
854
+ if (market) search.set("market", market);
855
+ appendProductLocaleSearchParams(search, params);
856
+ const query = search.toString();
857
+ return `ids=${ids}${query ? `&${query}` : ""}`;
750
858
  }
751
859
  function appendListingGroupsQuerySearchParams(search, options) {
860
+ const market = normalizedMarket(options?.market);
861
+ if (market) search.set("market", market);
862
+ appendProductLocaleSearchParams(search, options);
752
863
  if (options?.page != null) search.set("page", String(options.page));
753
864
  if (options?.limit != null) search.set("limit", String(options.limit));
754
865
  if (options?.sort != null) {
@@ -759,20 +870,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
759
870
  search.set("whereJson", JSON.stringify(options.where));
760
871
  }
761
872
  }
762
- function listingGroupsQueryUrl(options) {
873
+ function listingPageSearchParams(options) {
763
874
  const search = new URLSearchParams();
764
875
  appendListingGroupsQuerySearchParams(search, options);
765
- const query = search.toString();
766
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
767
- }
768
- function listingGroupsQueryCatalogUrl(options) {
769
- const search = new URLSearchParams();
770
- appendListingGroupsQuerySearchParams(search, options);
771
- const query = search.toString();
772
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQueryCatalog}${query ? `?${query}` : ""}`;
876
+ return search.toString();
773
877
  }
774
- function stockSnapshotQuery(params) {
775
- return `${COMMERCE_ENDPOINTS.products.stockSnapshot}?variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
878
+ function stockSnapshotSearchParams(params) {
879
+ return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
776
880
  }
777
881
 
778
882
  // src/core/collection/http-client.ts
@@ -815,10 +919,15 @@ var HttpClient = class {
815
919
  throw err;
816
920
  }
817
921
  }
818
- buildUrl(endpoint, options) {
819
- if (!options) return endpoint;
820
- const queryString = (0, import_qs_esm.stringify)(options, { addQueryPrefix: true });
821
- return queryString ? `${endpoint}${queryString}` : endpoint;
922
+ buildUrl(endpoint2, options) {
923
+ if (!options) return endpoint2;
924
+ const { fallbackLocale, ...rest } = options;
925
+ const queryOptions = fallbackLocale === void 0 ? rest : {
926
+ ...rest,
927
+ "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
928
+ };
929
+ const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
930
+ return queryString ? `${endpoint2}${queryString}` : endpoint2;
822
931
  }
823
932
  assertJsonResponse(response) {
824
933
  const contentType = response.headers.get("content-type");
@@ -960,39 +1069,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
960
1069
  from(collection) {
961
1070
  return new ReadOnlyCollectionQueryBuilder(this, collection);
962
1071
  }
963
- async requestFind(endpoint, options) {
964
- const url = this.buildUrl(endpoint, options);
1072
+ async requestFind(endpoint2, options) {
1073
+ const url = this.buildUrl(endpoint2, options);
965
1074
  const response = await this.fetchWithTracking(url, {
966
1075
  ...this.defaultOptions,
967
1076
  method: "GET"
968
1077
  });
969
1078
  return this.parseFindResponse(response);
970
1079
  }
971
- async requestFindEndpoint(endpoint, data) {
972
- const response = await this.fetchWithTracking(endpoint, {
1080
+ async requestFindEndpoint(endpoint2, data) {
1081
+ const response = await this.fetchWithTracking(endpoint2, {
973
1082
  ...this.defaultOptions,
974
1083
  method: "POST",
975
1084
  body: data ? JSON.stringify(data) : void 0
976
1085
  });
977
1086
  return this.parseFindResponse(response);
978
1087
  }
979
- async requestFindEndpointGet(endpoint) {
980
- const response = await this.fetchWithTracking(endpoint, {
1088
+ async requestFindEndpointGet(endpoint2) {
1089
+ const response = await this.fetchWithTracking(endpoint2, {
981
1090
  ...this.defaultOptions,
982
1091
  method: "GET"
983
1092
  });
984
1093
  return this.parseFindResponse(response);
985
1094
  }
986
- async requestFindById(endpoint, options) {
987
- const url = this.buildUrl(endpoint, options);
1095
+ async requestFindById(endpoint2, options) {
1096
+ const url = this.buildUrl(endpoint2, options);
988
1097
  const response = await this.fetchWithTracking(url, {
989
1098
  ...this.defaultOptions,
990
1099
  method: "GET"
991
1100
  });
992
1101
  return this.parseDocumentResponse(response);
993
1102
  }
994
- async requestCount(endpoint, options) {
995
- const url = this.buildUrl(endpoint, options);
1103
+ async requestCount(endpoint2, options) {
1104
+ const url = this.buildUrl(endpoint2, options);
996
1105
  const response = await this.fetchWithTracking(url, {
997
1106
  ...this.defaultOptions,
998
1107
  method: "GET"
@@ -1002,53 +1111,347 @@ var ReadOnlyCollectionClient = class extends HttpClient {
1002
1111
  };
1003
1112
 
1004
1113
  // src/core/api/parse-response.ts
1005
- async function parseApiResponse(response, endpoint) {
1006
- let data;
1114
+ async function parseApiResponse(response, endpoint2, options = {}) {
1115
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
1116
+ return void 0;
1117
+ }
1118
+ let parsed;
1007
1119
  try {
1008
- data = await response.json();
1120
+ parsed = await response.json();
1009
1121
  } catch {
1010
1122
  throw createApiError(
1011
- `Invalid JSON response from ${endpoint}`,
1123
+ `Invalid JSON response from ${endpoint2}`,
1012
1124
  response.status,
1013
1125
  void 0,
1014
1126
  "Server returned an invalid response.",
1015
1127
  "Check if the API endpoint is available."
1016
1128
  );
1017
1129
  }
1130
+ if (parsed === null || typeof parsed !== "object") {
1131
+ return parsed;
1132
+ }
1133
+ const data = parsed;
1018
1134
  if (data.error) {
1019
1135
  const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1020
1136
  const reason = typeof data.reason === "string" ? data.reason : void 0;
1021
1137
  const requestId = response.headers.get("x-request-id") ?? void 0;
1022
- const retryAfterRaw = response.headers.get("Retry-After");
1023
- const retryAfter = retryAfterRaw ? parseInt(retryAfterRaw, 10) || void 0 : void 0;
1138
+ const retryAfter = parseRetryAfter(response).seconds;
1139
+ let error;
1024
1140
  if (reason === "validation_failed") {
1025
- throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
1026
- }
1027
- if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1028
- throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
1141
+ error = createValidationError(errorMessage, data, errorMessage);
1142
+ } else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1143
+ error = createAuthError(errorMessage, data, errorMessage);
1144
+ } else if (reason === "forbidden") {
1145
+ error = createPermissionError(errorMessage, data, errorMessage);
1146
+ } else if (reason === "rate_limit_exceeded") {
1147
+ error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
1148
+ } else if (reason === "not_found") {
1149
+ error = createNotFoundError(errorMessage, data, errorMessage);
1150
+ } else if (reason === "conflict") {
1151
+ error = createConflictError(errorMessage, data, errorMessage);
1152
+ } else {
1153
+ error = createApiError(
1154
+ errorMessage,
1155
+ response.status,
1156
+ data,
1157
+ errorMessage,
1158
+ "An error occurred while processing the request."
1159
+ );
1029
1160
  }
1030
- if (reason === "forbidden") {
1031
- throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1161
+ const withRequestId = attachRequestId(error, requestId);
1162
+ if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
1163
+ throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
1164
+ }
1165
+ return data;
1166
+ }
1167
+
1168
+ // ../../internal/http-contracts/src/index.ts
1169
+ var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1170
+ var operation = (collection, method, path) => Object.freeze({
1171
+ [operationBrand]: true,
1172
+ collection,
1173
+ method,
1174
+ path
1175
+ });
1176
+ var COMMERCE_ENDPOINT_OPERATIONS = {
1177
+ products: {
1178
+ detail: operation("products", "get", "/detail"),
1179
+ detailCatalog: operation("products", "get", "/detail/catalog"),
1180
+ listingGroups: operation("products", "get", "/listing-groups"),
1181
+ listingGroupsCatalog: operation(
1182
+ "products",
1183
+ "get",
1184
+ "/listing-groups/catalog"
1185
+ ),
1186
+ listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
1187
+ listingGroupsQueryGet: operation(
1188
+ "products",
1189
+ "get",
1190
+ "/listing-groups/query"
1191
+ ),
1192
+ listingGroupsQueryCatalog: operation(
1193
+ "products",
1194
+ "get",
1195
+ "/listing-groups/query/catalog"
1196
+ ),
1197
+ stockCheck: operation("products", "post", "/stock-check"),
1198
+ stockSnapshot: operation("products", "get", "/stock"),
1199
+ upsert: operation("products", "post", "/upsert")
1200
+ },
1201
+ orders: {
1202
+ create: operation("orders", "post", "/create"),
1203
+ update: operation("orders", "post", "/update"),
1204
+ confirmPayment: operation("orders", "post", "/confirm-payment"),
1205
+ byPayment: operation("orders", "get", "/by-payment"),
1206
+ cancel: operation("orders", "post", "/cancel"),
1207
+ resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1208
+ checkout: operation("orders", "post", "/checkout"),
1209
+ createFulfillment: operation("orders", "post", "/create-fulfillment"),
1210
+ updateFulfillment: operation("orders", "post", "/update-fulfillment")
1211
+ },
1212
+ checkouts: {
1213
+ detail: operation("checkouts", "post", "/detail"),
1214
+ query: operation("checkouts", "post", "/query")
1215
+ },
1216
+ transactions: {
1217
+ update: operation("transactions", "post", "/update")
1218
+ },
1219
+ returns: {
1220
+ create: operation("returns", "post", "/create"),
1221
+ update: operation("returns", "post", "/update"),
1222
+ returnRefund: operation("returns", "post", "/return-refund")
1223
+ },
1224
+ fulfillmentOrders: {
1225
+ prepare: operation(
1226
+ "fulfillment-orders",
1227
+ "post",
1228
+ "/prepare-fulfillment-order"
1229
+ )
1230
+ },
1231
+ fulfillments: {
1232
+ bulkImport: operation("fulfillments", "post", "/bulk-import")
1233
+ },
1234
+ carts: {
1235
+ create: operation("carts", "post", "/create"),
1236
+ retrieve: operation("carts", "post", "/retrieve"),
1237
+ mine: operation("carts", "post", "/mine"),
1238
+ merge: operation("carts", "post", "/merge"),
1239
+ addItem: operation("carts", "post", "/add-item"),
1240
+ updateItem: operation("carts", "post", "/update-item"),
1241
+ removeItem: operation("carts", "post", "/remove-item"),
1242
+ updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
1243
+ updateAttributes: operation("carts", "post", "/update-attributes"),
1244
+ clear: operation("carts", "post", "/clear")
1245
+ },
1246
+ paymentSessions: {
1247
+ create: operation("payment-sessions", "post", "/create"),
1248
+ retrieve: operation("payment-sessions", "post", "/retrieve"),
1249
+ cancel: operation("payment-sessions", "post", "/cancel"),
1250
+ server: {
1251
+ create: operation("payment-sessions", "post", "/server/create"),
1252
+ retrieve: operation("payment-sessions", "post", "/server/retrieve"),
1253
+ cancel: operation("payment-sessions", "post", "/server/cancel"),
1254
+ confirm: operation("payment-sessions", "post", "/server/confirm")
1255
+ },
1256
+ custom: {
1257
+ create: operation("orders", "post", "/custom-payment-sessions"),
1258
+ confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
1032
1259
  }
1033
- if (reason === "rate_limit_exceeded") {
1034
- throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1260
+ },
1261
+ shippingPolicies: {
1262
+ calculate: operation("shipping-policies", "post", "/calculate")
1263
+ },
1264
+ discounts: {
1265
+ validate: operation("discounts", "post", "/validate")
1266
+ }
1267
+ };
1268
+ var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1269
+ subscribe: operation(null, "post", "/memberships/subscribe"),
1270
+ cancel: operation(null, "post", "/memberships/:id/cancel"),
1271
+ me: operation(null, "get", "/memberships/me")
1272
+ };
1273
+ var EVENTS_ENDPOINT_OPERATIONS = {
1274
+ occurrences: {
1275
+ range: operation("event-occurrences", "get", "/range"),
1276
+ admissionAvailability: operation(
1277
+ "event-occurrences",
1278
+ "get",
1279
+ "/admission-availability"
1280
+ )
1281
+ }
1282
+ };
1283
+ function resolveOperationTemplate(descriptor) {
1284
+ return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
1285
+ }
1286
+ function resolveOperationPath(descriptor, options) {
1287
+ const path = resolveOperationTemplate(descriptor).replace(
1288
+ /:([A-Za-z][A-Za-z0-9_]*)/g,
1289
+ (_, key) => {
1290
+ const value = options?.pathParams?.[key];
1291
+ if (value === void 0) {
1292
+ throw new TypeError(`Missing path parameter: ${key}`);
1293
+ }
1294
+ return encodeURIComponent(value);
1035
1295
  }
1036
- if (reason === "not_found") {
1037
- throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1296
+ );
1297
+ const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
1298
+ if (unresolved) {
1299
+ throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
1300
+ }
1301
+ const query = options?.query?.toString().replace(/^\?/, "");
1302
+ return query ? `${path}?${query}` : path;
1303
+ }
1304
+ function resolveOperationMethod(descriptor) {
1305
+ return descriptor.method.toUpperCase();
1306
+ }
1307
+
1308
+ // src/core/api/endpoints.ts
1309
+ var endpoint = (method, path) => ({ method, path });
1310
+ var sharedEndpoint = (descriptor) => descriptor;
1311
+ function resolveOperationMethod2(descriptor) {
1312
+ return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1313
+ }
1314
+ function resolveOperationPath2(descriptor, options) {
1315
+ if ("collection" in descriptor) {
1316
+ return resolveOperationPath(descriptor, options);
1317
+ }
1318
+ const query = options?.query?.toString().replace(/^\?/, "");
1319
+ return query ? `${descriptor.path}?${query}` : descriptor.path;
1320
+ }
1321
+ var COMMERCE_ENDPOINTS = {
1322
+ products: {
1323
+ detail: endpoint("GET", "/api/products/detail"),
1324
+ detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1325
+ listingGroups: endpoint("GET", "/api/products/listing-groups"),
1326
+ listingGroupsCatalog: endpoint(
1327
+ "GET",
1328
+ "/api/products/listing-groups/catalog"
1329
+ ),
1330
+ listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1331
+ listingGroupsQueryCatalog: endpoint(
1332
+ "GET",
1333
+ "/api/products/listing-groups/query/catalog"
1334
+ ),
1335
+ stockCheck: endpoint("POST", "/api/products/stock-check"),
1336
+ stockSnapshot: endpoint("GET", "/api/products/stock"),
1337
+ upsert: endpoint("POST", "/api/products/upsert")
1338
+ },
1339
+ orders: {
1340
+ update: endpoint("POST", "/api/orders/update"),
1341
+ byPayment: endpoint("GET", "/api/orders/by-payment"),
1342
+ cancel: endpoint("POST", "/api/orders/cancel"),
1343
+ resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1344
+ createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1345
+ updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1346
+ },
1347
+ checkouts: {
1348
+ create: endpoint("POST", "/api/orders/checkout"),
1349
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1350
+ server: {
1351
+ create: endpoint("POST", "/api/orders/checkout"),
1352
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1353
+ query: endpoint("POST", "/api/checkouts/query")
1038
1354
  }
1039
- if (reason === "conflict") {
1040
- throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1355
+ },
1356
+ returns: {
1357
+ create: endpoint("POST", "/api/returns/create"),
1358
+ update: endpoint("POST", "/api/returns/update"),
1359
+ returnRefund: endpoint("POST", "/api/returns/return-refund")
1360
+ },
1361
+ fulfillmentOrders: {
1362
+ prepare: endpoint(
1363
+ "POST",
1364
+ "/api/fulfillment-orders/prepare-fulfillment-order"
1365
+ )
1366
+ },
1367
+ fulfillments: {
1368
+ bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1369
+ },
1370
+ carts: {
1371
+ create: endpoint("POST", "/api/carts/create"),
1372
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1373
+ mine: endpoint("POST", "/api/carts/mine"),
1374
+ merge: endpoint("POST", "/api/carts/merge"),
1375
+ server: {
1376
+ // Server credentials are an authorization lane, not a second Cart
1377
+ // transport. These must stay bound to the registered shared operations.
1378
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
1379
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1380
+ mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
1381
+ merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
1382
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1383
+ updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
1384
+ removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
1385
+ updateDiscountCodes: sharedEndpoint(
1386
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
1387
+ ),
1388
+ updateAttributes: sharedEndpoint(
1389
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
1390
+ ),
1391
+ clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
1392
+ },
1393
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1394
+ updateItem: endpoint("POST", "/api/carts/update-item"),
1395
+ removeItem: endpoint("POST", "/api/carts/remove-item"),
1396
+ updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
1397
+ updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
1398
+ clear: endpoint("POST", "/api/carts/clear")
1399
+ },
1400
+ paymentSessions: {
1401
+ create: endpoint("POST", "/api/payment-sessions/create"),
1402
+ retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
1403
+ cancel: endpoint("POST", "/api/payment-sessions/cancel"),
1404
+ custom: {
1405
+ create: sharedEndpoint(
1406
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.create
1407
+ ),
1408
+ confirm: sharedEndpoint(
1409
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.confirm
1410
+ )
1411
+ },
1412
+ server: {
1413
+ create: endpoint("POST", "/api/payment-sessions/server/create"),
1414
+ retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
1415
+ cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
1416
+ confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
1041
1417
  }
1042
- throw attachRequestId(
1043
- createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1044
- requestId
1045
- );
1418
+ },
1419
+ shippingPolicies: {
1420
+ calculate: endpoint("POST", "/api/shipping-policies/calculate")
1046
1421
  }
1047
- return data;
1422
+ };
1423
+ function isCommerceEndpointDescriptor(value) {
1424
+ if (!value || typeof value !== "object") return false;
1425
+ const candidate = value;
1426
+ return typeof candidate.method === "string" && typeof candidate.path === "string";
1427
+ }
1428
+ function flattenEndpointPaths(value) {
1429
+ if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1430
+ if (!value || typeof value !== "object") return [];
1431
+ return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1432
+ }
1433
+ function flattenEndpointDescriptors(value) {
1434
+ if (isCommerceEndpointDescriptor(value)) return [value];
1435
+ if (!value || typeof value !== "object") return [];
1436
+ return Object.values(value).flatMap(
1437
+ (entry) => flattenEndpointDescriptors(entry)
1438
+ );
1048
1439
  }
1440
+ var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1441
+ var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1442
+ var MEMBERSHIP_ENDPOINTS = {
1443
+ subscribe: "/api/memberships/subscribe",
1444
+ cancel: (id) => `/api/memberships/${id}/cancel`,
1445
+ me: "/api/memberships/me"
1446
+ };
1447
+ var MEMBERSHIP_ENDPOINT_PATHS = [
1448
+ MEMBERSHIP_ENDPOINTS.subscribe,
1449
+ MEMBERSHIP_ENDPOINTS.cancel(":id"),
1450
+ MEMBERSHIP_ENDPOINTS.me
1451
+ ];
1049
1452
 
1050
1453
  // src/core/api/customer-scoped-api.ts
1051
- var CustomerScopedApi = class {
1454
+ var CustomerScopedTransport = class {
1052
1455
  constructor(apiName, options) {
1053
1456
  if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
1054
1457
  throw createConfigError(
@@ -1066,10 +1469,10 @@ var CustomerScopedApi = class {
1066
1469
  this.onUnauthorized = options.onUnauthorized;
1067
1470
  this.onRequestId = options.onRequestId;
1068
1471
  }
1069
- async request(endpoint, options) {
1472
+ async request(endpoint2, options) {
1070
1473
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1071
1474
  try {
1072
- const response = await httpFetch(endpoint, {
1475
+ const response = await httpFetch(endpoint2, {
1073
1476
  method: options.method,
1074
1477
  apiUrl: this.apiUrl,
1075
1478
  publishableKey: this.publishableKey,
@@ -1079,10 +1482,13 @@ var CustomerScopedApi = class {
1079
1482
  ...options.body !== void 0 && {
1080
1483
  body: JSON.stringify(options.body)
1081
1484
  },
1082
- ...options.headers && { headers: options.headers }
1485
+ ...options.headers && { headers: options.headers },
1486
+ ...options.errorFamily && { errorFamily: options.errorFamily }
1083
1487
  });
1084
1488
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1085
- return parseApiResponse(response, endpoint);
1489
+ return parseApiResponse(response, endpoint2, {
1490
+ errorFamily: options.errorFamily
1491
+ });
1086
1492
  } catch (err) {
1087
1493
  const id = err instanceof SDKError ? err.requestId ?? null : null;
1088
1494
  this.onRequestId?.(id);
@@ -1090,6 +1496,26 @@ var CustomerScopedApi = class {
1090
1496
  }
1091
1497
  }
1092
1498
  };
1499
+ var CustomerScopedApi = class {
1500
+ constructor(apiName, options) {
1501
+ this.transport = new CustomerScopedTransport(apiName, options);
1502
+ }
1503
+ requestEndpoint(endpoint2, body, options) {
1504
+ return this.transport.request(resolveOperationPath2(endpoint2, options), {
1505
+ method: resolveOperationMethod2(endpoint2),
1506
+ body,
1507
+ headers: options?.headers
1508
+ });
1509
+ }
1510
+ };
1511
+ var RawCustomerScopedApi = class {
1512
+ constructor(apiName, options) {
1513
+ this.transport = new CustomerScopedTransport(apiName, options);
1514
+ }
1515
+ request(endpoint2, options) {
1516
+ return this.transport.request(endpoint2, options);
1517
+ }
1518
+ };
1093
1519
 
1094
1520
  // src/core/community/community-client.ts
1095
1521
  var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
@@ -1100,7 +1526,7 @@ function unwrapPayloadDoc(value) {
1100
1526
  }
1101
1527
  return value;
1102
1528
  }
1103
- var CommunityClient = class extends CustomerScopedApi {
1529
+ var CommunityClient = class extends RawCustomerScopedApi {
1104
1530
  constructor(options) {
1105
1531
  super("CommunityClient", { ...options, requiresCredential: false });
1106
1532
  }
@@ -1144,11 +1570,11 @@ var CommunityClient = class extends CustomerScopedApi {
1144
1570
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1145
1571
  return `/api/comments/public?${urlParams.toString()}`;
1146
1572
  }
1147
- async execute(endpoint, method, body) {
1148
- return this.request(endpoint, { method, body });
1573
+ async execute(endpoint2, method, body) {
1574
+ return this.request(endpoint2, { method, body });
1149
1575
  }
1150
- async executeDoc(endpoint, method, body) {
1151
- const response = await this.execute(endpoint, method, body);
1576
+ async executeDoc(endpoint2, method, body) {
1577
+ const response = await this.execute(endpoint2, method, body);
1152
1578
  return unwrapPayloadDoc(response);
1153
1579
  }
1154
1580
  createPost(params) {
@@ -1384,56 +1810,1538 @@ var CommunityClient = class extends CustomerScopedApi {
1384
1810
  body
1385
1811
  );
1386
1812
  }
1387
- };
1388
-
1389
- // src/core/content/content-client.ts
1390
- var PublicContentApi = class extends CustomerScopedApi {
1391
- get(endpoint) {
1392
- return this.request(endpoint, { method: "GET" });
1393
- }
1394
- };
1395
- function appendCommonParams(search, options, defaultSort) {
1396
- search.set("sort", options?.sort ?? defaultSort);
1397
- if (options?.page != null) search.set("page", String(options.page));
1398
- if (options?.limit != null) search.set("limit", String(options.limit));
1399
- }
1400
- function linksListPath(options) {
1401
- const search = new URLSearchParams();
1402
- appendCommonParams(search, options, "-publishedAt,-createdAt");
1403
- if (options?.categoryId) search.set("categoryId", options.categoryId);
1404
- if (options?.categorySlug) {
1405
- search.set("categorySlug", options.categorySlug);
1406
- }
1407
- if (options?.tagId) search.set("tagId", options.tagId);
1408
- if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
1409
- if (options?.featured != null) search.set("featured", String(options.featured));
1410
- return `/api/links/storefront?${search}`;
1411
- }
1412
- function galleryItemsListPath(options) {
1413
- const search = new URLSearchParams();
1414
- appendCommonParams(search, options, "manual");
1415
- if (options?.galleryId) search.set("galleryId", options.galleryId);
1416
- if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
1417
- return `/api/gallery-items/storefront?${search}`;
1813
+ };
1814
+
1815
+ // src/core/content/content-client.ts
1816
+ var PublicContentApi = class extends RawCustomerScopedApi {
1817
+ get(endpoint2) {
1818
+ return this.request(endpoint2, { method: "GET" });
1819
+ }
1820
+ };
1821
+ function appendCommonParams(search, options, defaultSort) {
1822
+ search.set("sort", options?.sort ?? defaultSort);
1823
+ if (options?.page != null) search.set("page", String(options.page));
1824
+ if (options?.limit != null) search.set("limit", String(options.limit));
1825
+ }
1826
+ function linksListPath(options) {
1827
+ const search = new URLSearchParams();
1828
+ appendCommonParams(search, options, "-publishedAt,-createdAt");
1829
+ if (options?.categoryId) search.set("categoryId", options.categoryId);
1830
+ if (options?.categorySlug) {
1831
+ search.set("categorySlug", options.categorySlug);
1832
+ }
1833
+ if (options?.tagId) search.set("tagId", options.tagId);
1834
+ if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
1835
+ if (options?.featured != null)
1836
+ search.set("featured", String(options.featured));
1837
+ return `/api/links/storefront?${search}`;
1838
+ }
1839
+ function galleryItemsListPath(options) {
1840
+ const search = new URLSearchParams();
1841
+ appendCommonParams(search, options, "manual");
1842
+ if (options?.galleryId) search.set("galleryId", options.galleryId);
1843
+ if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
1844
+ return `/api/gallery-items/storefront?${search}`;
1845
+ }
1846
+ var ContentClient = class {
1847
+ constructor(options) {
1848
+ const api = new PublicContentApi("ContentClient", {
1849
+ publishableKey: options.publishableKey,
1850
+ apiUrl: options.apiUrl,
1851
+ onRequestId: options.onRequestId,
1852
+ requiresCredential: false
1853
+ });
1854
+ this.links = {
1855
+ list: (params) => api.get(linksListPath(params))
1856
+ };
1857
+ this.galleryItems = {
1858
+ list: (params) => api.get(
1859
+ galleryItemsListPath(params)
1860
+ )
1861
+ };
1862
+ }
1863
+ };
1864
+
1865
+ // src/core/api/canonical-response.ts
1866
+ var CART_STATUSES = ["active", "completed", "abandoned"];
1867
+ var MAX_CART_LINE_QUANTITY = 99;
1868
+ var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
1869
+ var MAX_COMMERCE_ADDRESS_LENGTH = 500;
1870
+ var MAX_COMMERCE_EMAIL_LENGTH = 254;
1871
+ var MAX_COMMERCE_PHONE_LENGTH = 32;
1872
+ var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
1873
+ var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
1874
+ var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
1875
+ var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
1876
+ var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
1877
+ var ORDER_FINANCIAL_STATUSES = [
1878
+ "pending",
1879
+ "authorized",
1880
+ "expired",
1881
+ "partially_paid",
1882
+ "paid",
1883
+ "canceled",
1884
+ "partially_refunded",
1885
+ "refunded",
1886
+ "reconciliation_required"
1887
+ ];
1888
+ var ORDER_FULFILLMENT_STATUSES = [
1889
+ "unfulfilled",
1890
+ "in_progress",
1891
+ "on_hold",
1892
+ "partially_fulfilled",
1893
+ "shipped",
1894
+ "fulfilled",
1895
+ "canceled"
1896
+ ];
1897
+ var ORDER_RETURN_STATUSES = [
1898
+ "no_return",
1899
+ "return_requested",
1900
+ "in_progress",
1901
+ "returned"
1902
+ ];
1903
+ var ORDER_CONFIRMATION_STATUSES = ["unconfirmed", "confirmed"];
1904
+ var ORDER_PRIMARY_DISPLAY_STATUSES = [
1905
+ "pending",
1906
+ "paid",
1907
+ "canceled",
1908
+ "refunded",
1909
+ "preparing",
1910
+ "shipped",
1911
+ "delivered",
1912
+ "confirmed"
1913
+ ];
1914
+ var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
1915
+ var ABANDONED_REASONS = ["expired", "customer", "operator"];
1916
+ var PAYMENT_PROVIDERS = ["toss"];
1917
+ var PAYMENT_PROVIDER_STATUSES = [
1918
+ "requires_payment_method",
1919
+ "requires_action",
1920
+ "requires_confirmation",
1921
+ "initializing",
1922
+ "processing",
1923
+ "authorized",
1924
+ "canceling",
1925
+ "unknown",
1926
+ "captured",
1927
+ "failed",
1928
+ "canceled"
1929
+ ];
1930
+ var PAYMENT_FAILURE_REASONS = [
1931
+ "payment_declined",
1932
+ "authentication_failed",
1933
+ "authorization_expired",
1934
+ "payment_method_unavailable",
1935
+ "provider_terminal_failure",
1936
+ "unknown_provider_terminal_failure"
1937
+ ];
1938
+ var CART_WARNING_CODES = [
1939
+ "DISCOUNT_CODE_NOT_HONOURED",
1940
+ "DISCOUNT_CURRENTLY_INACTIVE",
1941
+ "DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
1942
+ "DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
1943
+ "DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
1944
+ "DISCOUNT_NO_ENTITLED_LINE_ITEMS",
1945
+ "DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
1946
+ "DISCOUNT_NOT_FOUND",
1947
+ "DISCOUNT_PURCHASE_NOT_IN_RANGE",
1948
+ "DISCOUNT_USAGE_LIMIT_REACHED",
1949
+ "MERCHANDISE_NOT_ENOUGH_STOCK",
1950
+ "MERCHANDISE_OUT_OF_STOCK"
1951
+ ];
1952
+ function invalidCanonicalResponse(resource, details) {
1953
+ throw createApiError(
1954
+ `Invalid canonical ${resource} response.`,
1955
+ 502,
1956
+ { resource, ...details },
1957
+ `The server returned an incompatible ${resource} response.`,
1958
+ "Verify that the Console commerce contract is deployed before using this SDK version."
1959
+ );
1960
+ }
1961
+ function fail(resource, path, expected) {
1962
+ invalidCanonicalResponse(resource, { path, expected });
1963
+ }
1964
+ function record(value, resource, path) {
1965
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1966
+ fail(resource, path, "object");
1967
+ }
1968
+ return value;
1969
+ }
1970
+ function exact(value, required, optional, resource, path) {
1971
+ for (const key of required) {
1972
+ if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
1973
+ }
1974
+ const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
1975
+ const unexpected = Object.keys(value).find((key) => !allowed.has(key));
1976
+ if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
1977
+ }
1978
+ function string(value, resource, path) {
1979
+ if (typeof value !== "string" || value.length === 0) {
1980
+ fail(resource, path, "non-empty string");
1981
+ }
1982
+ return value;
1983
+ }
1984
+ function boundedString(value, maxLength, resource, path, allowEmpty = false) {
1985
+ if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
1986
+ fail(
1987
+ resource,
1988
+ path,
1989
+ `${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
1990
+ );
1991
+ }
1992
+ return value;
1993
+ }
1994
+ function nullableString(value, resource, path) {
1995
+ if (value !== null && typeof value !== "string") {
1996
+ fail(resource, path, "string or null");
1997
+ }
1998
+ }
1999
+ function cartLineQuantity(value, resource, path) {
2000
+ const quantity = positiveInteger(value, resource, path);
2001
+ if (quantity > MAX_CART_LINE_QUANTITY) {
2002
+ fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
2003
+ }
2004
+ return quantity;
2005
+ }
2006
+ function boolean(value, resource, path) {
2007
+ if (typeof value !== "boolean") fail(resource, path, "boolean");
2008
+ }
2009
+ function safeMinor(value, resource, path) {
2010
+ if (!Number.isSafeInteger(value) || value < 0) {
2011
+ fail(resource, path, "non-negative safe integer");
2012
+ }
2013
+ return value;
2014
+ }
2015
+ function positiveInteger(value, resource, path) {
2016
+ if (!Number.isSafeInteger(value) || value <= 0) {
2017
+ fail(resource, path, "positive safe integer");
2018
+ }
2019
+ return value;
2020
+ }
2021
+ function enumValue(value, values, resource, path) {
2022
+ if (typeof value !== "string" || !values.includes(value)) {
2023
+ fail(resource, path, values.join(" | "));
2024
+ }
2025
+ return value;
2026
+ }
2027
+ function timestamp(value, resource, path) {
2028
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
2029
+ fail(resource, path, "ISO 8601 timestamp with offset");
2030
+ }
2031
+ }
2032
+ function currency(value, resource, path) {
2033
+ if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
2034
+ fail(resource, path, "three-letter uppercase currency code");
2035
+ }
2036
+ }
2037
+ function array(value, resource, path) {
2038
+ if (!Array.isArray(value)) fail(resource, path, "array");
2039
+ return value;
2040
+ }
2041
+ function optionalNullableNumber(value, resource, path) {
2042
+ if (value !== void 0 && value !== null && typeof value !== "number") {
2043
+ fail(resource, path, "number or null");
2044
+ }
2045
+ }
2046
+ function validateMediaSize(value, resource, path) {
2047
+ const item = record(value, resource, path);
2048
+ exact(
2049
+ item,
2050
+ [],
2051
+ ["width", "height", "mimeType", "filename", "url"],
2052
+ resource,
2053
+ path
2054
+ );
2055
+ optionalNullableNumber(item.width, resource, `${path}.width`);
2056
+ optionalNullableNumber(item.height, resource, `${path}.height`);
2057
+ for (const key of ["mimeType", "filename", "url"]) {
2058
+ if (item[key] !== void 0)
2059
+ nullableString(item[key], resource, `${path}.${key}`);
2060
+ }
2061
+ }
2062
+ function validateMedia(value, resource, path) {
2063
+ if (typeof value === "string") return;
2064
+ const media = record(value, resource, path);
2065
+ exact(
2066
+ media,
2067
+ [],
2068
+ ["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
2069
+ resource,
2070
+ path
2071
+ );
2072
+ if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
2073
+ fail(resource, `${path}.id`, "string, number, or null");
2074
+ }
2075
+ for (const key of ["alt", "mimeType", "filename", "url"]) {
2076
+ if (media[key] !== void 0)
2077
+ nullableString(media[key], resource, `${path}.${key}`);
2078
+ }
2079
+ optionalNullableNumber(media.width, resource, `${path}.width`);
2080
+ optionalNullableNumber(media.height, resource, `${path}.height`);
2081
+ if (media.sizes !== void 0) {
2082
+ const sizes = record(media.sizes, resource, `${path}.sizes`);
2083
+ Object.entries(sizes).forEach(
2084
+ ([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
2085
+ );
2086
+ }
2087
+ }
2088
+ function validateReference(value, resource, path) {
2089
+ const ref = record(value, resource, path);
2090
+ exact(ref, ["id", "title", "handle", "image"], [], resource, path);
2091
+ string(ref.id, resource, `${path}.id`);
2092
+ string(ref.title, resource, `${path}.title`);
2093
+ if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
2094
+ if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
2095
+ }
2096
+ function validateAdmission(value, resource, path) {
2097
+ const admission = record(value, resource, path);
2098
+ exact(
2099
+ admission,
2100
+ ["eventId", "occurrenceId", "admissionTypeId"],
2101
+ [],
2102
+ resource,
2103
+ path
2104
+ );
2105
+ string(admission.eventId, resource, `${path}.eventId`);
2106
+ string(admission.occurrenceId, resource, `${path}.occurrenceId`);
2107
+ string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
2108
+ }
2109
+ function compareAdmissions(left, right) {
2110
+ for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
2111
+ if (left[field] < right[field]) return -1;
2112
+ if (left[field] > right[field]) return 1;
2113
+ }
2114
+ return 0;
2115
+ }
2116
+ function validateAdmissions(value, resource, path) {
2117
+ const admissions = array(value, resource, path);
2118
+ if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
2119
+ let prior;
2120
+ admissions.forEach((admission, index) => {
2121
+ validateAdmission(admission, resource, `${path}[${index}]`);
2122
+ const item = admission;
2123
+ const comparison = prior ? compareAdmissions(item, prior) : void 0;
2124
+ if (comparison !== void 0 && comparison <= 0) {
2125
+ fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
2126
+ }
2127
+ prior = item;
2128
+ });
2129
+ }
2130
+ function validateAttributes(value, resource, path) {
2131
+ const attributes = array(value, resource, path);
2132
+ if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
2133
+ const keys = /* @__PURE__ */ new Set();
2134
+ attributes.forEach((value2, index) => {
2135
+ const itemPath = `${path}[${index}]`;
2136
+ const attribute = record(value2, resource, itemPath);
2137
+ exact(attribute, ["key", "value"], [], resource, itemPath);
2138
+ const key = string(attribute.key, resource, `${itemPath}.key`);
2139
+ if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
2140
+ fail(
2141
+ resource,
2142
+ `${itemPath}.key`,
2143
+ "unique, non-reserved key of at most 40 characters"
2144
+ );
2145
+ }
2146
+ keys.add(key);
2147
+ if (typeof attribute.value !== "string" || attribute.value.length > 500) {
2148
+ fail(resource, `${itemPath}.value`, "string of at most 500 characters");
2149
+ }
2150
+ });
2151
+ }
2152
+ function validateCustomer(value, resource, path) {
2153
+ const customer = record(value, resource, path);
2154
+ exact(customer, ["email"], ["name", "phone"], resource, path);
2155
+ const email = boundedString(
2156
+ customer.email,
2157
+ MAX_COMMERCE_EMAIL_LENGTH,
2158
+ resource,
2159
+ `${path}.email`
2160
+ );
2161
+ if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
2162
+ email
2163
+ )) {
2164
+ fail(resource, `${path}.email`, "email address");
2165
+ }
2166
+ if (customer.name !== void 0)
2167
+ boundedString(
2168
+ customer.name,
2169
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2170
+ resource,
2171
+ `${path}.name`
2172
+ );
2173
+ if (customer.phone !== void 0)
2174
+ boundedString(
2175
+ customer.phone,
2176
+ MAX_COMMERCE_PHONE_LENGTH,
2177
+ resource,
2178
+ `${path}.phone`
2179
+ );
2180
+ }
2181
+ function validateShippingAddress(value, resource, path) {
2182
+ const address = record(value, resource, path);
2183
+ exact(
2184
+ address,
2185
+ ["recipientName", "phone", "postalCode", "address", "detailAddress"],
2186
+ ["countryCode", "regionCode", "deliveryMessage"],
2187
+ resource,
2188
+ path
2189
+ );
2190
+ boundedString(
2191
+ address.recipientName,
2192
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2193
+ resource,
2194
+ `${path}.recipientName`
2195
+ );
2196
+ boundedString(
2197
+ address.phone,
2198
+ MAX_COMMERCE_PHONE_LENGTH,
2199
+ resource,
2200
+ `${path}.phone`
2201
+ );
2202
+ boundedString(
2203
+ address.postalCode,
2204
+ MAX_COMMERCE_POSTAL_CODE_LENGTH,
2205
+ resource,
2206
+ `${path}.postalCode`
2207
+ );
2208
+ for (const key of ["address", "detailAddress"]) {
2209
+ boundedString(
2210
+ address[key],
2211
+ MAX_COMMERCE_ADDRESS_LENGTH,
2212
+ resource,
2213
+ `${path}.${key}`
2214
+ );
2215
+ }
2216
+ if (address.countryCode !== void 0) {
2217
+ if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
2218
+ fail(resource, `${path}.countryCode`, "two-letter country code");
2219
+ }
2220
+ }
2221
+ if (address.regionCode !== void 0) {
2222
+ if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
2223
+ fail(
2224
+ resource,
2225
+ `${path}.regionCode`,
2226
+ "trimmed string of at most 64 characters"
2227
+ );
2228
+ }
2229
+ }
2230
+ if (address.deliveryMessage !== void 0) {
2231
+ boundedString(
2232
+ address.deliveryMessage,
2233
+ MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
2234
+ resource,
2235
+ `${path}.deliveryMessage`,
2236
+ true
2237
+ );
2238
+ }
2239
+ }
2240
+ function validateOrderReference(value, resource, path) {
2241
+ const order = record(value, resource, path);
2242
+ exact(order, ["id", "orderNumber"], [], resource, path);
2243
+ string(order.id, resource, `${path}.id`);
2244
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2245
+ }
2246
+ function validateIntegrationMetadata(value, resource, path) {
2247
+ const metadata = record(value, resource, path);
2248
+ if (Object.keys(metadata).length > 50)
2249
+ fail(resource, path, "at most 50 entries");
2250
+ Object.entries(metadata).forEach(([key, entry]) => {
2251
+ if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
2252
+ fail(resource, `${path}.${key}`, "valid metadata key");
2253
+ }
2254
+ if (typeof entry !== "string" || entry.length > 500) {
2255
+ fail(resource, `${path}.${key}`, "string of at most 500 characters");
2256
+ }
2257
+ });
2258
+ }
2259
+ function validateCartItem(value, resource, path) {
2260
+ const item = record(value, resource, path);
2261
+ exact(
2262
+ item,
2263
+ [
2264
+ "id",
2265
+ "product",
2266
+ "variant",
2267
+ "admissions",
2268
+ "quantity",
2269
+ "unitPriceMinor",
2270
+ "discountMinor",
2271
+ "estimatedLineTotalMinor",
2272
+ "requiresShipping"
2273
+ ],
2274
+ [],
2275
+ resource,
2276
+ path
2277
+ );
2278
+ string(item.id, resource, `${path}.id`);
2279
+ validateReference(item.product, resource, `${path}.product`);
2280
+ validateReference(item.variant, resource, `${path}.variant`);
2281
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2282
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2283
+ const unitPrice = safeMinor(
2284
+ item.unitPriceMinor,
2285
+ resource,
2286
+ `${path}.unitPriceMinor`
2287
+ );
2288
+ const discount = safeMinor(
2289
+ item.discountMinor,
2290
+ resource,
2291
+ `${path}.discountMinor`
2292
+ );
2293
+ const estimatedLineTotal = safeMinor(
2294
+ item.estimatedLineTotalMinor,
2295
+ resource,
2296
+ `${path}.estimatedLineTotalMinor`
2297
+ );
2298
+ const quantity = item.quantity;
2299
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2300
+ if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
2301
+ fail(
2302
+ resource,
2303
+ `${path}.estimatedLineTotalMinor`,
2304
+ "unitPriceMinor * quantity - discountMinor"
2305
+ );
2306
+ }
2307
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2308
+ }
2309
+ function validatePublicCart(value, resource = "Cart") {
2310
+ const cart = record(value, resource, "$");
2311
+ exact(
2312
+ cart,
2313
+ [
2314
+ "id",
2315
+ "status",
2316
+ "revision",
2317
+ "currency",
2318
+ "market",
2319
+ "subtotalMinor",
2320
+ "discountMinor",
2321
+ "estimatedTotalMinor",
2322
+ "discountCodes",
2323
+ "attributes",
2324
+ "items",
2325
+ "expiresAt",
2326
+ "createdAt",
2327
+ "updatedAt"
2328
+ ],
2329
+ [],
2330
+ resource,
2331
+ "$"
2332
+ );
2333
+ string(cart.id, resource, "$.id");
2334
+ enumValue(cart.status, CART_STATUSES, resource, "$.status");
2335
+ safeMinor(cart.revision, resource, "$.revision");
2336
+ currency(cart.currency, resource, "$.currency");
2337
+ const market = record(cart.market, resource, "$.market");
2338
+ exact(market, ["id", "handle", "name"], [], resource, "$.market");
2339
+ for (const key of ["id", "handle", "name"])
2340
+ string(market[key], resource, `$.market.${key}`);
2341
+ const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
2342
+ const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
2343
+ const estimatedTotal = safeMinor(
2344
+ cart.estimatedTotalMinor,
2345
+ resource,
2346
+ "$.estimatedTotalMinor"
2347
+ );
2348
+ array(cart.discountCodes, resource, "$.discountCodes").forEach(
2349
+ (value2, index) => {
2350
+ const itemPath = `$.discountCodes[${index}]`;
2351
+ const code = record(value2, resource, itemPath);
2352
+ exact(code, ["code", "applicable"], [], resource, itemPath);
2353
+ boundedString(
2354
+ code.code,
2355
+ MAX_CART_DISCOUNT_CODE_LENGTH,
2356
+ resource,
2357
+ `${itemPath}.code`
2358
+ );
2359
+ boolean(code.applicable, resource, `${itemPath}.applicable`);
2360
+ }
2361
+ );
2362
+ validateAttributes(cart.attributes, resource, "$.attributes");
2363
+ const items = array(cart.items, resource, "$.items");
2364
+ items.forEach(
2365
+ (item, index) => validateCartItem(item, resource, `$.items[${index}]`)
2366
+ );
2367
+ const expectedSubtotal = items.reduce((total, value2) => {
2368
+ const item = value2;
2369
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2370
+ }, 0n);
2371
+ const expectedDiscount = items.reduce((total, value2) => {
2372
+ const item = value2;
2373
+ return total + BigInt(item.discountMinor);
2374
+ }, 0n);
2375
+ if (BigInt(subtotal) !== expectedSubtotal) {
2376
+ fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
2377
+ }
2378
+ if (BigInt(discount) !== expectedDiscount) {
2379
+ fail(resource, "$.discountMinor", "sum of cart line discounts");
2380
+ }
2381
+ if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
2382
+ fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
2383
+ }
2384
+ timestamp(cart.expiresAt, resource, "$.expiresAt");
2385
+ timestamp(cart.createdAt, resource, "$.createdAt");
2386
+ timestamp(cart.updatedAt, resource, "$.updatedAt");
2387
+ return value;
2388
+ }
2389
+ function validateWarnings(value, resource, path) {
2390
+ array(value, resource, path).forEach((value2, index) => {
2391
+ const itemPath = `${path}[${index}]`;
2392
+ const warning = record(value2, resource, itemPath);
2393
+ exact(warning, ["code", "message", "target"], [], resource, itemPath);
2394
+ enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
2395
+ string(warning.message, resource, `${itemPath}.message`);
2396
+ string(warning.target, resource, `${itemPath}.target`);
2397
+ });
2398
+ }
2399
+ function validateCartMutationResult(value) {
2400
+ const result = record(value, "Cart mutation result", "$");
2401
+ exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
2402
+ validatePublicCart(result.cart);
2403
+ validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
2404
+ return value;
2405
+ }
2406
+ function validateCreateCartResult(value) {
2407
+ const result = record(value, "Cart create result", "$");
2408
+ exact(
2409
+ result,
2410
+ ["cart", "warnings", "cartToken"],
2411
+ [],
2412
+ "Cart create result",
2413
+ "$"
2414
+ );
2415
+ const cart = record(result.cart, "Cart create result", "$.cart");
2416
+ validatePublicCart(cart);
2417
+ if (cart.revision !== 0) {
2418
+ fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
2419
+ }
2420
+ validateWarnings(result.warnings, "Cart create result", "$.warnings");
2421
+ boundedString(
2422
+ result.cartToken,
2423
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2424
+ "Cart create result",
2425
+ "$.cartToken"
2426
+ );
2427
+ return value;
2428
+ }
2429
+ function validateCartMineResult(value) {
2430
+ const result = record(value, "Cart mine result", "$");
2431
+ exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
2432
+ if (result.cart === null || result.cartToken === null) {
2433
+ if (result.cart !== null || result.cartToken !== null) {
2434
+ fail("Cart mine result", "$", "cart and cartToken must both be null");
2435
+ }
2436
+ } else {
2437
+ validatePublicCart(result.cart);
2438
+ boundedString(
2439
+ result.cartToken,
2440
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2441
+ "Cart mine result",
2442
+ "$.cartToken"
2443
+ );
2444
+ }
2445
+ return value;
2446
+ }
2447
+ function validateCartMergeResult(value) {
2448
+ const result = record(value, "Cart merge result", "$");
2449
+ exact(
2450
+ result,
2451
+ ["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
2452
+ [],
2453
+ "Cart merge result",
2454
+ "$"
2455
+ );
2456
+ validatePublicCart(result.cart);
2457
+ validateWarnings(result.warnings, "Cart merge result", "$.warnings");
2458
+ boundedString(
2459
+ result.cartToken,
2460
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2461
+ "Cart merge result",
2462
+ "$.cartToken"
2463
+ );
2464
+ const resolution = enumValue(
2465
+ result.resolution,
2466
+ ["unchanged", "claimed", "merged"],
2467
+ "Cart merge result",
2468
+ "$.resolution"
2469
+ );
2470
+ boolean(result.merged, "Cart merge result", "$.merged");
2471
+ boolean(result.claimed, "Cart merge result", "$.claimed");
2472
+ const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
2473
+ if (result.merged !== expected[0] || result.claimed !== expected[1]) {
2474
+ fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
2475
+ }
2476
+ return value;
2477
+ }
2478
+ function validatePublicOrderItem(value, resource, path) {
2479
+ const item = record(value, resource, path);
2480
+ exact(
2481
+ item,
2482
+ [
2483
+ "id",
2484
+ "product",
2485
+ "variant",
2486
+ "productTitle",
2487
+ "variantTitle",
2488
+ "sku",
2489
+ "admissions",
2490
+ "quantity",
2491
+ "unitPriceMinor",
2492
+ "discountMinor",
2493
+ "lineTotalMinor",
2494
+ "requiresShipping"
2495
+ ],
2496
+ [],
2497
+ resource,
2498
+ path
2499
+ );
2500
+ string(item.id, resource, `${path}.id`);
2501
+ if (item.product !== null) {
2502
+ validateReference(item.product, resource, `${path}.product`);
2503
+ }
2504
+ if (item.variant !== null) {
2505
+ validateReference(item.variant, resource, `${path}.variant`);
2506
+ }
2507
+ string(item.productTitle, resource, `${path}.productTitle`);
2508
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2509
+ nullableString(item.sku, resource, `${path}.sku`);
2510
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2511
+ const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
2512
+ const unitPrice = safeMinor(
2513
+ item.unitPriceMinor,
2514
+ resource,
2515
+ `${path}.unitPriceMinor`
2516
+ );
2517
+ const discount = safeMinor(
2518
+ item.discountMinor,
2519
+ resource,
2520
+ `${path}.discountMinor`
2521
+ );
2522
+ const lineTotal = safeMinor(
2523
+ item.lineTotalMinor,
2524
+ resource,
2525
+ `${path}.lineTotalMinor`
2526
+ );
2527
+ const expected = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2528
+ if (expected < 0n || BigInt(lineTotal) !== expected) {
2529
+ fail(
2530
+ resource,
2531
+ `${path}.lineTotalMinor`,
2532
+ "unitPriceMinor * quantity - discountMinor"
2533
+ );
2534
+ }
2535
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2536
+ }
2537
+ function validatePublicOrderAt(value, resource, path) {
2538
+ const order = record(value, resource, path);
2539
+ exact(
2540
+ order,
2541
+ [
2542
+ "id",
2543
+ "orderNumber",
2544
+ "amounts",
2545
+ "market",
2546
+ "customerSnapshot",
2547
+ "shippingAddress",
2548
+ "attributes",
2549
+ "items",
2550
+ "financialStatus",
2551
+ "fulfillmentStatus",
2552
+ "returnStatus",
2553
+ "confirmationStatus",
2554
+ "primaryDisplayStatus",
2555
+ "placedAt",
2556
+ "createdAt",
2557
+ "updatedAt"
2558
+ ],
2559
+ [],
2560
+ resource,
2561
+ path
2562
+ );
2563
+ string(order.id, resource, `${path}.id`);
2564
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2565
+ const amounts = record(order.amounts, resource, `${path}.amounts`);
2566
+ exact(
2567
+ amounts,
2568
+ [
2569
+ "currency",
2570
+ "subtotalMinor",
2571
+ "shippingMinor",
2572
+ "discountMinor",
2573
+ "totalMinor",
2574
+ "refundedMinor",
2575
+ "currentTotalMinor"
2576
+ ],
2577
+ [],
2578
+ resource,
2579
+ `${path}.amounts`
2580
+ );
2581
+ currency(amounts.currency, resource, `${path}.amounts.currency`);
2582
+ const subtotal = safeMinor(
2583
+ amounts.subtotalMinor,
2584
+ resource,
2585
+ `${path}.amounts.subtotalMinor`
2586
+ );
2587
+ const shipping = safeMinor(
2588
+ amounts.shippingMinor,
2589
+ resource,
2590
+ `${path}.amounts.shippingMinor`
2591
+ );
2592
+ const discount = safeMinor(
2593
+ amounts.discountMinor,
2594
+ resource,
2595
+ `${path}.amounts.discountMinor`
2596
+ );
2597
+ const total = safeMinor(
2598
+ amounts.totalMinor,
2599
+ resource,
2600
+ `${path}.amounts.totalMinor`
2601
+ );
2602
+ const refunded = safeMinor(
2603
+ amounts.refundedMinor,
2604
+ resource,
2605
+ `${path}.amounts.refundedMinor`
2606
+ );
2607
+ const current = safeMinor(
2608
+ amounts.currentTotalMinor,
2609
+ resource,
2610
+ `${path}.amounts.currentTotalMinor`
2611
+ );
2612
+ const expectedTotal = BigInt(subtotal) + BigInt(shipping) - BigInt(discount);
2613
+ if (expectedTotal < 0n || BigInt(total) !== expectedTotal) {
2614
+ fail(
2615
+ resource,
2616
+ `${path}.amounts.totalMinor`,
2617
+ "subtotalMinor + shippingMinor - discountMinor"
2618
+ );
2619
+ }
2620
+ if (BigInt(total) - BigInt(refunded) < 0n || current !== total - refunded) {
2621
+ fail(
2622
+ resource,
2623
+ `${path}.amounts.currentTotalMinor`,
2624
+ "totalMinor - refundedMinor"
2625
+ );
2626
+ }
2627
+ if (order.market !== null) {
2628
+ const market = record(order.market, resource, `${path}.market`);
2629
+ exact(market, ["id", "handle", "name"], [], resource, `${path}.market`);
2630
+ for (const key of ["id", "handle", "name"]) {
2631
+ string(market[key], resource, `${path}.market.${key}`);
2632
+ }
2633
+ }
2634
+ validateCustomer(order.customerSnapshot, resource, `${path}.customerSnapshot`);
2635
+ if (order.shippingAddress !== null) {
2636
+ validateShippingAddress(
2637
+ order.shippingAddress,
2638
+ resource,
2639
+ `${path}.shippingAddress`
2640
+ );
2641
+ }
2642
+ validateAttributes(order.attributes, resource, `${path}.attributes`);
2643
+ const items = array(order.items, resource, `${path}.items`);
2644
+ if (items.length === 0) fail(resource, `${path}.items`, "non-empty array");
2645
+ items.forEach(
2646
+ (item, index) => validatePublicOrderItem(item, resource, `${path}.items[${index}]`)
2647
+ );
2648
+ const expectedSubtotal = items.reduce((sum, value2) => {
2649
+ const item = value2;
2650
+ return sum + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2651
+ }, 0n);
2652
+ const expectedDiscount = items.reduce((sum, value2) => {
2653
+ const item = value2;
2654
+ return sum + BigInt(item.discountMinor);
2655
+ }, 0n);
2656
+ if (BigInt(subtotal) !== expectedSubtotal) {
2657
+ fail(resource, `${path}.amounts.subtotalMinor`, "sum of line subtotals");
2658
+ }
2659
+ if (BigInt(discount) !== expectedDiscount) {
2660
+ fail(resource, `${path}.amounts.discountMinor`, "sum of line discounts");
2661
+ }
2662
+ enumValue(
2663
+ order.financialStatus,
2664
+ ORDER_FINANCIAL_STATUSES,
2665
+ resource,
2666
+ `${path}.financialStatus`
2667
+ );
2668
+ enumValue(
2669
+ order.fulfillmentStatus,
2670
+ ORDER_FULFILLMENT_STATUSES,
2671
+ resource,
2672
+ `${path}.fulfillmentStatus`
2673
+ );
2674
+ enumValue(
2675
+ order.returnStatus,
2676
+ ORDER_RETURN_STATUSES,
2677
+ resource,
2678
+ `${path}.returnStatus`
2679
+ );
2680
+ enumValue(
2681
+ order.confirmationStatus,
2682
+ ORDER_CONFIRMATION_STATUSES,
2683
+ resource,
2684
+ `${path}.confirmationStatus`
2685
+ );
2686
+ enumValue(
2687
+ order.primaryDisplayStatus,
2688
+ ORDER_PRIMARY_DISPLAY_STATUSES,
2689
+ resource,
2690
+ `${path}.primaryDisplayStatus`
2691
+ );
2692
+ timestamp(order.placedAt, resource, `${path}.placedAt`);
2693
+ timestamp(order.createdAt, resource, `${path}.createdAt`);
2694
+ timestamp(order.updatedAt, resource, `${path}.updatedAt`);
2695
+ }
2696
+ function nullablePositiveInteger(value, resource, path) {
2697
+ if (value !== null) positiveInteger(value, resource, path);
2698
+ }
2699
+ function validatePublicOrderList(value) {
2700
+ const resource = "Order list";
2701
+ const result = record(value, resource, "$");
2702
+ exact(
2703
+ result,
2704
+ [
2705
+ "docs",
2706
+ "totalDocs",
2707
+ "limit",
2708
+ "totalPages",
2709
+ "page",
2710
+ "pagingCounter",
2711
+ "hasPrevPage",
2712
+ "hasNextPage",
2713
+ "prevPage",
2714
+ "nextPage"
2715
+ ],
2716
+ [],
2717
+ resource,
2718
+ "$"
2719
+ );
2720
+ array(result.docs, resource, "$.docs").forEach(
2721
+ (order, index) => validatePublicOrderAt(order, resource, `$.docs[${index}]`)
2722
+ );
2723
+ safeMinor(result.totalDocs, resource, "$.totalDocs");
2724
+ positiveInteger(result.limit, resource, "$.limit");
2725
+ safeMinor(result.totalPages, resource, "$.totalPages");
2726
+ positiveInteger(result.page, resource, "$.page");
2727
+ positiveInteger(result.pagingCounter, resource, "$.pagingCounter");
2728
+ boolean(result.hasPrevPage, resource, "$.hasPrevPage");
2729
+ boolean(result.hasNextPage, resource, "$.hasNextPage");
2730
+ nullablePositiveInteger(result.prevPage, resource, "$.prevPage");
2731
+ nullablePositiveInteger(result.nextPage, resource, "$.nextPage");
2732
+ return value;
2733
+ }
2734
+ function validateCheckoutItem(value, resource, path) {
2735
+ const item = record(value, resource, path);
2736
+ exact(
2737
+ item,
2738
+ [
2739
+ "id",
2740
+ "product",
2741
+ "variant",
2742
+ "productTitle",
2743
+ "variantTitle",
2744
+ "sku",
2745
+ "admissions",
2746
+ "quantity",
2747
+ "unitPriceMinor",
2748
+ "discountMinor",
2749
+ "lineTotalMinor",
2750
+ "requiresShipping"
2751
+ ],
2752
+ [],
2753
+ resource,
2754
+ path
2755
+ );
2756
+ string(item.id, resource, `${path}.id`);
2757
+ validateReference(item.product, resource, `${path}.product`);
2758
+ validateReference(item.variant, resource, `${path}.variant`);
2759
+ string(item.productTitle, resource, `${path}.productTitle`);
2760
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2761
+ nullableString(item.sku, resource, `${path}.sku`);
2762
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2763
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2764
+ const unitPrice = safeMinor(
2765
+ item.unitPriceMinor,
2766
+ resource,
2767
+ `${path}.unitPriceMinor`
2768
+ );
2769
+ const discount = safeMinor(
2770
+ item.discountMinor,
2771
+ resource,
2772
+ `${path}.discountMinor`
2773
+ );
2774
+ const lineTotal = safeMinor(
2775
+ item.lineTotalMinor,
2776
+ resource,
2777
+ `${path}.lineTotalMinor`
2778
+ );
2779
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
2780
+ if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
2781
+ fail(
2782
+ resource,
2783
+ `${path}.lineTotalMinor`,
2784
+ "unitPriceMinor * quantity - discountMinor"
2785
+ );
2786
+ }
2787
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2788
+ }
2789
+ function validateCheckoutAmounts(value, resource, path) {
2790
+ const amounts = record(value, resource, path);
2791
+ exact(
2792
+ amounts,
2793
+ [
2794
+ "currency",
2795
+ "subtotalMinor",
2796
+ "shippingMinor",
2797
+ "discountMinor",
2798
+ "totalMinor"
2799
+ ],
2800
+ [],
2801
+ resource,
2802
+ path
2803
+ );
2804
+ currency(amounts.currency, resource, `${path}.currency`);
2805
+ const subtotal = safeMinor(
2806
+ amounts.subtotalMinor,
2807
+ resource,
2808
+ `${path}.subtotalMinor`
2809
+ );
2810
+ const shipping = safeMinor(
2811
+ amounts.shippingMinor,
2812
+ resource,
2813
+ `${path}.shippingMinor`
2814
+ );
2815
+ const discount = safeMinor(
2816
+ amounts.discountMinor,
2817
+ resource,
2818
+ `${path}.discountMinor`
2819
+ );
2820
+ const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
2821
+ if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
2822
+ fail(
2823
+ resource,
2824
+ `${path}.totalMinor`,
2825
+ "subtotalMinor + shippingMinor - discountMinor"
2826
+ );
2827
+ }
2828
+ }
2829
+ function validatePaymentSessionReference(value, resource, path) {
2830
+ const session = record(value, resource, path);
2831
+ exact(session, ["id", "provider", "providerStatus"], [], resource, path);
2832
+ string(session.id, resource, `${path}.id`);
2833
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
2834
+ enumValue(
2835
+ session.providerStatus,
2836
+ PAYMENT_PROVIDER_STATUSES,
2837
+ resource,
2838
+ `${path}.providerStatus`
2839
+ );
2840
+ }
2841
+ function checkoutVariantKeys(status, placedVia) {
2842
+ const base = [
2843
+ "id",
2844
+ "amounts",
2845
+ "items",
2846
+ "customerSnapshot",
2847
+ "shippingAddress",
2848
+ "attributes",
2849
+ "expiresAt",
2850
+ "createdAt",
2851
+ "updatedAt",
2852
+ "status",
2853
+ "paymentState",
2854
+ "order"
2855
+ ];
2856
+ if (status === "open") return { required: base, optional: [] };
2857
+ if (status === "abandoned") {
2858
+ return {
2859
+ required: [...base, "abandonedAt", "abandonedReason"],
2860
+ optional: []
2861
+ };
2862
+ }
2863
+ return placedVia === "late_capture" ? {
2864
+ required: [
2865
+ ...base,
2866
+ "placedAt",
2867
+ "placedVia",
2868
+ "abandonedAt",
2869
+ "abandonedReason"
2870
+ ],
2871
+ optional: []
2872
+ } : { required: [...base, "placedAt"], optional: [] };
2873
+ }
2874
+ function validateCheckoutCore(value, resource, list, server) {
2875
+ const checkout = record(value, resource, "$");
2876
+ const status = enumValue(
2877
+ checkout.status,
2878
+ CHECKOUT_STATUSES,
2879
+ resource,
2880
+ "$.status"
2881
+ );
2882
+ const keys = checkoutVariantKeys(status, checkout.placedVia);
2883
+ if (list) {
2884
+ keys.required = keys.required.filter(
2885
+ (key) => !["items", "shippingAddress", "attributes"].includes(key)
2886
+ );
2887
+ keys.required.push("clientReferenceId");
2888
+ } else if (server) {
2889
+ keys.required.push("clientReferenceId", "integrationMetadata");
2890
+ }
2891
+ exact(checkout, keys.required, keys.optional, resource, "$");
2892
+ string(checkout.id, resource, "$.id");
2893
+ validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
2894
+ if (!list) {
2895
+ const items = array(checkout.items, resource, "$.items");
2896
+ if (items.length === 0) fail(resource, "$.items", "non-empty array");
2897
+ items.forEach(
2898
+ (item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
2899
+ );
2900
+ const expectedSubtotal = items.reduce((total, value2) => {
2901
+ const item = value2;
2902
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2903
+ }, 0n);
2904
+ const expectedDiscount = items.reduce((total, value2) => {
2905
+ const item = value2;
2906
+ return total + BigInt(item.discountMinor);
2907
+ }, 0n);
2908
+ const amounts = checkout.amounts;
2909
+ if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
2910
+ fail(
2911
+ resource,
2912
+ "$.amounts.subtotalMinor",
2913
+ "sum of undiscounted checkout line totals"
2914
+ );
2915
+ }
2916
+ if (BigInt(amounts.discountMinor) !== expectedDiscount) {
2917
+ fail(
2918
+ resource,
2919
+ "$.amounts.discountMinor",
2920
+ "sum of checkout line discounts"
2921
+ );
2922
+ }
2923
+ if (checkout.shippingAddress !== null) {
2924
+ validateShippingAddress(
2925
+ checkout.shippingAddress,
2926
+ resource,
2927
+ "$.shippingAddress"
2928
+ );
2929
+ }
2930
+ validateAttributes(checkout.attributes, resource, "$.attributes");
2931
+ }
2932
+ validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
2933
+ timestamp(checkout.expiresAt, resource, "$.expiresAt");
2934
+ timestamp(checkout.createdAt, resource, "$.createdAt");
2935
+ timestamp(checkout.updatedAt, resource, "$.updatedAt");
2936
+ const paymentState = record(checkout.paymentState, resource, "$.paymentState");
2937
+ exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
2938
+ if (status === "open") {
2939
+ if (paymentState.activePaymentSession !== null) {
2940
+ validatePaymentSessionReference(
2941
+ paymentState.activePaymentSession,
2942
+ resource,
2943
+ "$.paymentState.activePaymentSession"
2944
+ );
2945
+ }
2946
+ if (checkout.order !== null)
2947
+ fail(resource, "$.order", "null for open Checkout");
2948
+ } else {
2949
+ if (paymentState.activePaymentSession !== null) {
2950
+ fail(
2951
+ resource,
2952
+ "$.paymentState.activePaymentSession",
2953
+ "null for spent Checkout"
2954
+ );
2955
+ }
2956
+ if (status === "placed") {
2957
+ timestamp(checkout.placedAt, resource, "$.placedAt");
2958
+ validateOrderReference(checkout.order, resource, "$.order");
2959
+ if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
2960
+ fail(resource, "$.placedVia", "late_capture");
2961
+ }
2962
+ if (checkout.placedVia === "late_capture") {
2963
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2964
+ enumValue(
2965
+ checkout.abandonedReason,
2966
+ ABANDONED_REASONS,
2967
+ resource,
2968
+ "$.abandonedReason"
2969
+ );
2970
+ }
2971
+ } else {
2972
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2973
+ enumValue(
2974
+ checkout.abandonedReason,
2975
+ ABANDONED_REASONS,
2976
+ resource,
2977
+ "$.abandonedReason"
2978
+ );
2979
+ if (checkout.order !== null)
2980
+ fail(resource, "$.order", "null for abandoned Checkout");
2981
+ }
2982
+ }
2983
+ if (list || server) {
2984
+ if (checkout.clientReferenceId !== null) {
2985
+ boundedString(
2986
+ checkout.clientReferenceId,
2987
+ MAX_COMMERCE_RESOURCE_ID_LENGTH,
2988
+ resource,
2989
+ "$.clientReferenceId"
2990
+ );
2991
+ }
2992
+ }
2993
+ if (server)
2994
+ validateIntegrationMetadata(
2995
+ checkout.integrationMetadata,
2996
+ resource,
2997
+ "$.integrationMetadata"
2998
+ );
2999
+ }
3000
+ function validatePublicCheckout(value) {
3001
+ validateCheckoutCore(value, "Checkout", false, false);
3002
+ return value;
3003
+ }
3004
+ function validateServerCheckout(value) {
3005
+ validateCheckoutCore(value, "Server Checkout", false, true);
3006
+ return value;
3007
+ }
3008
+ function validateCreateCheckoutResult(value, server) {
3009
+ const resource = server ? "Server Checkout create result" : "Checkout create result";
3010
+ const result = record(value, resource, "$");
3011
+ exact(result, ["checkout", "checkoutToken"], [], resource, "$");
3012
+ if (server) validateServerCheckout(result.checkout);
3013
+ else validatePublicCheckout(result.checkout);
3014
+ boundedString(
3015
+ result.checkoutToken,
3016
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3017
+ resource,
3018
+ "$.checkoutToken"
3019
+ );
3020
+ return value;
3021
+ }
3022
+ function validateCheckoutQueryResult(value) {
3023
+ const result = record(value, "Checkout query result", "$");
3024
+ exact(
3025
+ result,
3026
+ ["data", "hasMore", "nextCursor"],
3027
+ [],
3028
+ "Checkout query result",
3029
+ "$"
3030
+ );
3031
+ array(result.data, "Checkout query result", "$.data").forEach(
3032
+ (item) => validateCheckoutCore(item, "Checkout list item", true, false)
3033
+ );
3034
+ boolean(result.hasMore, "Checkout query result", "$.hasMore");
3035
+ if (result.nextCursor !== null)
3036
+ boundedString(
3037
+ result.nextCursor,
3038
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3039
+ "Checkout query result",
3040
+ "$.nextCursor"
3041
+ );
3042
+ if (result.hasMore === true && result.nextCursor === null) {
3043
+ fail(
3044
+ "Checkout query result",
3045
+ "$.nextCursor",
3046
+ "non-null when hasMore is true"
3047
+ );
3048
+ }
3049
+ return value;
3050
+ }
3051
+ function validateMoney(value, resource, path) {
3052
+ const money = record(value, resource, path);
3053
+ exact(money, ["amountMinor", "currency"], [], resource, path);
3054
+ safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3055
+ currency(money.currency, resource, `${path}.currency`);
3056
+ }
3057
+ function validateCaptureEvidence(value, resource, path) {
3058
+ const evidence = record(value, resource, path);
3059
+ exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
3060
+ safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
3061
+ currency(evidence.currency, resource, `${path}.currency`);
3062
+ timestamp(evidence.observedAt, resource, `${path}.observedAt`);
3063
+ }
3064
+ function validateNoReconciliation(value, resource, path) {
3065
+ const reconciliation = record(value, resource, path);
3066
+ exact(reconciliation, ["status"], [], resource, path);
3067
+ if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
3068
+ }
3069
+ function validateRequiredReconciliation(value, allowed, resource, path) {
3070
+ const reconciliation = record(value, resource, path);
3071
+ exact(reconciliation, ["status", "reasons"], [], resource, path);
3072
+ if (reconciliation.status !== "required")
3073
+ fail(resource, `${path}.status`, "required");
3074
+ const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
3075
+ if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
3076
+ let previous = -1;
3077
+ reasons.forEach((reason, index) => {
3078
+ const current = allowed.indexOf(reason);
3079
+ if (current < 0 || current <= previous) {
3080
+ fail(
3081
+ resource,
3082
+ `${path}.reasons[${index}]`,
3083
+ "unique canonical-sorted reconciliation reason"
3084
+ );
3085
+ }
3086
+ previous = current;
3087
+ });
3088
+ }
3089
+ function validateNextAction(value, resource, path) {
3090
+ const action = record(value, resource, path);
3091
+ exact(
3092
+ action,
3093
+ [
3094
+ "type",
3095
+ "clientKey",
3096
+ "paymentMethodVariantKey",
3097
+ "agreementVariantKey",
3098
+ "providerOrderId",
3099
+ "providerCustomerKey",
3100
+ "orderName"
3101
+ ],
3102
+ ["customerName", "customerEmail"],
3103
+ resource,
3104
+ path
3105
+ );
3106
+ if (action.type !== "toss_widget")
3107
+ fail(resource, `${path}.type`, "toss_widget");
3108
+ for (const key of [
3109
+ "clientKey",
3110
+ "paymentMethodVariantKey",
3111
+ "agreementVariantKey"
3112
+ ]) {
3113
+ boundedString(action[key], 255, resource, `${path}.${key}`);
3114
+ }
3115
+ string(action.providerOrderId, resource, `${path}.providerOrderId`);
3116
+ string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
3117
+ boundedString(
3118
+ action.orderName,
3119
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3120
+ resource,
3121
+ `${path}.orderName`
3122
+ );
3123
+ if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
3124
+ fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
3125
+ }
3126
+ 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(
3127
+ action.providerCustomerKey
3128
+ )) {
3129
+ fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
3130
+ }
3131
+ if (action.customerName !== void 0)
3132
+ boundedString(
3133
+ action.customerName,
3134
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3135
+ resource,
3136
+ `${path}.customerName`
3137
+ );
3138
+ if (action.customerEmail !== void 0)
3139
+ validateCustomer({ email: action.customerEmail }, resource, path);
3140
+ }
3141
+ function validatePublicPaymentSession(value) {
3142
+ const resource = "PaymentSession";
3143
+ const session = record(value, resource, "$");
3144
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
3145
+ const status = enumValue(
3146
+ session.providerStatus,
3147
+ PAYMENT_PROVIDER_STATUSES,
3148
+ resource,
3149
+ "$.providerStatus"
3150
+ );
3151
+ const common = [
3152
+ "id",
3153
+ "money",
3154
+ "expiresAt",
3155
+ "sessionRole",
3156
+ "provider",
3157
+ "providerStatus",
3158
+ "presentationStatus",
3159
+ "finalizationStatus",
3160
+ "reconciliation",
3161
+ "order"
3162
+ ];
3163
+ const optional = [];
3164
+ if (status === "requires_payment_method" || status === "requires_action")
3165
+ optional.push("nextAction");
3166
+ else if (status === "captured") common.push("providerEvidence");
3167
+ else if (status === "failed") common.push("failure");
3168
+ else if (status === "canceled") common.push("cancellationReason");
3169
+ exact(session, common, optional, resource, "$");
3170
+ string(session.id, resource, "$.id");
3171
+ validateMoney(session.money, resource, "$.money");
3172
+ if (session.expiresAt !== null)
3173
+ timestamp(session.expiresAt, resource, "$.expiresAt");
3174
+ if (status === "requires_payment_method" || status === "requires_action") {
3175
+ if (session.sessionRole === "active") {
3176
+ if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
3177
+ fail(resource, "$", "actionable active not-ready state");
3178
+ }
3179
+ if (!("nextAction" in session))
3180
+ fail(resource, "$.nextAction", "required field");
3181
+ validateNextAction(session.nextAction, resource, "$.nextAction");
3182
+ } else if (session.sessionRole === "residual") {
3183
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3184
+ fail(resource, "$", "suppressed residual not-ready state");
3185
+ }
3186
+ if ("nextAction" in session)
3187
+ fail(resource, "$.nextAction", "absent for suppressed state");
3188
+ } else fail(resource, "$.sessionRole", "active | residual");
3189
+ validateNoReconciliation(
3190
+ session.reconciliation,
3191
+ resource,
3192
+ "$.reconciliation"
3193
+ );
3194
+ if (session.order !== null) fail(resource, "$.order", "null");
3195
+ } else if ([
3196
+ "requires_confirmation",
3197
+ "initializing",
3198
+ "processing",
3199
+ "authorized",
3200
+ "canceling"
3201
+ ].includes(status)) {
3202
+ enumValue(
3203
+ session.sessionRole,
3204
+ ["active", "residual"],
3205
+ resource,
3206
+ "$.sessionRole"
3207
+ );
3208
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3209
+ fail(resource, "$", "suppressed not-ready state");
3210
+ }
3211
+ validateNoReconciliation(
3212
+ session.reconciliation,
3213
+ resource,
3214
+ "$.reconciliation"
3215
+ );
3216
+ if (session.order !== null) fail(resource, "$.order", "null");
3217
+ } else if (status === "unknown") {
3218
+ enumValue(
3219
+ session.sessionRole,
3220
+ ["active", "residual"],
3221
+ resource,
3222
+ "$.sessionRole"
3223
+ );
3224
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3225
+ fail(resource, "$", "suppressed not-ready state");
3226
+ }
3227
+ validateRequiredReconciliation(
3228
+ session.reconciliation,
3229
+ ["provider_outcome_unknown"],
3230
+ resource,
3231
+ "$.reconciliation"
3232
+ );
3233
+ if (session.order !== null) fail(resource, "$.order", "null");
3234
+ } else if (status === "captured") {
3235
+ validateCaptureEvidence(
3236
+ session.providerEvidence,
3237
+ resource,
3238
+ "$.providerEvidence"
3239
+ );
3240
+ if (session.presentationStatus !== "suppressed")
3241
+ fail(resource, "$.presentationStatus", "suppressed");
3242
+ if (session.finalizationStatus === "pending") {
3243
+ enumValue(
3244
+ session.sessionRole,
3245
+ ["canonical_candidate", "residual"],
3246
+ resource,
3247
+ "$.sessionRole"
3248
+ );
3249
+ if (session.order !== null)
3250
+ fail(resource, "$.order", "null for pending finalization");
3251
+ const reconciliation = record(
3252
+ session.reconciliation,
3253
+ resource,
3254
+ "$.reconciliation"
3255
+ );
3256
+ if (reconciliation.status === "none")
3257
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3258
+ else
3259
+ validateRequiredReconciliation(
3260
+ reconciliation,
3261
+ [
3262
+ "local_commit_ambiguous",
3263
+ "amount_mismatch",
3264
+ "currency_mismatch",
3265
+ "excess_capture_pending_order"
3266
+ ],
3267
+ resource,
3268
+ "$.reconciliation"
3269
+ );
3270
+ } else if (session.finalizationStatus === "committed") {
3271
+ validateOrderReference(session.order, resource, "$.order");
3272
+ const reconciliation = record(
3273
+ session.reconciliation,
3274
+ resource,
3275
+ "$.reconciliation"
3276
+ );
3277
+ if (reconciliation.status === "none") {
3278
+ enumValue(
3279
+ session.sessionRole,
3280
+ ["canonical", "historical"],
3281
+ resource,
3282
+ "$.sessionRole"
3283
+ );
3284
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3285
+ } else {
3286
+ enumValue(
3287
+ session.sessionRole,
3288
+ ["canonical", "residual"],
3289
+ resource,
3290
+ "$.sessionRole"
3291
+ );
3292
+ validateRequiredReconciliation(
3293
+ reconciliation,
3294
+ [
3295
+ "inventory_unavailable",
3296
+ "admission_unavailable",
3297
+ "amount_mismatch",
3298
+ "currency_mismatch",
3299
+ "excess_capture",
3300
+ "late_capture",
3301
+ "cross_checkout_duplicate"
3302
+ ],
3303
+ resource,
3304
+ "$.reconciliation"
3305
+ );
3306
+ }
3307
+ } else fail(resource, "$.finalizationStatus", "pending | committed");
3308
+ } else if (status === "failed") {
3309
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3310
+ fail(resource, "$", "historical suppressed failed state");
3311
+ }
3312
+ validateNoReconciliation(
3313
+ session.reconciliation,
3314
+ resource,
3315
+ "$.reconciliation"
3316
+ );
3317
+ const failure = record(session.failure, resource, "$.failure");
3318
+ exact(failure, ["reason"], ["message"], resource, "$.failure");
3319
+ enumValue(
3320
+ failure.reason,
3321
+ PAYMENT_FAILURE_REASONS,
3322
+ resource,
3323
+ "$.failure.reason"
3324
+ );
3325
+ if (failure.message !== void 0)
3326
+ string(failure.message, resource, "$.failure.message");
3327
+ } else {
3328
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3329
+ fail(resource, "$", "historical suppressed canceled state");
3330
+ }
3331
+ validateNoReconciliation(
3332
+ session.reconciliation,
3333
+ resource,
3334
+ "$.reconciliation"
3335
+ );
3336
+ enumValue(
3337
+ session.cancellationReason,
3338
+ ["expired", "customer", "operator", "provider"],
3339
+ resource,
3340
+ "$.cancellationReason"
3341
+ );
3342
+ }
3343
+ return value;
1418
3344
  }
1419
- var ContentClient = class {
1420
- constructor(options) {
1421
- const api = new PublicContentApi("ContentClient", {
1422
- publishableKey: options.publishableKey,
1423
- apiUrl: options.apiUrl,
1424
- onRequestId: options.onRequestId,
1425
- requiresCredential: false
1426
- });
1427
- this.links = {
1428
- list: (params) => api.get(linksListPath(params))
1429
- };
1430
- this.galleryItems = {
1431
- list: (params) => api.get(
1432
- galleryItemsListPath(params)
1433
- )
1434
- };
1435
- }
1436
- };
1437
3345
 
1438
3346
  // src/core/customer/customer-auth.ts
1439
3347
  var DEFAULT_TIMEOUT2 = 15e3;
@@ -1452,8 +3360,10 @@ var CustomerAuth = class {
1452
3360
  const persist = options?.persist ?? true;
1453
3361
  if (persist) {
1454
3362
  const key = typeof persist === "string" ? persist : "customer-token";
3363
+ const refreshKey = `${key}:refresh`;
1455
3364
  const isBrowser = typeof window !== "undefined";
1456
3365
  this.token = isBrowser ? safeGetItem(key) : null;
3366
+ this.refreshTokenValue = isBrowser ? safeGetItem(refreshKey) : null;
1457
3367
  this.onTokenChange = isBrowser ? (token) => {
1458
3368
  try {
1459
3369
  if (token) localStorage.setItem(key, token);
@@ -1461,9 +3371,18 @@ var CustomerAuth = class {
1461
3371
  } catch {
1462
3372
  }
1463
3373
  } : void 0;
3374
+ this.onRefreshTokenChange = isBrowser ? (refreshToken) => {
3375
+ try {
3376
+ if (refreshToken) localStorage.setItem(refreshKey, refreshToken);
3377
+ else localStorage.removeItem(refreshKey);
3378
+ } catch {
3379
+ }
3380
+ } : void 0;
1464
3381
  } else {
1465
3382
  this.token = options?.token ?? null;
3383
+ this.refreshTokenValue = options?.refreshToken ?? null;
1466
3384
  this.onTokenChange = options?.onTokenChange;
3385
+ this.onRefreshTokenChange = options?.onRefreshTokenChange;
1467
3386
  }
1468
3387
  }
1469
3388
  /**
@@ -1487,13 +3406,17 @@ var CustomerAuth = class {
1487
3406
  }
1488
3407
  );
1489
3408
  this.setToken(result.token);
3409
+ if (result.refreshToken) this.setRefreshToken(result.refreshToken);
1490
3410
  return result;
1491
3411
  }
1492
3412
  /**
1493
- * Refresh the current token. Requires a valid (non-expired) token.
3413
+ * Refresh the current token. Uses a refresh token when available, otherwise
3414
+ * falls back to the legacy bearer-token compatibility path.
1494
3415
  */
1495
3416
  async refreshToken() {
1496
- if (!this.token) throw new ApiError("Not authenticated", 401);
3417
+ if (!this.refreshTokenValue && !this.token) {
3418
+ throw new ApiError("Not authenticated", 401);
3419
+ }
1497
3420
  if (this.refreshPromise) return this.refreshPromise;
1498
3421
  this.refreshPromise = this._doRefreshToken();
1499
3422
  try {
@@ -1503,14 +3426,19 @@ var CustomerAuth = class {
1503
3426
  }
1504
3427
  }
1505
3428
  async _doRefreshToken() {
3429
+ const init = this.refreshTokenValue ? {
3430
+ method: "POST",
3431
+ body: JSON.stringify({ refreshToken: this.refreshTokenValue })
3432
+ } : {
3433
+ method: "POST",
3434
+ headers: { Authorization: `Bearer ${this.token}` }
3435
+ };
1506
3436
  const result = await this.requestJson(
1507
3437
  "/api/customers/refresh",
1508
- {
1509
- method: "POST",
1510
- headers: { Authorization: `Bearer ${this.token}` }
1511
- }
3438
+ init
1512
3439
  );
1513
3440
  this.setToken(result.token);
3441
+ if (result.refreshToken) this.setRefreshToken(result.refreshToken);
1514
3442
  return result;
1515
3443
  }
1516
3444
  /**
@@ -1518,6 +3446,7 @@ var CustomerAuth = class {
1518
3446
  */
1519
3447
  logout() {
1520
3448
  this.setToken(null);
3449
+ this.setRefreshToken(null);
1521
3450
  }
1522
3451
  /**
1523
3452
  * Get the current authenticated customer's profile
@@ -1593,25 +3522,28 @@ var CustomerAuth = class {
1593
3522
  const params = new URLSearchParams();
1594
3523
  if (options?.page) params.set("page", String(options.page));
1595
3524
  if (options?.limit) params.set("limit", String(options.limit));
1596
- if (options?.displayFinancialStatus) {
1597
- params.set("displayFinancialStatus", options.displayFinancialStatus);
3525
+ if (options?.financialStatus) {
3526
+ params.set("financialStatus", options.financialStatus);
1598
3527
  }
1599
- if (options?.displayFulfillmentStatus) {
1600
- params.set("displayFulfillmentStatus", options.displayFulfillmentStatus);
3528
+ if (options?.fulfillmentStatus) {
3529
+ params.set("fulfillmentStatus", options.fulfillmentStatus);
1601
3530
  }
1602
3531
  if (options?.returnStatus) params.set("returnStatus", options.returnStatus);
3532
+ if (options?.confirmationStatus) {
3533
+ params.set("confirmationStatus", options.confirmationStatus);
3534
+ }
1603
3535
  if (options?.primaryDisplayStatus) {
1604
3536
  params.set("primaryDisplayStatus", options.primaryDisplayStatus);
1605
3537
  }
1606
- if (options?.returnDisplayStatus) {
1607
- params.set("returnDisplayStatus", options.returnDisplayStatus);
1608
- }
1609
- if (options?.status) params.set("status", options.status);
1610
3538
  const qs = params.toString();
1611
- return this.requestJson(`/api/customers/me/orders${qs ? `?${qs}` : ""}`, {
1612
- method: "GET",
1613
- headers: { Authorization: `Bearer ${this.token}` }
1614
- });
3539
+ const result = await this.requestJson(
3540
+ `/api/customers/me/orders${qs ? `?${qs}` : ""}`,
3541
+ {
3542
+ method: "GET",
3543
+ headers: { Authorization: `Bearer ${this.token}` }
3544
+ }
3545
+ );
3546
+ return validatePublicOrderList(result);
1615
3547
  }
1616
3548
  /**
1617
3549
  * Get the current token (or null if not authenticated)
@@ -1619,6 +3551,12 @@ var CustomerAuth = class {
1619
3551
  getToken() {
1620
3552
  return this.token;
1621
3553
  }
3554
+ /**
3555
+ * Get the current refresh token (or null if unavailable)
3556
+ */
3557
+ getRefreshToken() {
3558
+ return this.refreshTokenValue;
3559
+ }
1622
3560
  /**
1623
3561
  * Set the token manually (e.g. from SSR)
1624
3562
  */
@@ -1626,6 +3564,13 @@ var CustomerAuth = class {
1626
3564
  this.token = token;
1627
3565
  this.onTokenChange?.(token);
1628
3566
  }
3567
+ /**
3568
+ * Set the refresh token manually (e.g. from SSR cookie)
3569
+ */
3570
+ setRefreshToken(refreshToken) {
3571
+ this.refreshTokenValue = refreshToken;
3572
+ this.onRefreshTokenChange?.(refreshToken);
3573
+ }
1629
3574
  /**
1630
3575
  * Check if the customer is currently authenticated
1631
3576
  */
@@ -1654,91 +3599,358 @@ var CustomerAuth = class {
1654
3599
  }
1655
3600
  };
1656
3601
 
3602
+ // src/core/customer/customer-oauth.ts
3603
+ var DEFAULT_SCOPES = ["openid", "profile", "email"];
3604
+ var DEFAULT_TIMEOUT3 = 15e3;
3605
+ function issuerUrl(issuer, path) {
3606
+ const base = resolveApiUrl(issuer);
3607
+ return new URL(path, base.endsWith("/") ? base : `${base}/`).toString();
3608
+ }
3609
+ function randomBase64Url(bytes) {
3610
+ const buffer = new Uint8Array(bytes);
3611
+ crypto.getRandomValues(buffer);
3612
+ let binary = "";
3613
+ for (const value of buffer) {
3614
+ binary += String.fromCharCode(value);
3615
+ }
3616
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
3617
+ }
3618
+ async function sha256Base64Url(value) {
3619
+ const data = new TextEncoder().encode(value);
3620
+ const digest = await crypto.subtle.digest("SHA-256", data);
3621
+ let binary = "";
3622
+ for (const byte of new Uint8Array(digest)) {
3623
+ binary += String.fromCharCode(byte);
3624
+ }
3625
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
3626
+ }
3627
+ function normalizeToken(body) {
3628
+ if (body.token_type !== "Bearer") {
3629
+ throw new Error("Unsupported customer OAuth token type");
3630
+ }
3631
+ return {
3632
+ accessToken: body.access_token,
3633
+ expiresAt: Date.now() + body.expires_in * 1e3,
3634
+ expiresIn: body.expires_in,
3635
+ ...body.id_token ? { idToken: body.id_token } : {},
3636
+ refreshToken: body.refresh_token,
3637
+ ...body.scope ? { scope: body.scope } : {},
3638
+ tokenType: "Bearer"
3639
+ };
3640
+ }
3641
+ var CustomerOAuth = class {
3642
+ constructor(config) {
3643
+ if (!config.clientId) throw new Error("customer OAuth clientId is required");
3644
+ if (!config.issuer) throw new Error("customer OAuth issuer is required");
3645
+ this.clientId = config.clientId;
3646
+ this.issuer = config.issuer;
3647
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT3;
3648
+ }
3649
+ async createAuthorizationUrl(input) {
3650
+ const codeVerifier = randomBase64Url(48);
3651
+ const codeChallenge = await sha256Base64Url(codeVerifier);
3652
+ const state = randomBase64Url(32);
3653
+ const nonce = randomBase64Url(32);
3654
+ const scopes = input.scopes ?? DEFAULT_SCOPES;
3655
+ const url = new URL(issuerUrl(this.issuer, "customer-oauth/authorize"));
3656
+ url.searchParams.set("response_type", "code");
3657
+ url.searchParams.set("client_id", this.clientId);
3658
+ url.searchParams.set("redirect_uri", input.redirectUri);
3659
+ url.searchParams.set("scope", scopes.join(" "));
3660
+ url.searchParams.set("state", state);
3661
+ url.searchParams.set("nonce", nonce);
3662
+ url.searchParams.set("code_challenge", codeChallenge);
3663
+ url.searchParams.set("code_challenge_method", "S256");
3664
+ return {
3665
+ authorizationUrl: url.toString(),
3666
+ codeChallenge,
3667
+ codeVerifier,
3668
+ nonce,
3669
+ returnTo: input.returnTo ?? null,
3670
+ state
3671
+ };
3672
+ }
3673
+ parseCallback(callbackUrl, options) {
3674
+ const url = new URL(callbackUrl);
3675
+ const error = url.searchParams.get("error");
3676
+ if (error) {
3677
+ throw new Error(
3678
+ url.searchParams.get("error_description") ?? `OAuth error: ${error}`
3679
+ );
3680
+ }
3681
+ const code = url.searchParams.get("code");
3682
+ const state = url.searchParams.get("state");
3683
+ if (!code || !state) throw new Error("OAuth callback is missing code/state");
3684
+ if (state !== options.expectedState) throw new Error("OAuth state mismatch");
3685
+ return { code, state };
3686
+ }
3687
+ async exchangeCode(input) {
3688
+ const body = new URLSearchParams({
3689
+ client_id: this.clientId,
3690
+ code: input.code,
3691
+ code_verifier: input.codeVerifier,
3692
+ grant_type: "authorization_code",
3693
+ redirect_uri: input.redirectUri
3694
+ });
3695
+ return this.tokenRequest(body);
3696
+ }
3697
+ async refresh(input) {
3698
+ const body = new URLSearchParams({
3699
+ client_id: this.clientId,
3700
+ grant_type: "refresh_token",
3701
+ refresh_token: input.refreshToken
3702
+ });
3703
+ return this.tokenRequest(body);
3704
+ }
3705
+ async logout(input) {
3706
+ const body = { client_id: this.clientId };
3707
+ if (input.refreshToken) body.refresh_token = input.refreshToken;
3708
+ if (input.postLogoutRedirectUri) {
3709
+ body.post_logout_redirect_uri = input.postLogoutRedirectUri;
3710
+ }
3711
+ const response = await httpFetch("/customer-oauth/logout", {
3712
+ apiUrl: this.issuer,
3713
+ method: "POST",
3714
+ body: JSON.stringify(body),
3715
+ headers: { "Content-Type": "application/json" },
3716
+ timeout: this.timeout,
3717
+ retry: { maxRetries: 0 }
3718
+ });
3719
+ return parseApiResponse(
3720
+ response,
3721
+ "/customer-oauth/logout"
3722
+ );
3723
+ }
3724
+ verifyIdToken() {
3725
+ throw new Error(
3726
+ "Customer OAuth ID token verification is not implemented; treat idToken as opaque."
3727
+ );
3728
+ }
3729
+ async tokenRequest(body) {
3730
+ const response = await httpFetch("/api/customer-oauth/token", {
3731
+ apiUrl: this.issuer,
3732
+ method: "POST",
3733
+ body,
3734
+ headers: {
3735
+ "Content-Type": "application/x-www-form-urlencoded"
3736
+ },
3737
+ timeout: this.timeout,
3738
+ retry: { maxRetries: 0 }
3739
+ });
3740
+ return normalizeToken(
3741
+ await parseApiResponse(
3742
+ response,
3743
+ "/api/customer-oauth/token"
3744
+ )
3745
+ );
3746
+ }
3747
+ };
3748
+
1657
3749
  // src/core/customer/customer-namespace.ts
1658
3750
  var CustomerNamespace = class {
1659
3751
  constructor(publishableKey, options, apiUrl) {
1660
3752
  this.auth = new CustomerAuth(publishableKey, options, apiUrl);
3753
+ if (options?.oauth) {
3754
+ this.oauth = new CustomerOAuth(options.oauth);
3755
+ }
1661
3756
  }
1662
3757
  };
1663
3758
 
3759
+ // src/core/api/commerce-idempotency.ts
3760
+ 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;
3761
+ var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
3762
+ function isCommerceIdempotencyKey(value) {
3763
+ return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
3764
+ }
3765
+ function assertCommerceIdempotencyKey(value) {
3766
+ if (isCommerceIdempotencyKey(value)) return;
3767
+ throw createValidationError(
3768
+ "idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
3769
+ { field: "idempotencyKey" }
3770
+ );
3771
+ }
3772
+
1664
3773
  // src/core/api/cart-api.ts
1665
3774
  var CartApi = class extends CustomerScopedApi {
1666
3775
  constructor(options) {
1667
3776
  super("CartApi", { ...options, requiresCredential: false });
3777
+ this.serverTransport = Boolean(options.secretKey);
1668
3778
  }
1669
- async execute(endpoint, method, body) {
1670
- return this.request(endpoint, { method, body });
3779
+ endpoint(key) {
3780
+ return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
1671
3781
  }
1672
- /**
1673
- * Create a cart and receive its `cartToken`. Store the token and pass it to
1674
- * every subsequent cart operation.
1675
- */
1676
- createCart(params = {}) {
1677
- return this.execute("/api/carts/create", "POST", params);
3782
+ execute(endpoint2, body, idempotencyKey) {
3783
+ return this.requestEndpoint(endpoint2, body, {
3784
+ ...idempotencyKey && {
3785
+ headers: { "X-Idempotency-Key": idempotencyKey }
3786
+ }
3787
+ });
1678
3788
  }
1679
- getCart(cartToken) {
1680
- return this.execute("/api/carts/get", "POST", { cartToken });
3789
+ create(params = {}) {
3790
+ return this.execute(this.endpoint("create"), params).then(
3791
+ (value) => validateCreateCartResult(value)
3792
+ );
1681
3793
  }
1682
- merge(params) {
1683
- return this.execute(
1684
- COMMERCE_ENDPOINTS.carts.merge,
1685
- "POST",
1686
- params
3794
+ retrieve(params) {
3795
+ return this.execute(this.endpoint("retrieve"), params).then(
3796
+ (value) => validatePublicCart(value)
1687
3797
  );
1688
3798
  }
1689
- /**
1690
- * Resolve the authenticated customer's active cart by JWT (no `cartToken`
1691
- * required). Returns the cart and its capability handle, or both `null` when
1692
- * the customer has no active cart. Requires a customer token.
1693
- */
1694
- mine() {
1695
- return this.execute(
1696
- COMMERCE_ENDPOINTS.carts.mine,
1697
- "POST",
1698
- {}
3799
+ mine(params = {}) {
3800
+ const endpoint2 = this.endpoint("mine");
3801
+ return this.execute(endpoint2, params).then(
3802
+ (value) => validateCartMineResult(value)
3803
+ );
3804
+ }
3805
+ merge(params) {
3806
+ const { idempotencyKey, ...body } = params;
3807
+ assertCommerceIdempotencyKey(idempotencyKey);
3808
+ const endpoint2 = this.endpoint("merge");
3809
+ return this.execute(endpoint2, body, idempotencyKey).then(
3810
+ (value) => validateCartMergeResult(value)
1699
3811
  );
1700
3812
  }
1701
3813
  addItem(params) {
1702
- return this.execute(
1703
- COMMERCE_ENDPOINTS.carts.addItem,
1704
- "POST",
1705
- params
3814
+ return this.mutate(this.endpoint("addItem"), params);
3815
+ }
3816
+ mutate(endpoint2, params) {
3817
+ const { idempotencyKey, ...body } = params;
3818
+ assertCommerceIdempotencyKey(idempotencyKey);
3819
+ return this.execute(endpoint2, body, idempotencyKey).then(
3820
+ (value) => validateCartMutationResult(value)
1706
3821
  );
1707
3822
  }
1708
3823
  updateItem(params) {
1709
- return this.execute(
1710
- COMMERCE_ENDPOINTS.carts.updateItem,
1711
- "POST",
1712
- params
1713
- );
3824
+ return this.mutate(this.endpoint("updateItem"), params);
1714
3825
  }
1715
3826
  removeItem(params) {
1716
- return this.execute(
1717
- COMMERCE_ENDPOINTS.carts.removeItem,
1718
- "POST",
1719
- params
3827
+ return this.mutate(this.endpoint("removeItem"), params);
3828
+ }
3829
+ clear(params) {
3830
+ return this.mutate(this.endpoint("clear"), params);
3831
+ }
3832
+ updateDiscountCodes(params) {
3833
+ return this.mutate(this.endpoint("updateDiscountCodes"), params);
3834
+ }
3835
+ updateAttributes(params) {
3836
+ return this.mutate(this.endpoint("updateAttributes"), params);
3837
+ }
3838
+ };
3839
+
3840
+ // src/core/api/checkout-api.ts
3841
+ var CheckoutApi = class extends CustomerScopedApi {
3842
+ constructor(options) {
3843
+ super("CheckoutApi", { ...options, requiresCredential: false });
3844
+ }
3845
+ post(endpoint2, body, idempotencyKey) {
3846
+ return this.requestEndpoint(endpoint2, body, {
3847
+ ...idempotencyKey && {
3848
+ headers: { "X-Idempotency-Key": idempotencyKey }
3849
+ }
3850
+ });
3851
+ }
3852
+ async publicCheckout(result) {
3853
+ return validatePublicCheckout(await result);
3854
+ }
3855
+ async serverCheckout(result) {
3856
+ return validateServerCheckout(await result);
3857
+ }
3858
+ async createResult(result) {
3859
+ return validateCreateCheckoutResult(
3860
+ await result,
3861
+ false
1720
3862
  );
1721
3863
  }
1722
- applyDiscount(params) {
1723
- return this.execute(
1724
- COMMERCE_ENDPOINTS.carts.applyDiscount,
1725
- "POST",
1726
- params
3864
+ async createServerResult(result) {
3865
+ return validateCreateCheckoutResult(
3866
+ await result,
3867
+ true
1727
3868
  );
1728
3869
  }
1729
- removeDiscount(params) {
1730
- return this.execute(
1731
- COMMERCE_ENDPOINTS.carts.removeDiscount,
1732
- "POST",
1733
- params
3870
+ create(params) {
3871
+ const { idempotencyKey, ...body } = params;
3872
+ assertCommerceIdempotencyKey(idempotencyKey);
3873
+ return this.createResult(
3874
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
1734
3875
  );
1735
3876
  }
1736
- clearCart(params) {
1737
- return this.execute(
1738
- COMMERCE_ENDPOINTS.carts.clear,
1739
- "POST",
3877
+ createServer(params) {
3878
+ const { idempotencyKey, ...body } = params;
3879
+ assertCommerceIdempotencyKey(idempotencyKey);
3880
+ return this.createServerResult(
3881
+ this.post(
3882
+ COMMERCE_ENDPOINTS.checkouts.server.create,
3883
+ body,
3884
+ idempotencyKey
3885
+ )
3886
+ );
3887
+ }
3888
+ retrieve(params) {
3889
+ return this.publicCheckout(
3890
+ this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
3891
+ );
3892
+ }
3893
+ retrieveServer(params) {
3894
+ return this.serverCheckout(
3895
+ this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
3896
+ );
3897
+ }
3898
+ async query(params = {}) {
3899
+ const result = await this.post(
3900
+ COMMERCE_ENDPOINTS.checkouts.server.query,
1740
3901
  params
1741
3902
  );
3903
+ return validateCheckoutQueryResult(result);
3904
+ }
3905
+ };
3906
+
3907
+ // src/core/api/payment-session-api.ts
3908
+ var PaymentSessionApi = class extends CustomerScopedApi {
3909
+ constructor(options) {
3910
+ super("PaymentSessionApi", { ...options, requiresCredential: false });
3911
+ this.serverTransport = Boolean(options.secretKey);
3912
+ }
3913
+ post(endpoint2, body, idempotencyKey) {
3914
+ return this.requestEndpoint(endpoint2, body, {
3915
+ ...idempotencyKey && {
3916
+ headers: { "X-Idempotency-Key": idempotencyKey }
3917
+ }
3918
+ });
3919
+ }
3920
+ async paymentSession(result) {
3921
+ return validatePublicPaymentSession(await result);
3922
+ }
3923
+ create(params) {
3924
+ const { idempotencyKey, ...body } = params;
3925
+ assertCommerceIdempotencyKey(idempotencyKey);
3926
+ return this.paymentSession(
3927
+ this.post(
3928
+ this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
3929
+ body,
3930
+ idempotencyKey
3931
+ )
3932
+ );
3933
+ }
3934
+ retrieve(params) {
3935
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
3936
+ return this.paymentSession(this.post(endpoint2, params));
3937
+ }
3938
+ cancel(params) {
3939
+ const { idempotencyKey, ...body } = params;
3940
+ assertCommerceIdempotencyKey(idempotencyKey);
3941
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
3942
+ return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
3943
+ }
3944
+ confirm(params) {
3945
+ const { idempotencyKey, ...body } = params;
3946
+ assertCommerceIdempotencyKey(idempotencyKey);
3947
+ return this.paymentSession(
3948
+ this.post(
3949
+ COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
3950
+ body,
3951
+ idempotencyKey
3952
+ )
3953
+ );
1742
3954
  }
1743
3955
  };
1744
3956
 
@@ -2545,6 +4757,9 @@ function compareVariantOrder(a, b) {
2545
4757
  }
2546
4758
  function getVariantAvailableForSale(variant) {
2547
4759
  if (variant.isActive === false) return false;
4760
+ if (typeof variant.availableForSale === "boolean") {
4761
+ return variant.availableForSale;
4762
+ }
2548
4763
  if (variant.isUnlimited) return true;
2549
4764
  if (variant.inventoryPolicy === "continue") return true;
2550
4765
  return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
@@ -2654,7 +4869,7 @@ function buildProductListingCard(item, options = {}) {
2654
4869
  { listing: { selectionHintVariant } },
2655
4870
  options
2656
4871
  ),
2657
- title: product.title,
4872
+ title: product.title ?? "",
2658
4873
  representativeVariant,
2659
4874
  primaryImage: listingPrimaryMedia,
2660
4875
  priceRange,
@@ -2782,6 +4997,11 @@ function productDetailResultFromError(error) {
2782
4997
  if (!reason) return void 0;
2783
4998
  return { found: false, reason };
2784
4999
  }
5000
+ var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
5001
+ var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
5002
+ "priceRange.minVariantPrice.amount",
5003
+ "priceRange.maxVariantPrice.amount"
5004
+ ]);
2785
5005
  function nonEmpty(values) {
2786
5006
  return values?.length ? values : void 0;
2787
5007
  }
@@ -2829,14 +5049,34 @@ function buildProductListingPageWhere(params) {
2829
5049
  if (clauses.length === 1) return clauses[0];
2830
5050
  return { and: clauses };
2831
5051
  }
2832
- function buildProductListingPageUrl(params) {
5052
+ function productListingPageUsesBasePriceSort(sort) {
5053
+ const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
5054
+ return values.some(
5055
+ (value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
5056
+ );
5057
+ }
5058
+ function assertMarketListingPageQuerySupported(params) {
5059
+ if (!params.market?.trim()) return;
5060
+ const priceFilter = params.filters?.price;
5061
+ if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
5062
+ throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
5063
+ }
5064
+ }
5065
+ function buildProductListingPageRequest(params) {
5066
+ assertMarketListingPageQuerySupported(params);
2833
5067
  const options = {
5068
+ market: params.market,
5069
+ locale: params.locale,
5070
+ fallbackLocale: params.fallbackLocale,
2834
5071
  page: params.page,
2835
5072
  limit: params.limit,
2836
5073
  sort: params.sort,
2837
5074
  where: buildProductListingPageWhere(params)
2838
5075
  };
2839
- return params.mode === "full" ? listingGroupsQueryUrl(options) : listingGroupsQueryCatalogUrl(options);
5076
+ return {
5077
+ operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
5078
+ query: listingPageSearchParams(options)
5079
+ };
2840
5080
  }
2841
5081
  function withProductListingCards(response, options) {
2842
5082
  return {
@@ -2845,30 +5085,15 @@ function withProductListingCards(response, options) {
2845
5085
  };
2846
5086
  }
2847
5087
 
2848
- // src/core/api/order-api.ts
2849
- function idempotencyRequestOptions(idempotencyKey) {
2850
- return idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0;
2851
- }
2852
- function splitIdempotencyKey(params) {
2853
- const { idempotencyKey, ...body } = params;
2854
- return { body, idempotencyKey };
2855
- }
2856
-
2857
5088
  // src/core/commerce/commerce-client.ts
2858
5089
  var BrowserCommerceApi = class extends CustomerScopedApi {
2859
- post(endpoint, body, requestOptions) {
2860
- return this.request(endpoint, {
2861
- method: "POST",
2862
- body,
2863
- headers: requestOptions?.headers
2864
- });
2865
- }
2866
- get(endpoint) {
2867
- return this.request(endpoint, { method: "GET" });
5090
+ requestEndpoint(endpoint2, body, options) {
5091
+ return super.requestEndpoint(endpoint2, body, options);
2868
5092
  }
2869
5093
  };
2870
5094
  var CommerceClient = class {
2871
5095
  constructor(options) {
5096
+ this.market = options.market;
2872
5097
  const cartApi = new CartApi({
2873
5098
  publishableKey: options.publishableKey,
2874
5099
  apiUrl: options.apiUrl,
@@ -2876,6 +5101,20 @@ var CommerceClient = class {
2876
5101
  onUnauthorized: options.onUnauthorized,
2877
5102
  onRequestId: options.onRequestId
2878
5103
  });
5104
+ const checkoutApi = new CheckoutApi({
5105
+ publishableKey: options.publishableKey,
5106
+ apiUrl: options.apiUrl,
5107
+ customerToken: options.customerToken,
5108
+ onUnauthorized: options.onUnauthorized,
5109
+ onRequestId: options.onRequestId
5110
+ });
5111
+ const paymentSessionApi = new PaymentSessionApi({
5112
+ publishableKey: options.publishableKey,
5113
+ apiUrl: options.apiUrl,
5114
+ customerToken: options.customerToken,
5115
+ onUnauthorized: options.onUnauthorized,
5116
+ onRequestId: options.onRequestId
5117
+ });
2879
5118
  const api = new BrowserCommerceApi("CommerceClient", {
2880
5119
  publishableKey: options.publishableKey,
2881
5120
  apiUrl: options.apiUrl,
@@ -2884,29 +5123,42 @@ var CommerceClient = class {
2884
5123
  onRequestId: options.onRequestId
2885
5124
  });
2886
5125
  this.product = {
2887
- stockCheck: (params) => api.post(
2888
- COMMERCE_ENDPOINTS.products.stockCheck,
5126
+ stockCheck: (params) => api.requestEndpoint(
5127
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
2889
5128
  params
2890
5129
  ),
2891
- stockSnapshot: (params) => api.get(stockSnapshotQuery(params)),
2892
- listingGroups: (params) => api.get(
2893
- listingGroupsCatalogQuery(params)
5130
+ stockSnapshot: (params) => api.requestEndpoint(
5131
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
5132
+ void 0,
5133
+ { query: stockSnapshotSearchParams(params) }
5134
+ ),
5135
+ listingGroups: (params) => api.requestEndpoint(
5136
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
5137
+ void 0,
5138
+ { query: listingGroupsSearchParams(this.withMarket(params)) }
2894
5139
  ),
2895
- listingGroupsCatalog: (params) => api.get(
2896
- listingGroupsCatalogQuery(params)
5140
+ listingGroupsCatalog: (params) => api.requestEndpoint(
5141
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
5142
+ void 0,
5143
+ { query: listingGroupsSearchParams(this.withMarket(params)) }
2897
5144
  ),
2898
5145
  listingPage: async (params = {}) => {
2899
5146
  const catalogParams = {
2900
5147
  ...params,
2901
5148
  mode: "catalog"
2902
5149
  };
2903
- const response = await api.get(buildProductListingPageUrl(catalogParams));
2904
- return withProductListingCards(response, catalogParams);
5150
+ const request = buildProductListingPageRequest(
5151
+ this.withMarket(catalogParams)
5152
+ );
5153
+ const response = await api.requestEndpoint(request.operation, void 0, { query: request.query });
5154
+ return withProductListingCards(response, this.withMarket(catalogParams));
2905
5155
  },
2906
5156
  detail: async (params) => {
2907
5157
  try {
2908
- const product = await api.get(
2909
- productDetailQuery(params)
5158
+ const product = await api.requestEndpoint(
5159
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
5160
+ void 0,
5161
+ { query: productDetailSearchParams(this.withMarket(params)) }
2910
5162
  );
2911
5163
  return { found: true, product };
2912
5164
  } catch (err) {
@@ -2917,8 +5169,10 @@ var CommerceClient = class {
2917
5169
  },
2918
5170
  detailCatalog: async (params) => {
2919
5171
  try {
2920
- const product = await api.get(
2921
- productDetailCatalogQuery(params)
5172
+ const product = await api.requestEndpoint(
5173
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
5174
+ void 0,
5175
+ { query: productDetailSearchParams(this.withMarket(params)) }
2922
5176
  );
2923
5177
  return { found: true, product };
2924
5178
  } catch (err) {
@@ -2928,39 +5182,51 @@ var CommerceClient = class {
2928
5182
  }
2929
5183
  }
2930
5184
  };
2931
- this.cart = {
2932
- create: cartApi.createCart.bind(cartApi),
2933
- get: cartApi.getCart.bind(cartApi),
5185
+ this.carts = {
5186
+ create: (params) => cartApi.create(this.withMarket(params ?? {})),
5187
+ retrieve: cartApi.retrieve.bind(cartApi),
2934
5188
  addItem: cartApi.addItem.bind(cartApi),
2935
5189
  updateItem: cartApi.updateItem.bind(cartApi),
2936
5190
  removeItem: cartApi.removeItem.bind(cartApi),
2937
- applyDiscount: cartApi.applyDiscount.bind(cartApi),
2938
- removeDiscount: cartApi.removeDiscount.bind(cartApi),
2939
- clear: cartApi.clearCart.bind(cartApi),
5191
+ updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
5192
+ updateAttributes: cartApi.updateAttributes.bind(cartApi),
5193
+ clear: cartApi.clear.bind(cartApi),
2940
5194
  merge: cartApi.merge.bind(cartApi),
2941
5195
  mine: cartApi.mine.bind(cartApi)
2942
5196
  };
2943
5197
  this.orders = {
2944
- checkout: (params) => {
2945
- const { body, idempotencyKey } = splitIdempotencyKey(params);
2946
- return api.post(
2947
- "/api/orders/checkout",
2948
- body,
2949
- idempotencyRequestOptions(idempotencyKey)
2950
- );
2951
- },
2952
5198
  listMine: (params) => options.customerAuth.getMyOrders(params)
2953
5199
  };
5200
+ this.checkouts = {
5201
+ create: checkoutApi.create.bind(checkoutApi),
5202
+ retrieve: checkoutApi.retrieve.bind(checkoutApi)
5203
+ };
5204
+ this.paymentSessions = {
5205
+ create: paymentSessionApi.create.bind(paymentSessionApi),
5206
+ retrieve: (params) => paymentSessionApi.retrieve(params),
5207
+ cancel: (params) => paymentSessionApi.cancel(params)
5208
+ };
2954
5209
  this.discounts = {
2955
- validate: (params) => api.post("/api/discounts/validate", params)
5210
+ validate: (params) => api.requestEndpoint(
5211
+ COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
5212
+ params
5213
+ )
2956
5214
  };
2957
5215
  this.shipping = {
2958
- calculate: (params) => api.post(
2959
- "/api/shipping-policies/calculate",
5216
+ calculate: (params) => api.requestEndpoint(
5217
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
2960
5218
  params
2961
5219
  )
2962
5220
  };
2963
5221
  }
5222
+ getDefaultMarket() {
5223
+ return this.market;
5224
+ }
5225
+ withMarket(params) {
5226
+ const defaultMarket = this.market?.trim();
5227
+ if (!defaultMarket || params.market?.trim()) return params;
5228
+ return { ...params, market: defaultMarket };
5229
+ }
2964
5230
  };
2965
5231
 
2966
5232
  // src/core/events/events-client.ts
@@ -2980,7 +5246,17 @@ var EventsClient = class {
2980
5246
  getRange(params) {
2981
5247
  return this.execute(
2982
5248
  buildRangeEndpoint(params),
2983
- "GET",
5249
+ resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
5250
+ void 0,
5251
+ { useCustomerAuth: false }
5252
+ );
5253
+ }
5254
+ getAdmissionAvailability(params) {
5255
+ return this.execute(
5256
+ buildAdmissionAvailabilityEndpoint(params),
5257
+ resolveOperationMethod(
5258
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
5259
+ ),
2984
5260
  void 0,
2985
5261
  { useCustomerAuth: false }
2986
5262
  );
@@ -3009,11 +5285,11 @@ var EventsClient = class {
3009
5285
  { useCustomerAuth: false }
3010
5286
  );
3011
5287
  }
3012
- async execute(endpoint, method, body, options = {}) {
5288
+ async execute(endpoint2, method, body, options = {}) {
3013
5289
  const useCustomerAuth = options.useCustomerAuth === true;
3014
5290
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
3015
5291
  try {
3016
- const response = await httpFetch(endpoint, {
5292
+ const response = await httpFetch(endpoint2, {
3017
5293
  method,
3018
5294
  apiUrl: this.apiUrl,
3019
5295
  publishableKey: this.publishableKey,
@@ -3022,7 +5298,7 @@ var EventsClient = class {
3022
5298
  ...body !== void 0 && { body: JSON.stringify(body) }
3023
5299
  });
3024
5300
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
3025
- return parseApiResponse(response, endpoint);
5301
+ return parseApiResponse(response, endpoint2);
3026
5302
  } catch (err) {
3027
5303
  const id = err instanceof SDKError ? err.requestId ?? null : null;
3028
5304
  this.onRequestId?.(id);
@@ -3061,7 +5337,17 @@ function buildRangeEndpoint(params) {
3061
5337
  appendValues(urlParams, "categorySlug", params.categorySlug);
3062
5338
  appendValues(urlParams, "tag", params.tag);
3063
5339
  appendValues(urlParams, "tagSlug", params.tagSlug);
3064
- return `/api/event-occurrences/range?${urlParams.toString()}`;
5340
+ return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
5341
+ query: urlParams
5342
+ });
5343
+ }
5344
+ function buildAdmissionAvailabilityEndpoint(params) {
5345
+ const urlParams = new URLSearchParams();
5346
+ urlParams.set("occurrence", params.occurrence);
5347
+ return resolveOperationPath(
5348
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
5349
+ { query: urlParams }
5350
+ );
3065
5351
  }
3066
5352
  function formatDateParam(value) {
3067
5353
  return value instanceof Date ? value.toISOString() : value;
@@ -3074,15 +5360,62 @@ function appendValues(params, key, value) {
3074
5360
  }
3075
5361
  }
3076
5362
 
5363
+ // src/core/market/market-discovery.ts
5364
+ function toMarketDTO(row) {
5365
+ return {
5366
+ id: row.id,
5367
+ handle: row.handle,
5368
+ name: row.name,
5369
+ countryCode: row.countryCode,
5370
+ targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
5371
+ currency: row.currency,
5372
+ isPrimary: row.isPrimary === true,
5373
+ isActive: row.isActive === true
5374
+ };
5375
+ }
5376
+ var MarketDiscovery = class {
5377
+ constructor(read) {
5378
+ this.read = read;
5379
+ }
5380
+ async list() {
5381
+ const res = await this.read({
5382
+ where: { isActive: { equals: true } },
5383
+ limit: 100
5384
+ });
5385
+ if (res.hasNextPage) {
5386
+ console.warn(
5387
+ "[markets.list] more than 100 active markets; results truncated to 100."
5388
+ );
5389
+ }
5390
+ return res.docs.map(toMarketDTO);
5391
+ }
5392
+ async default() {
5393
+ const res = await this.read({
5394
+ where: { isPrimary: { equals: true }, isActive: { equals: true } },
5395
+ limit: 1
5396
+ });
5397
+ const row = res.docs[0];
5398
+ return row ? toMarketDTO(row) : null;
5399
+ }
5400
+ };
5401
+
3077
5402
  // src/core/client/client.ts
3078
5403
  var BrowserMembershipApi = class extends CustomerScopedApi {
3079
5404
  me() {
3080
- return this.request(MEMBERSHIP_ENDPOINTS.me, {
3081
- method: "GET"
3082
- });
5405
+ return this.requestEndpoint(
5406
+ MEMBERSHIP_ENDPOINT_OPERATIONS.me
5407
+ );
5408
+ }
5409
+ cancel(params) {
5410
+ const { id, immediate } = params;
5411
+ return this.requestEndpoint(
5412
+ MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
5413
+ immediate !== void 0 ? { immediate } : {},
5414
+ { pathParams: { id } }
5415
+ );
3083
5416
  }
3084
5417
  };
3085
- var Client = class {
5418
+ var Client = class _Client {
3086
5419
  constructor(options) {
3087
5420
  this.lastRequestId = null;
3088
5421
  const publishableKey = options.publishableKey;
@@ -3114,6 +5447,7 @@ var Client = class {
3114
5447
  this.commerce = new CommerceClient({
3115
5448
  publishableKey: this.config.publishableKey,
3116
5449
  apiUrl: this.config.apiUrl,
5450
+ market: this.config.market,
3117
5451
  customerToken: () => this.customer.auth.getToken(),
3118
5452
  onUnauthorized,
3119
5453
  onRequestId,
@@ -3146,6 +5480,9 @@ var Client = class {
3146
5480
  onRequestId,
3147
5481
  this.config.apiUrl
3148
5482
  );
5483
+ this.markets = new MarketDiscovery(
5484
+ (options2) => this.collections.from("markets").find(options2)
5485
+ );
3149
5486
  const membershipApi = new BrowserMembershipApi("MembershipApi", {
3150
5487
  publishableKey: this.config.publishableKey,
3151
5488
  apiUrl: this.config.apiUrl,
@@ -3154,12 +5491,23 @@ var Client = class {
3154
5491
  onRequestId
3155
5492
  });
3156
5493
  this.memberships = {
3157
- me: membershipApi.me.bind(membershipApi)
5494
+ me: membershipApi.me.bind(membershipApi),
5495
+ cancel: membershipApi.cancel.bind(membershipApi)
3158
5496
  };
3159
5497
  }
3160
5498
  getState() {
3161
5499
  return { ...this.state };
3162
5500
  }
5501
+ withMarket(market) {
5502
+ return new _Client({
5503
+ ...this.config,
5504
+ customer: this.config.customer?.persist === false ? {
5505
+ ...this.config.customer,
5506
+ token: this.customer.auth.getToken() ?? void 0
5507
+ } : this.config.customer,
5508
+ market
5509
+ });
5510
+ }
3163
5511
  getConfig() {
3164
5512
  return { ...this.config };
3165
5513
  }