@01.software/sdk 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +358 -2
  2. package/MIGRATION.md +89 -10
  3. package/README.md +441 -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 +2680 -345
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.d.cts +10 -7
  9. package/dist/client.d.ts +10 -7
  10. package/dist/client.js +2680 -345
  11. package/dist/client.js.map +1 -1
  12. package/dist/{collection-client-Dyl-CDcj.d.cts → collection-client-BSo7VXQE.d.cts} +8 -5
  13. package/dist/{collection-client-DWooaiTr.d.ts → collection-client-Ckfusuee.d.ts} +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 +2741 -368
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +18 -19
  27. package/dist/index.d.ts +18 -19
  28. package/dist/index.js +2741 -368
  29. package/dist/index.js.map +1 -1
  30. package/dist/{payload-types-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 +550 -101
  33. package/dist/query.cjs.map +1 -1
  34. package/dist/query.d.cts +43 -45
  35. package/dist/query.d.ts +43 -45
  36. package/dist/query.js +550 -101
  37. package/dist/query.js.map +1 -1
  38. package/dist/realtime.cjs.map +1 -1
  39. package/dist/realtime.d.cts +2 -2
  40. package/dist/realtime.d.ts +2 -2
  41. package/dist/realtime.js.map +1 -1
  42. package/dist/server.cjs +2252 -444
  43. package/dist/server.cjs.map +1 -1
  44. package/dist/server.d.cts +11 -10
  45. package/dist/server.d.ts +11 -10
  46. package/dist/server.js +2252 -444
  47. package/dist/server.js.map +1 -1
  48. package/dist/storefront-cache.cjs +65 -1
  49. package/dist/storefront-cache.cjs.map +1 -1
  50. package/dist/storefront-cache.js +65 -1
  51. package/dist/storefront-cache.js.map +1 -1
  52. package/dist/types-BC6rVmJa.d.ts +47 -0
  53. package/dist/{types-CDND3hzq.d.cts → types-BlOvjoTX.d.ts} +1095 -509
  54. package/dist/{types-Dt9FJisi.d.ts → types-C4WuJfw7.d.cts} +1095 -509
  55. package/dist/types-D5p7-m1l.d.cts +47 -0
  56. package/dist/ui/canvas/server.cjs +244 -2
  57. package/dist/ui/canvas/server.cjs.map +1 -1
  58. package/dist/ui/canvas/server.d.cts +27 -1
  59. package/dist/ui/canvas/server.d.ts +27 -1
  60. package/dist/ui/canvas/server.js +244 -2
  61. package/dist/ui/canvas/server.js.map +1 -1
  62. package/dist/ui/canvas.cjs +419 -103
  63. package/dist/ui/canvas.cjs.map +1 -1
  64. package/dist/ui/canvas.d.cts +19 -7
  65. package/dist/ui/canvas.d.ts +19 -7
  66. package/dist/ui/canvas.js +419 -103
  67. package/dist/ui/canvas.js.map +1 -1
  68. package/dist/ui/form.d.cts +1 -1
  69. package/dist/ui/form.d.ts +1 -1
  70. package/dist/ui/video.d.cts +1 -1
  71. package/dist/ui/video.d.ts +1 -1
  72. package/dist/webhook.cjs +2 -1
  73. package/dist/webhook.cjs.map +1 -1
  74. package/dist/webhook.d.cts +4 -4
  75. package/dist/webhook.d.ts +4 -4
  76. package/dist/webhook.js +2 -1
  77. package/dist/webhook.js.map +1 -1
  78. package/package.json +12 -11
  79. package/dist/types-SoXsbKhj.d.cts +0 -33
  80. package/dist/types-oiae_LMm.d.ts +0 -33
package/dist/server.cjs CHANGED
@@ -63,10 +63,136 @@ var SDKError = class extends Error {
63
63
  details: this.details,
64
64
  userMessage: this.userMessage,
65
65
  suggestion: this.suggestion,
66
- ...this.requestId !== void 0 && { requestId: this.requestId }
66
+ ...this.requestId !== void 0 && { requestId: this.requestId },
67
+ ...this.kind !== void 0 && { kind: this.kind },
68
+ ...this.reason !== void 0 && { reason: this.reason },
69
+ ...this.rawReason !== void 0 && { rawReason: this.rawReason },
70
+ ...this.retryable !== void 0 && { retryable: this.retryable },
71
+ ...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
67
72
  };
68
73
  }
69
74
  };
75
+ var COMMERCE_ERROR_CODES = [
76
+ "validation_failed",
77
+ "unauthorized",
78
+ "forbidden",
79
+ "token_expired",
80
+ "origin_not_allowed",
81
+ "server_credentials_required",
82
+ "not_found",
83
+ "conflict",
84
+ "cart_revision_conflict",
85
+ "rate_limit_exceeded",
86
+ "usage_limit_exceeded",
87
+ "service_unavailable",
88
+ "idempotency_conflict",
89
+ "idempotency_in_progress",
90
+ "cart_not_active",
91
+ "cart_locked",
92
+ "cart_empty",
93
+ "cart_market_unavailable",
94
+ "cart_market_mismatch",
95
+ "checkout_not_open",
96
+ "payment_slot_held",
97
+ "reservation_expired",
98
+ "payment_session_not_cancelable",
99
+ "provider_identity_mismatch",
100
+ "provider_unavailable",
101
+ "lock_timeout",
102
+ "price_changed",
103
+ "pricing_fact_in_use",
104
+ "insufficient_stock",
105
+ "market_not_found",
106
+ "market_shipping_currency_unsupported",
107
+ "missing_market_rate",
108
+ "missing_shipping_amount",
109
+ "no_enabled_payment_provider",
110
+ "product_market_unavailable",
111
+ "unsupported_currency",
112
+ "missing_price_row",
113
+ "payment_provider_currency_unsupported",
114
+ "discount_code_not_found",
115
+ "discount_not_started",
116
+ "discount_expired",
117
+ "discount_usage_limit",
118
+ "discount_per_customer_limit",
119
+ "discount_customer_required",
120
+ "discount_first_order_only",
121
+ "discount_customer_not_eligible",
122
+ "discount_customer_excluded",
123
+ "discount_items_required",
124
+ "discount_product_not_eligible",
125
+ "discount_product_excluded",
126
+ "discount_min_order_amount",
127
+ "discount_currency_scope_required",
128
+ "discount_allocation_method_unsupported",
129
+ "currency_mismatch"
130
+ ];
131
+ var COMMERCE_ERROR_CODE_SET = new Set(
132
+ COMMERCE_ERROR_CODES
133
+ );
134
+ var COMMERCE_ERROR_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
135
+ "error",
136
+ "reason",
137
+ "requestId",
138
+ "retryable",
139
+ "details"
140
+ ]);
141
+ function isPlainRecord(value) {
142
+ return typeof value === "object" && value !== null && !Array.isArray(value);
143
+ }
144
+ function commerceProtocolError(issue, trustedRequestId) {
145
+ return createApiError(
146
+ "Invalid canonical commerce error response.",
147
+ 502,
148
+ { protocol: "commerce-error-envelope", issue },
149
+ "The server returned an incompatible commerce error response.",
150
+ "Verify that the Console commerce contract is deployed before using this SDK version.",
151
+ trustedRequestId
152
+ );
153
+ }
154
+ function parseCommerceErrorEnvelope(body, headerRequestId) {
155
+ if (!isPlainRecord(body)) {
156
+ throw commerceProtocolError("expected_object", headerRequestId);
157
+ }
158
+ if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {
159
+ throw commerceProtocolError("unexpected_field", headerRequestId);
160
+ }
161
+ 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)) {
162
+ throw commerceProtocolError("invalid_field", headerRequestId);
163
+ }
164
+ if (headerRequestId && headerRequestId !== body.requestId) {
165
+ throw commerceProtocolError("request_id_mismatch", headerRequestId);
166
+ }
167
+ return {
168
+ error: body.error,
169
+ reason: body.reason,
170
+ requestId: body.requestId,
171
+ retryable: body.retryable === true,
172
+ ...body.details === void 0 ? {} : { details: body.details }
173
+ };
174
+ }
175
+ function enhanceCommerceError(error, body, headerRequestId) {
176
+ const envelope = parseCommerceErrorEnvelope(body, headerRequestId);
177
+ const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason);
178
+ Object.assign(error, {
179
+ code: envelope.reason,
180
+ kind: "commerce",
181
+ reason: known ? envelope.reason : "unknown_commerce_error",
182
+ ...known ? {} : { rawReason: envelope.reason },
183
+ requestId: envelope.requestId,
184
+ retryable: envelope.retryable,
185
+ details: envelope.details
186
+ });
187
+ return error;
188
+ }
189
+ function isCommerceSDKError(error) {
190
+ if (!(error instanceof SDKError) || error.kind !== "commerce") return false;
191
+ if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
192
+ return false;
193
+ }
194
+ return error.reason === "unknown_commerce_error" ? typeof error.rawReason === "string" : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === void 0;
195
+ }
70
196
  var NetworkError = class extends SDKError {
71
197
  constructor(message, status, details, userMessage, suggestion) {
72
198
  super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
@@ -260,6 +386,7 @@ var NON_RETRYABLE_STATUSES = [400, 401, 403, 404, 409, 422];
260
386
  var SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
261
387
  var DEFAULT_MAX_RETRIES = 3;
262
388
  var STOREFRONT_BROWSER_MAX_RETRIES = 1;
389
+ var MAX_AUTOMATIC_RETRY_AFTER_SECONDS = 5 * 60;
263
390
  function debugLog(debug, type, message, data) {
264
391
  if (!debug) return;
265
392
  const shouldLog = debug === true || type === "request" && debug.logRequests || type === "response" && debug.logResponses || type === "error" && debug.logErrors;
@@ -374,116 +501,129 @@ function attachRequestId(err, id) {
374
501
  }
375
502
  function parseRetryAfter(response) {
376
503
  const raw = response.headers.get("Retry-After");
377
- if (!raw) return void 0;
378
- return parseInt(raw, 10) || void 0;
504
+ if (!raw) return { permitsAutomaticRetry: true };
505
+ const trimmed = raw.trim();
506
+ let seconds;
507
+ if (/^\d+$/.test(trimmed)) {
508
+ seconds = Number(trimmed);
509
+ if (!Number.isSafeInteger(seconds)) {
510
+ return { permitsAutomaticRetry: false };
511
+ }
512
+ } else {
513
+ const retryAt = Date.parse(trimmed);
514
+ if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
515
+ seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
516
+ }
517
+ return {
518
+ seconds,
519
+ permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
520
+ };
379
521
  }
380
- function mapResponseToError(status, parsed, details, requestId, retryAfter) {
522
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
381
523
  const errorDetails = {
382
524
  ...details,
383
525
  ...parsed.errors && { errors: parsed.errors },
384
- ...parsed.body && { body: parsed.body }
526
+ ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
385
527
  };
386
528
  const suggestion = getParsedErrorSuggestion(status, parsed);
529
+ const finalize = (error) => {
530
+ const withRequestId = attachRequestId(error, requestId);
531
+ if (retryAfter !== void 0) {
532
+ Object.assign(withRequestId, { retryAfter });
533
+ }
534
+ return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
535
+ };
387
536
  if (status === 400 || status === 422) {
388
- return attachRequestId(
537
+ return finalize(
389
538
  createValidationError(
390
539
  parsed.errorMessage,
391
540
  errorDetails,
392
541
  parsed.userMessage,
393
542
  suggestion,
394
543
  status
395
- ),
396
- requestId
544
+ )
397
545
  );
398
546
  }
399
547
  if (status === 401) {
400
- return attachRequestId(
548
+ return finalize(
401
549
  createAuthError(
402
550
  parsed.errorMessage,
403
551
  errorDetails,
404
552
  parsed.userMessage,
405
553
  suggestion
406
- ),
407
- requestId
554
+ )
408
555
  );
409
556
  }
410
557
  if (status === 403) {
411
- return attachRequestId(
558
+ return finalize(
412
559
  createPermissionError(
413
560
  parsed.errorMessage,
414
561
  errorDetails,
415
562
  parsed.userMessage,
416
563
  suggestion
417
- ),
418
- requestId
564
+ )
419
565
  );
420
566
  }
421
567
  if (status === 404) {
422
- return attachRequestId(
568
+ return finalize(
423
569
  createNotFoundError(
424
570
  parsed.errorMessage,
425
571
  errorDetails,
426
572
  parsed.userMessage,
427
573
  suggestion
428
- ),
429
- requestId
574
+ )
430
575
  );
431
576
  }
432
577
  if (status === 409) {
433
- return attachRequestId(
578
+ return finalize(
434
579
  createConflictError(
435
580
  parsed.errorMessage,
436
581
  errorDetails,
437
582
  parsed.userMessage,
438
583
  suggestion
439
- ),
440
- requestId
584
+ )
441
585
  );
442
586
  }
443
587
  if (status === 410) {
444
- return attachRequestId(
588
+ return finalize(
445
589
  createGoneError(
446
590
  parsed.errorMessage,
447
591
  errorDetails,
448
592
  parsed.userMessage,
449
593
  suggestion
450
- ),
451
- requestId
594
+ )
452
595
  );
453
596
  }
454
597
  if (status === 429) {
455
- return attachRequestId(
598
+ return finalize(
456
599
  createRateLimitError(
457
600
  parsed.errorMessage,
458
601
  retryAfter,
459
602
  errorDetails,
460
603
  parsed.userMessage,
461
604
  suggestion
462
- ),
463
- requestId
605
+ )
464
606
  );
465
607
  }
466
608
  if (status === 503) {
467
- return attachRequestId(
609
+ return finalize(
468
610
  createServiceUnavailableError(
469
611
  parsed.errorMessage,
470
612
  retryAfter,
471
613
  errorDetails,
472
614
  parsed.userMessage,
473
615
  suggestion
474
- ),
475
- requestId
616
+ )
476
617
  );
477
618
  }
478
- return attachRequestId(
619
+ return finalize(
479
620
  createNetworkError(
480
621
  parsed.errorMessage,
481
622
  status,
482
623
  errorDetails,
483
624
  parsed.userMessage,
484
625
  suggestion
485
- ),
486
- requestId
626
+ )
487
627
  );
488
628
  }
489
629
  async function httpFetch(url, options) {
@@ -496,6 +636,7 @@ async function httpFetch(url, options) {
496
636
  debug,
497
637
  retry,
498
638
  onUnauthorized,
639
+ errorFamily,
499
640
  ...requestInit
500
641
  } = options || {};
501
642
  const baseUrl = resolveApiUrl(apiUrl);
@@ -548,6 +689,8 @@ async function httpFetch(url, options) {
548
689
  headers: redactSensitiveHeaders(response.headers)
549
690
  });
550
691
  if (!response.ok) {
692
+ const parsed = await parseErrorBody(response);
693
+ const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
551
694
  if (isUsageLimitExceededResponse(response)) {
552
695
  const limit = parseInt(
553
696
  response.headers.get("X-Usage-Limit") || "0",
@@ -561,7 +704,7 @@ async function httpFetch(url, options) {
561
704
  response.headers.get("X-Usage-Remaining") || "0",
562
705
  10
563
706
  );
564
- throw attachRequestId(
707
+ const usageError = attachRequestId(
565
708
  createUsageLimitError(
566
709
  `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
567
710
  { limit, current, remaining },
@@ -575,9 +718,9 @@ async function httpFetch(url, options) {
575
718
  ),
576
719
  requestId
577
720
  );
721
+ throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
578
722
  }
579
- const parsed = await parseErrorBody(response);
580
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
723
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
581
724
  hasRetried401 = true;
582
725
  try {
583
726
  const newToken = await onUnauthorized();
@@ -599,13 +742,18 @@ async function httpFetch(url, options) {
599
742
  parsed,
600
743
  details,
601
744
  requestId,
602
- retryAfter
745
+ retryAfter.seconds,
746
+ errorFamily
603
747
  );
604
748
  const method2 = (requestInit.method || "GET").toUpperCase();
605
749
  const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
606
- if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
750
+ const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
751
+ if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
607
752
  lastError = error;
608
- const retryDelay = retryConfig.retryDelay(attempt);
753
+ const retryDelay = Math.max(
754
+ retryConfig.retryDelay(attempt),
755
+ (retryAfter.seconds ?? 0) * 1e3
756
+ );
609
757
  debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
610
758
  await delay(retryDelay);
611
759
  continue;
@@ -675,90 +823,45 @@ async function httpFetch(url, options) {
675
823
  throw lastError ?? new NetworkError("Request failed after retries");
676
824
  }
677
825
 
678
- // src/core/api/endpoints.ts
679
- var COMMERCE_ENDPOINTS = {
680
- orders: {
681
- create: "/api/orders/create",
682
- update: "/api/orders/update",
683
- confirmPayment: "/api/orders/confirm-payment",
684
- byPayment: "/api/orders/by-payment",
685
- cancel: "/api/orders/cancel",
686
- resolveCancelRefund: "/api/orders/resolve-cancel-refund",
687
- checkout: "/api/orders/checkout",
688
- createFulfillment: "/api/orders/create-fulfillment",
689
- updateFulfillment: "/api/orders/update-fulfillment"
690
- },
691
- transactions: {
692
- update: "/api/transactions/update"
693
- },
694
- returns: {
695
- create: "/api/returns/create",
696
- update: "/api/returns/update",
697
- returnRefund: "/api/returns/return-refund"
698
- },
699
- fulfillmentOrders: {
700
- prepare: "/api/fulfillment-orders/prepare-fulfillment-order"
701
- },
702
- fulfillments: {
703
- bulkImport: "/api/fulfillments/bulk-import"
704
- },
705
- carts: {
706
- mine: "/api/carts/mine",
707
- merge: "/api/carts/merge",
708
- addItem: "/api/carts/add-item",
709
- updateItem: "/api/carts/update-item",
710
- removeItem: "/api/carts/remove-item",
711
- applyDiscount: "/api/carts/apply-discount",
712
- removeDiscount: "/api/carts/remove-discount",
713
- clear: "/api/carts/clear"
714
- },
715
- products: {
716
- stockCheck: "/api/products/stock-check",
717
- stockSnapshot: "/api/products/stock",
718
- listingGroups: "/api/products/listing-groups",
719
- listingGroupsCatalog: "/api/products/listing-groups/catalog",
720
- listingGroupsQuery: "/api/products/listing-groups/query",
721
- listingGroupsQueryCatalog: "/api/products/listing-groups/query/catalog",
722
- detail: "/api/products/detail",
723
- detailCatalog: "/api/products/detail/catalog",
724
- upsert: "/api/products/upsert"
725
- }
726
- };
727
- var COMMERCE_ENDPOINT_PATHS = Object.values(
728
- COMMERCE_ENDPOINTS
729
- ).flatMap((group) => Object.values(group));
730
- var MEMBERSHIP_ENDPOINTS = {
731
- subscribe: "/api/memberships/subscribe",
732
- cancel: (id) => `/api/memberships/${id}/cancel`,
733
- me: "/api/memberships/me"
734
- };
735
-
736
826
  // src/core/internal/utils/query-string.ts
737
- function productDetailQuery(params) {
738
- const search = new URLSearchParams();
739
- if ("slug" in params) {
740
- search.set("slug", params.slug);
741
- } else {
742
- search.set("id", params.id);
827
+ function normalizedMarket(value) {
828
+ const market = value?.trim();
829
+ return market || void 0;
830
+ }
831
+ function appendProductLocaleSearchParams(search, options) {
832
+ if (options?.locale) search.set("locale", options.locale);
833
+ if (options?.fallbackLocale !== void 0) {
834
+ search.set(
835
+ "fallbackLocale",
836
+ options.fallbackLocale === false ? "none" : options.fallbackLocale
837
+ );
743
838
  }
744
- return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
745
839
  }
746
- function productDetailCatalogQuery(params) {
840
+ function productDetailSearchParams(params) {
747
841
  const search = new URLSearchParams();
748
842
  if ("slug" in params) {
749
843
  search.set("slug", params.slug);
750
844
  } else {
751
845
  search.set("id", params.id);
752
846
  }
753
- return `${COMMERCE_ENDPOINTS.products.detailCatalog}?${search}`;
847
+ const market = normalizedMarket(params.market);
848
+ if (market) search.set("market", market);
849
+ appendProductLocaleSearchParams(search, params);
850
+ return search.toString();
754
851
  }
755
- function listingGroupsQuery(params) {
756
- return `${COMMERCE_ENDPOINTS.products.listingGroups}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
757
- }
758
- function listingGroupsCatalogQuery(params) {
759
- return `${COMMERCE_ENDPOINTS.products.listingGroupsCatalog}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
852
+ function listingGroupsSearchParams(params) {
853
+ const ids = params.productIds.map(encodeURIComponent).join(",");
854
+ const search = new URLSearchParams();
855
+ const market = normalizedMarket(params.market);
856
+ if (market) search.set("market", market);
857
+ appendProductLocaleSearchParams(search, params);
858
+ const query = search.toString();
859
+ return `ids=${ids}${query ? `&${query}` : ""}`;
760
860
  }
761
861
  function appendListingGroupsQuerySearchParams(search, options) {
862
+ const market = normalizedMarket(options?.market);
863
+ if (market) search.set("market", market);
864
+ appendProductLocaleSearchParams(search, options);
762
865
  if (options?.page != null) search.set("page", String(options.page));
763
866
  if (options?.limit != null) search.set("limit", String(options.limit));
764
867
  if (options?.sort != null) {
@@ -769,20 +872,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
769
872
  search.set("whereJson", JSON.stringify(options.where));
770
873
  }
771
874
  }
772
- function listingGroupsQueryUrl(options) {
875
+ function listingPageSearchParams(options) {
773
876
  const search = new URLSearchParams();
774
877
  appendListingGroupsQuerySearchParams(search, options);
775
- const query = search.toString();
776
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
878
+ return search.toString();
777
879
  }
778
- function listingGroupsQueryCatalogUrl(options) {
779
- const search = new URLSearchParams();
780
- appendListingGroupsQuerySearchParams(search, options);
781
- const query = search.toString();
782
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQueryCatalog}${query ? `?${query}` : ""}`;
783
- }
784
- function stockSnapshotQuery(params) {
785
- return `${COMMERCE_ENDPOINTS.products.stockSnapshot}?variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
880
+ function stockSnapshotSearchParams(params) {
881
+ return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
786
882
  }
787
883
 
788
884
  // src/core/collection/http-client.ts
@@ -825,10 +921,15 @@ var HttpClient = class {
825
921
  throw err;
826
922
  }
827
923
  }
828
- buildUrl(endpoint, options) {
829
- if (!options) return endpoint;
830
- const queryString = (0, import_qs_esm.stringify)(options, { addQueryPrefix: true });
831
- return queryString ? `${endpoint}${queryString}` : endpoint;
924
+ buildUrl(endpoint2, options) {
925
+ if (!options) return endpoint2;
926
+ const { fallbackLocale, ...rest } = options;
927
+ const queryOptions = fallbackLocale === void 0 ? rest : {
928
+ ...rest,
929
+ "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
930
+ };
931
+ const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
932
+ return queryString ? `${endpoint2}${queryString}` : endpoint2;
832
933
  }
833
934
  assertJsonResponse(response) {
834
935
  const contentType = response.headers.get("content-type");
@@ -1019,16 +1120,16 @@ var CollectionQueryBuilder = class {
1019
1120
  * @returns Payload CMS mutation response with doc and message
1020
1121
  */
1021
1122
  async create(data, options) {
1022
- const endpoint = `/api/${String(this.collection)}`;
1123
+ const endpoint2 = `/api/${String(this.collection)}`;
1023
1124
  if (options?.file) {
1024
1125
  return this.api.requestCreateWithFile(
1025
- endpoint,
1126
+ endpoint2,
1026
1127
  data,
1027
1128
  options.file,
1028
1129
  options.filename
1029
1130
  );
1030
1131
  }
1031
- return this.api.requestCreate(endpoint, data);
1132
+ return this.api.requestCreate(endpoint2, data);
1032
1133
  }
1033
1134
  /**
1034
1135
  * Update a document by ID
@@ -1036,16 +1137,16 @@ var CollectionQueryBuilder = class {
1036
1137
  * @returns Payload CMS mutation response with doc and message
1037
1138
  */
1038
1139
  async update(id, data, options) {
1039
- const endpoint = `/api/${String(this.collection)}/${String(id)}`;
1140
+ const endpoint2 = `/api/${String(this.collection)}/${String(id)}`;
1040
1141
  if (options?.file) {
1041
1142
  return this.api.requestUpdateWithFile(
1042
- endpoint,
1143
+ endpoint2,
1043
1144
  data,
1044
1145
  options.file,
1045
1146
  options.filename
1046
1147
  );
1047
1148
  }
1048
- return this.api.requestUpdate(endpoint, data);
1149
+ return this.api.requestUpdate(endpoint2, data);
1049
1150
  }
1050
1151
  /**
1051
1152
  * Count documents
@@ -1141,8 +1242,8 @@ var CollectionClient = class extends HttpClient {
1141
1242
  * Find documents (list query)
1142
1243
  * GET /api/{collection}
1143
1244
  */
1144
- async requestFind(endpoint, options) {
1145
- const url = this.buildUrl(endpoint, options);
1245
+ async requestFind(endpoint2, options) {
1246
+ const url = this.buildUrl(endpoint2, options);
1146
1247
  const response = await this.fetchWithTracking(url, {
1147
1248
  ...this.defaultOptions,
1148
1249
  method: "GET"
@@ -1153,8 +1254,8 @@ var CollectionClient = class extends HttpClient {
1153
1254
  * Find-like response from a custom endpoint
1154
1255
  * POST /api/...custom-endpoint
1155
1256
  */
1156
- async requestFindEndpoint(endpoint, data) {
1157
- const response = await this.fetchWithTracking(endpoint, {
1257
+ async requestFindEndpoint(endpoint2, data) {
1258
+ const response = await this.fetchWithTracking(endpoint2, {
1158
1259
  ...this.defaultOptions,
1159
1260
  method: "POST",
1160
1261
  body: data ? JSON.stringify(data) : void 0
@@ -1164,8 +1265,8 @@ var CollectionClient = class extends HttpClient {
1164
1265
  /**
1165
1266
  * Find-like response from a cacheable GET custom endpoint.
1166
1267
  */
1167
- async requestFindEndpointGet(endpoint) {
1168
- const response = await this.fetchWithTracking(endpoint, {
1268
+ async requestFindEndpointGet(endpoint2) {
1269
+ const response = await this.fetchWithTracking(endpoint2, {
1169
1270
  ...this.defaultOptions,
1170
1271
  method: "GET"
1171
1272
  });
@@ -1175,8 +1276,8 @@ var CollectionClient = class extends HttpClient {
1175
1276
  * Find document by ID
1176
1277
  * GET /api/{collection}/{id}
1177
1278
  */
1178
- async requestFindById(endpoint, options) {
1179
- const url = this.buildUrl(endpoint, options);
1279
+ async requestFindById(endpoint2, options) {
1280
+ const url = this.buildUrl(endpoint2, options);
1180
1281
  const response = await this.fetchWithTracking(url, {
1181
1282
  ...this.defaultOptions,
1182
1283
  method: "GET"
@@ -1187,8 +1288,8 @@ var CollectionClient = class extends HttpClient {
1187
1288
  * Create document
1188
1289
  * POST /api/{collection}
1189
1290
  */
1190
- async requestCreate(endpoint, data) {
1191
- const response = await this.fetchWithTracking(endpoint, {
1291
+ async requestCreate(endpoint2, data) {
1292
+ const response = await this.fetchWithTracking(endpoint2, {
1192
1293
  ...this.defaultOptions,
1193
1294
  method: "POST",
1194
1295
  body: data ? JSON.stringify(data) : void 0
@@ -1199,8 +1300,8 @@ var CollectionClient = class extends HttpClient {
1199
1300
  * Update document
1200
1301
  * PATCH /api/{collection}/{id}
1201
1302
  */
1202
- async requestUpdate(endpoint, data) {
1203
- const response = await this.fetchWithTracking(endpoint, {
1303
+ async requestUpdate(endpoint2, data) {
1304
+ const response = await this.fetchWithTracking(endpoint2, {
1204
1305
  ...this.defaultOptions,
1205
1306
  method: "PATCH",
1206
1307
  body: data ? JSON.stringify(data) : void 0
@@ -1211,8 +1312,8 @@ var CollectionClient = class extends HttpClient {
1211
1312
  * Count documents
1212
1313
  * GET /api/{collection}/count
1213
1314
  */
1214
- async requestCount(endpoint, options) {
1215
- const url = this.buildUrl(endpoint, options);
1315
+ async requestCount(endpoint2, options) {
1316
+ const url = this.buildUrl(endpoint2, options);
1216
1317
  const response = await this.fetchWithTracking(url, {
1217
1318
  ...this.defaultOptions,
1218
1319
  method: "GET"
@@ -1223,8 +1324,8 @@ var CollectionClient = class extends HttpClient {
1223
1324
  * Update multiple documents (bulk update)
1224
1325
  * PATCH /api/{collection}
1225
1326
  */
1226
- async requestUpdateMany(endpoint, data) {
1227
- const response = await this.fetchWithTracking(endpoint, {
1327
+ async requestUpdateMany(endpoint2, data) {
1328
+ const response = await this.fetchWithTracking(endpoint2, {
1228
1329
  ...this.defaultOptions,
1229
1330
  method: "PATCH",
1230
1331
  body: JSON.stringify(data)
@@ -1235,8 +1336,8 @@ var CollectionClient = class extends HttpClient {
1235
1336
  * Delete document
1236
1337
  * DELETE /api/{collection}/{id}
1237
1338
  */
1238
- async requestDelete(endpoint, options) {
1239
- const url = this.buildUrl(endpoint, options);
1339
+ async requestDelete(endpoint2, options) {
1340
+ const url = this.buildUrl(endpoint2, options);
1240
1341
  const response = await this.fetchWithTracking(url, {
1241
1342
  ...this.defaultOptions,
1242
1343
  method: "DELETE"
@@ -1247,8 +1348,8 @@ var CollectionClient = class extends HttpClient {
1247
1348
  * Delete multiple documents (bulk delete)
1248
1349
  * DELETE /api/{collection}
1249
1350
  */
1250
- async requestDeleteMany(endpoint, data) {
1251
- const response = await this.fetchWithTracking(endpoint, {
1351
+ async requestDeleteMany(endpoint2, data) {
1352
+ const response = await this.fetchWithTracking(endpoint2, {
1252
1353
  ...this.defaultOptions,
1253
1354
  method: "DELETE",
1254
1355
  body: JSON.stringify(data)
@@ -1259,8 +1360,8 @@ var CollectionClient = class extends HttpClient {
1259
1360
  * Create document with file upload
1260
1361
  * POST /api/{collection} (multipart/form-data)
1261
1362
  */
1262
- async requestCreateWithFile(endpoint, data, file, filename) {
1263
- const response = await this.fetchWithTracking(endpoint, {
1363
+ async requestCreateWithFile(endpoint2, data, file, filename) {
1364
+ const response = await this.fetchWithTracking(endpoint2, {
1264
1365
  ...this.defaultOptions,
1265
1366
  method: "POST",
1266
1367
  body: buildPayloadFormData(data, file, filename)
@@ -1271,8 +1372,8 @@ var CollectionClient = class extends HttpClient {
1271
1372
  * Update document with file upload
1272
1373
  * PATCH /api/{collection}/{id} (multipart/form-data)
1273
1374
  */
1274
- async requestUpdateWithFile(endpoint, data, file, filename) {
1275
- const response = await this.fetchWithTracking(endpoint, {
1375
+ async requestUpdateWithFile(endpoint2, data, file, filename) {
1376
+ const response = await this.fetchWithTracking(endpoint2, {
1276
1377
  ...this.defaultOptions,
1277
1378
  method: "PATCH",
1278
1379
  body: buildPayloadFormData(data, file, filename)
@@ -1287,53 +1388,339 @@ var ServerCollectionClient = class extends CollectionClient {
1287
1388
  };
1288
1389
 
1289
1390
  // src/core/api/parse-response.ts
1290
- async function parseApiResponse(response, endpoint) {
1291
- let data;
1391
+ async function parseApiResponse(response, endpoint2, options = {}) {
1392
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
1393
+ return void 0;
1394
+ }
1395
+ let parsed;
1292
1396
  try {
1293
- data = await response.json();
1397
+ parsed = await response.json();
1294
1398
  } catch {
1295
1399
  throw createApiError(
1296
- `Invalid JSON response from ${endpoint}`,
1400
+ `Invalid JSON response from ${endpoint2}`,
1297
1401
  response.status,
1298
1402
  void 0,
1299
1403
  "Server returned an invalid response.",
1300
1404
  "Check if the API endpoint is available."
1301
1405
  );
1302
1406
  }
1407
+ if (parsed === null || typeof parsed !== "object") {
1408
+ return parsed;
1409
+ }
1410
+ const data = parsed;
1303
1411
  if (data.error) {
1304
1412
  const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1305
1413
  const reason = typeof data.reason === "string" ? data.reason : void 0;
1306
1414
  const requestId = response.headers.get("x-request-id") ?? void 0;
1307
- const retryAfterRaw = response.headers.get("Retry-After");
1308
- const retryAfter = retryAfterRaw ? parseInt(retryAfterRaw, 10) || void 0 : void 0;
1415
+ const retryAfter = parseRetryAfter(response).seconds;
1416
+ let error;
1309
1417
  if (reason === "validation_failed") {
1310
- throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
1311
- }
1312
- if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1313
- throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
1418
+ error = createValidationError(errorMessage, data, errorMessage);
1419
+ } else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1420
+ error = createAuthError(errorMessage, data, errorMessage);
1421
+ } else if (reason === "forbidden") {
1422
+ error = createPermissionError(errorMessage, data, errorMessage);
1423
+ } else if (reason === "rate_limit_exceeded") {
1424
+ error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
1425
+ } else if (reason === "not_found") {
1426
+ error = createNotFoundError(errorMessage, data, errorMessage);
1427
+ } else if (reason === "conflict") {
1428
+ error = createConflictError(errorMessage, data, errorMessage);
1429
+ } else {
1430
+ error = createApiError(
1431
+ errorMessage,
1432
+ response.status,
1433
+ data,
1434
+ errorMessage,
1435
+ "An error occurred while processing the request."
1436
+ );
1314
1437
  }
1315
- if (reason === "forbidden") {
1316
- throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1438
+ const withRequestId = attachRequestId(error, requestId);
1439
+ if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
1440
+ throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
1441
+ }
1442
+ return data;
1443
+ }
1444
+
1445
+ // ../../internal/http-contracts/src/index.ts
1446
+ var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1447
+ var operation = (collection, method, path) => Object.freeze({
1448
+ [operationBrand]: true,
1449
+ collection,
1450
+ method,
1451
+ path
1452
+ });
1453
+ var COMMERCE_ENDPOINT_OPERATIONS = {
1454
+ products: {
1455
+ detail: operation("products", "get", "/detail"),
1456
+ detailCatalog: operation("products", "get", "/detail/catalog"),
1457
+ listingGroups: operation("products", "get", "/listing-groups"),
1458
+ listingGroupsCatalog: operation(
1459
+ "products",
1460
+ "get",
1461
+ "/listing-groups/catalog"
1462
+ ),
1463
+ listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
1464
+ listingGroupsQueryGet: operation(
1465
+ "products",
1466
+ "get",
1467
+ "/listing-groups/query"
1468
+ ),
1469
+ listingGroupsQueryCatalog: operation(
1470
+ "products",
1471
+ "get",
1472
+ "/listing-groups/query/catalog"
1473
+ ),
1474
+ stockCheck: operation("products", "post", "/stock-check"),
1475
+ stockSnapshot: operation("products", "get", "/stock"),
1476
+ upsert: operation("products", "post", "/upsert")
1477
+ },
1478
+ orders: {
1479
+ create: operation("orders", "post", "/create"),
1480
+ update: operation("orders", "post", "/update"),
1481
+ confirmPayment: operation("orders", "post", "/confirm-payment"),
1482
+ byPayment: operation("orders", "get", "/by-payment"),
1483
+ cancel: operation("orders", "post", "/cancel"),
1484
+ resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1485
+ checkout: operation("orders", "post", "/checkout"),
1486
+ createFulfillment: operation("orders", "post", "/create-fulfillment"),
1487
+ updateFulfillment: operation("orders", "post", "/update-fulfillment")
1488
+ },
1489
+ checkouts: {
1490
+ detail: operation("checkouts", "post", "/detail"),
1491
+ query: operation("checkouts", "post", "/query")
1492
+ },
1493
+ transactions: {
1494
+ update: operation("transactions", "post", "/update")
1495
+ },
1496
+ returns: {
1497
+ create: operation("returns", "post", "/create"),
1498
+ update: operation("returns", "post", "/update"),
1499
+ returnRefund: operation("returns", "post", "/return-refund")
1500
+ },
1501
+ fulfillmentOrders: {
1502
+ prepare: operation(
1503
+ "fulfillment-orders",
1504
+ "post",
1505
+ "/prepare-fulfillment-order"
1506
+ )
1507
+ },
1508
+ fulfillments: {
1509
+ bulkImport: operation("fulfillments", "post", "/bulk-import")
1510
+ },
1511
+ carts: {
1512
+ create: operation("carts", "post", "/create"),
1513
+ retrieve: operation("carts", "post", "/retrieve"),
1514
+ mine: operation("carts", "post", "/mine"),
1515
+ merge: operation("carts", "post", "/merge"),
1516
+ addItem: operation("carts", "post", "/add-item"),
1517
+ updateItem: operation("carts", "post", "/update-item"),
1518
+ removeItem: operation("carts", "post", "/remove-item"),
1519
+ updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
1520
+ updateAttributes: operation("carts", "post", "/update-attributes"),
1521
+ clear: operation("carts", "post", "/clear")
1522
+ },
1523
+ paymentSessions: {
1524
+ create: operation("payment-sessions", "post", "/create"),
1525
+ retrieve: operation("payment-sessions", "post", "/retrieve"),
1526
+ cancel: operation("payment-sessions", "post", "/cancel"),
1527
+ server: {
1528
+ create: operation("payment-sessions", "post", "/server/create"),
1529
+ retrieve: operation("payment-sessions", "post", "/server/retrieve"),
1530
+ cancel: operation("payment-sessions", "post", "/server/cancel"),
1531
+ confirm: operation("payment-sessions", "post", "/server/confirm")
1532
+ },
1533
+ custom: {
1534
+ create: operation("orders", "post", "/custom-payment-sessions"),
1535
+ confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
1317
1536
  }
1318
- if (reason === "rate_limit_exceeded") {
1319
- throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1537
+ },
1538
+ shippingPolicies: {
1539
+ calculate: operation("shipping-policies", "post", "/calculate")
1540
+ },
1541
+ discounts: {
1542
+ validate: operation("discounts", "post", "/validate")
1543
+ }
1544
+ };
1545
+ var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1546
+ subscribe: operation(null, "post", "/memberships/subscribe"),
1547
+ cancel: operation(null, "post", "/memberships/:id/cancel"),
1548
+ me: operation(null, "get", "/memberships/me")
1549
+ };
1550
+ var EVENTS_ENDPOINT_OPERATIONS = {
1551
+ occurrences: {
1552
+ range: operation("event-occurrences", "get", "/range"),
1553
+ admissionAvailability: operation(
1554
+ "event-occurrences",
1555
+ "get",
1556
+ "/admission-availability"
1557
+ )
1558
+ }
1559
+ };
1560
+ function resolveOperationTemplate(descriptor) {
1561
+ return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
1562
+ }
1563
+ function resolveOperationPath(descriptor, options) {
1564
+ const path = resolveOperationTemplate(descriptor).replace(
1565
+ /:([A-Za-z][A-Za-z0-9_]*)/g,
1566
+ (_, key) => {
1567
+ const value = options?.pathParams?.[key];
1568
+ if (value === void 0) {
1569
+ throw new TypeError(`Missing path parameter: ${key}`);
1570
+ }
1571
+ return encodeURIComponent(value);
1320
1572
  }
1321
- if (reason === "not_found") {
1322
- throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1573
+ );
1574
+ const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
1575
+ if (unresolved) {
1576
+ throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
1577
+ }
1578
+ const query = options?.query?.toString().replace(/^\?/, "");
1579
+ return query ? `${path}?${query}` : path;
1580
+ }
1581
+ function resolveOperationMethod(descriptor) {
1582
+ return descriptor.method.toUpperCase();
1583
+ }
1584
+
1585
+ // src/core/api/endpoints.ts
1586
+ var endpoint = (method, path) => ({ method, path });
1587
+ var sharedEndpoint = (descriptor) => descriptor;
1588
+ function resolveOperationMethod2(descriptor) {
1589
+ return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1590
+ }
1591
+ function resolveOperationPath2(descriptor, options) {
1592
+ if ("collection" in descriptor) {
1593
+ return resolveOperationPath(descriptor, options);
1594
+ }
1595
+ const query = options?.query?.toString().replace(/^\?/, "");
1596
+ return query ? `${descriptor.path}?${query}` : descriptor.path;
1597
+ }
1598
+ var COMMERCE_ENDPOINTS = {
1599
+ products: {
1600
+ detail: endpoint("GET", "/api/products/detail"),
1601
+ detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1602
+ listingGroups: endpoint("GET", "/api/products/listing-groups"),
1603
+ listingGroupsCatalog: endpoint(
1604
+ "GET",
1605
+ "/api/products/listing-groups/catalog"
1606
+ ),
1607
+ listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1608
+ listingGroupsQueryCatalog: endpoint(
1609
+ "GET",
1610
+ "/api/products/listing-groups/query/catalog"
1611
+ ),
1612
+ stockCheck: endpoint("POST", "/api/products/stock-check"),
1613
+ stockSnapshot: endpoint("GET", "/api/products/stock"),
1614
+ upsert: endpoint("POST", "/api/products/upsert")
1615
+ },
1616
+ orders: {
1617
+ update: endpoint("POST", "/api/orders/update"),
1618
+ byPayment: endpoint("GET", "/api/orders/by-payment"),
1619
+ cancel: endpoint("POST", "/api/orders/cancel"),
1620
+ resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1621
+ createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1622
+ updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1623
+ },
1624
+ checkouts: {
1625
+ create: endpoint("POST", "/api/orders/checkout"),
1626
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1627
+ server: {
1628
+ create: endpoint("POST", "/api/orders/checkout"),
1629
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1630
+ query: endpoint("POST", "/api/checkouts/query")
1323
1631
  }
1324
- if (reason === "conflict") {
1325
- throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1632
+ },
1633
+ returns: {
1634
+ create: endpoint("POST", "/api/returns/create"),
1635
+ update: endpoint("POST", "/api/returns/update"),
1636
+ returnRefund: endpoint("POST", "/api/returns/return-refund")
1637
+ },
1638
+ fulfillmentOrders: {
1639
+ prepare: endpoint(
1640
+ "POST",
1641
+ "/api/fulfillment-orders/prepare-fulfillment-order"
1642
+ )
1643
+ },
1644
+ fulfillments: {
1645
+ bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1646
+ },
1647
+ carts: {
1648
+ create: endpoint("POST", "/api/carts/create"),
1649
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1650
+ mine: endpoint("POST", "/api/carts/mine"),
1651
+ merge: endpoint("POST", "/api/carts/merge"),
1652
+ server: {
1653
+ // Server credentials are an authorization lane, not a second Cart
1654
+ // transport. These must stay bound to the registered shared operations.
1655
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
1656
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1657
+ mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
1658
+ merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
1659
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1660
+ updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
1661
+ removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
1662
+ updateDiscountCodes: sharedEndpoint(
1663
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
1664
+ ),
1665
+ updateAttributes: sharedEndpoint(
1666
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
1667
+ ),
1668
+ clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
1669
+ },
1670
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1671
+ updateItem: endpoint("POST", "/api/carts/update-item"),
1672
+ removeItem: endpoint("POST", "/api/carts/remove-item"),
1673
+ updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
1674
+ updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
1675
+ clear: endpoint("POST", "/api/carts/clear")
1676
+ },
1677
+ paymentSessions: {
1678
+ create: endpoint("POST", "/api/payment-sessions/create"),
1679
+ retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
1680
+ cancel: endpoint("POST", "/api/payment-sessions/cancel"),
1681
+ server: {
1682
+ create: endpoint("POST", "/api/payment-sessions/server/create"),
1683
+ retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
1684
+ cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
1685
+ confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
1326
1686
  }
1327
- throw attachRequestId(
1328
- createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1329
- requestId
1330
- );
1687
+ },
1688
+ shippingPolicies: {
1689
+ calculate: endpoint("POST", "/api/shipping-policies/calculate")
1331
1690
  }
1332
- return data;
1691
+ };
1692
+ function isCommerceEndpointDescriptor(value) {
1693
+ if (!value || typeof value !== "object") return false;
1694
+ const candidate = value;
1695
+ return typeof candidate.method === "string" && typeof candidate.path === "string";
1696
+ }
1697
+ function flattenEndpointPaths(value) {
1698
+ if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1699
+ if (!value || typeof value !== "object") return [];
1700
+ return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1701
+ }
1702
+ function flattenEndpointDescriptors(value) {
1703
+ if (isCommerceEndpointDescriptor(value)) return [value];
1704
+ if (!value || typeof value !== "object") return [];
1705
+ return Object.values(value).flatMap(
1706
+ (entry) => flattenEndpointDescriptors(entry)
1707
+ );
1333
1708
  }
1709
+ var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1710
+ var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1711
+ var MEMBERSHIP_ENDPOINTS = {
1712
+ subscribe: "/api/memberships/subscribe",
1713
+ cancel: (id) => `/api/memberships/${id}/cancel`,
1714
+ me: "/api/memberships/me"
1715
+ };
1716
+ var MEMBERSHIP_ENDPOINT_PATHS = [
1717
+ MEMBERSHIP_ENDPOINTS.subscribe,
1718
+ MEMBERSHIP_ENDPOINTS.cancel(":id"),
1719
+ MEMBERSHIP_ENDPOINTS.me
1720
+ ];
1334
1721
 
1335
1722
  // src/core/api/customer-scoped-api.ts
1336
- var CustomerScopedApi = class {
1723
+ var CustomerScopedTransport = class {
1337
1724
  constructor(apiName, options) {
1338
1725
  if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
1339
1726
  throw createConfigError(
@@ -1351,10 +1738,10 @@ var CustomerScopedApi = class {
1351
1738
  this.onUnauthorized = options.onUnauthorized;
1352
1739
  this.onRequestId = options.onRequestId;
1353
1740
  }
1354
- async request(endpoint, options) {
1741
+ async request(endpoint2, options) {
1355
1742
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1356
1743
  try {
1357
- const response = await httpFetch(endpoint, {
1744
+ const response = await httpFetch(endpoint2, {
1358
1745
  method: options.method,
1359
1746
  apiUrl: this.apiUrl,
1360
1747
  publishableKey: this.publishableKey,
@@ -1364,10 +1751,13 @@ var CustomerScopedApi = class {
1364
1751
  ...options.body !== void 0 && {
1365
1752
  body: JSON.stringify(options.body)
1366
1753
  },
1367
- ...options.headers && { headers: options.headers }
1754
+ ...options.headers && { headers: options.headers },
1755
+ ...options.errorFamily && { errorFamily: options.errorFamily }
1368
1756
  });
1369
1757
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1370
- return parseApiResponse(response, endpoint);
1758
+ return parseApiResponse(response, endpoint2, {
1759
+ errorFamily: options.errorFamily
1760
+ });
1371
1761
  } catch (err) {
1372
1762
  const id = err instanceof SDKError ? err.requestId ?? null : null;
1373
1763
  this.onRequestId?.(id);
@@ -1375,6 +1765,26 @@ var CustomerScopedApi = class {
1375
1765
  }
1376
1766
  }
1377
1767
  };
1768
+ var CustomerScopedApi = class {
1769
+ constructor(apiName, options) {
1770
+ this.transport = new CustomerScopedTransport(apiName, options);
1771
+ }
1772
+ requestEndpoint(endpoint2, body, options) {
1773
+ return this.transport.request(resolveOperationPath2(endpoint2, options), {
1774
+ method: resolveOperationMethod2(endpoint2),
1775
+ body,
1776
+ headers: options?.headers
1777
+ });
1778
+ }
1779
+ };
1780
+ var RawCustomerScopedApi = class {
1781
+ constructor(apiName, options) {
1782
+ this.transport = new CustomerScopedTransport(apiName, options);
1783
+ }
1784
+ request(endpoint2, options) {
1785
+ return this.transport.request(endpoint2, options);
1786
+ }
1787
+ };
1378
1788
 
1379
1789
  // src/core/community/community-client.ts
1380
1790
  var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
@@ -1385,7 +1795,7 @@ function unwrapPayloadDoc(value) {
1385
1795
  }
1386
1796
  return value;
1387
1797
  }
1388
- var CommunityClient = class extends CustomerScopedApi {
1798
+ var CommunityClient = class extends RawCustomerScopedApi {
1389
1799
  constructor(options) {
1390
1800
  super("CommunityClient", { ...options, requiresCredential: false });
1391
1801
  }
@@ -1429,11 +1839,11 @@ var CommunityClient = class extends CustomerScopedApi {
1429
1839
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1430
1840
  return `/api/comments/public?${urlParams.toString()}`;
1431
1841
  }
1432
- async execute(endpoint, method, body) {
1433
- return this.request(endpoint, { method, body });
1842
+ async execute(endpoint2, method, body) {
1843
+ return this.request(endpoint2, { method, body });
1434
1844
  }
1435
- async executeDoc(endpoint, method, body) {
1436
- const response = await this.execute(endpoint, method, body);
1845
+ async executeDoc(endpoint2, method, body) {
1846
+ const response = await this.execute(endpoint2, method, body);
1437
1847
  return unwrapPayloadDoc(response);
1438
1848
  }
1439
1849
  createPost(params) {
@@ -1668,144 +2078,1366 @@ var CommunityClient = class extends CustomerScopedApi {
1668
2078
  "PATCH",
1669
2079
  body
1670
2080
  );
1671
- }
1672
- };
1673
-
1674
- // src/core/api/base-api.ts
1675
- var BaseApi = class {
1676
- constructor(apiName, options) {
1677
- if (!options.secretKey) {
1678
- throw createConfigError(`secretKey is required for ${apiName}.`);
2081
+ }
2082
+ };
2083
+
2084
+ // src/core/api/base-api.ts
2085
+ var ServerApiTransport = class {
2086
+ constructor(apiName, options) {
2087
+ if (!options.secretKey) {
2088
+ throw createConfigError(`secretKey is required for ${apiName}.`);
2089
+ }
2090
+ this.publishableKey = requirePublishableKeyForSecret(
2091
+ apiName,
2092
+ options.publishableKey,
2093
+ options.secretKey
2094
+ );
2095
+ this.secretKey = options.secretKey;
2096
+ this.apiUrl = options.apiUrl;
2097
+ this.onRequestId = options.onRequestId;
2098
+ }
2099
+ async request(endpoint2, body, options) {
2100
+ const method = options?.method ?? "POST";
2101
+ try {
2102
+ const response = await httpFetch(endpoint2, {
2103
+ method,
2104
+ apiUrl: this.apiUrl,
2105
+ publishableKey: this.publishableKey,
2106
+ secretKey: this.secretKey,
2107
+ ...body !== void 0 && { body: JSON.stringify(body) },
2108
+ ...options?.headers && { headers: options.headers },
2109
+ ...options?.errorFamily && { errorFamily: options.errorFamily }
2110
+ });
2111
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
2112
+ return parseApiResponse(response, endpoint2, {
2113
+ errorFamily: options?.errorFamily
2114
+ });
2115
+ } catch (err) {
2116
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
2117
+ this.onRequestId?.(id);
2118
+ throw err;
2119
+ }
2120
+ }
2121
+ };
2122
+ var BaseApi = class {
2123
+ constructor(apiName, options) {
2124
+ this.transport = new ServerApiTransport(apiName, options);
2125
+ }
2126
+ requestEndpoint(endpoint2, body, options) {
2127
+ return this.transport.request(
2128
+ resolveOperationPath2(endpoint2, options),
2129
+ body,
2130
+ {
2131
+ method: resolveOperationMethod2(endpoint2),
2132
+ headers: options?.headers
2133
+ }
2134
+ );
2135
+ }
2136
+ };
2137
+ var RawBaseApi = class {
2138
+ constructor(apiName, options) {
2139
+ this.transport = new ServerApiTransport(apiName, options);
2140
+ this.publishableKey = requirePublishableKeyForSecret(
2141
+ apiName,
2142
+ options.publishableKey,
2143
+ options.secretKey
2144
+ );
2145
+ this.secretKey = options.secretKey;
2146
+ this.apiUrl = options.apiUrl;
2147
+ this.onRequestId = options.onRequestId;
2148
+ }
2149
+ request(endpoint2, body, options) {
2150
+ return this.transport.request(endpoint2, body, options);
2151
+ }
2152
+ };
2153
+
2154
+ // src/core/community/moderation-api.ts
2155
+ var ModerationApi = class extends RawBaseApi {
2156
+ constructor(options) {
2157
+ super("ModerationApi", options);
2158
+ }
2159
+ banCustomer(params) {
2160
+ return this.request(
2161
+ "/api/community-bans/ban-bearer",
2162
+ params,
2163
+ { method: "POST" }
2164
+ );
2165
+ }
2166
+ unbanCustomer(params) {
2167
+ return this.request(
2168
+ "/api/community-bans/unban-bearer",
2169
+ params,
2170
+ { method: "POST" }
2171
+ );
2172
+ }
2173
+ };
2174
+
2175
+ // src/core/api/canonical-response.ts
2176
+ var CART_STATUSES = ["active", "completed", "abandoned"];
2177
+ var MAX_CART_LINE_QUANTITY = 99;
2178
+ var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
2179
+ var MAX_COMMERCE_ADDRESS_LENGTH = 500;
2180
+ var MAX_COMMERCE_EMAIL_LENGTH = 254;
2181
+ var MAX_COMMERCE_PHONE_LENGTH = 32;
2182
+ var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
2183
+ var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
2184
+ var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
2185
+ var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
2186
+ var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
2187
+ var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
2188
+ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2189
+ var PAYMENT_PROVIDERS = ["toss"];
2190
+ var PAYMENT_PROVIDER_STATUSES = [
2191
+ "requires_payment_method",
2192
+ "requires_action",
2193
+ "requires_confirmation",
2194
+ "initializing",
2195
+ "processing",
2196
+ "authorized",
2197
+ "canceling",
2198
+ "unknown",
2199
+ "captured",
2200
+ "failed",
2201
+ "canceled"
2202
+ ];
2203
+ var PAYMENT_FAILURE_REASONS = [
2204
+ "payment_declined",
2205
+ "authentication_failed",
2206
+ "authorization_expired",
2207
+ "payment_method_unavailable",
2208
+ "provider_terminal_failure",
2209
+ "unknown_provider_terminal_failure"
2210
+ ];
2211
+ var CART_WARNING_CODES = [
2212
+ "DISCOUNT_CODE_NOT_HONOURED",
2213
+ "DISCOUNT_CURRENTLY_INACTIVE",
2214
+ "DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
2215
+ "DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
2216
+ "DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
2217
+ "DISCOUNT_NO_ENTITLED_LINE_ITEMS",
2218
+ "DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
2219
+ "DISCOUNT_NOT_FOUND",
2220
+ "DISCOUNT_PURCHASE_NOT_IN_RANGE",
2221
+ "DISCOUNT_USAGE_LIMIT_REACHED",
2222
+ "MERCHANDISE_NOT_ENOUGH_STOCK",
2223
+ "MERCHANDISE_OUT_OF_STOCK"
2224
+ ];
2225
+ function invalidCanonicalResponse(resource, details) {
2226
+ throw createApiError(
2227
+ `Invalid canonical ${resource} response.`,
2228
+ 502,
2229
+ { resource, ...details },
2230
+ `The server returned an incompatible ${resource} response.`,
2231
+ "Verify that the Console commerce contract is deployed before using this SDK version."
2232
+ );
2233
+ }
2234
+ function fail(resource, path, expected) {
2235
+ invalidCanonicalResponse(resource, { path, expected });
2236
+ }
2237
+ function record(value, resource, path) {
2238
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2239
+ fail(resource, path, "object");
2240
+ }
2241
+ return value;
2242
+ }
2243
+ function exact(value, required, optional, resource, path) {
2244
+ for (const key of required) {
2245
+ if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
2246
+ }
2247
+ const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
2248
+ const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2249
+ if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2250
+ }
2251
+ function string(value, resource, path) {
2252
+ if (typeof value !== "string" || value.length === 0) {
2253
+ fail(resource, path, "non-empty string");
2254
+ }
2255
+ return value;
2256
+ }
2257
+ function boundedString(value, maxLength, resource, path, allowEmpty = false) {
2258
+ if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
2259
+ fail(
2260
+ resource,
2261
+ path,
2262
+ `${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
2263
+ );
2264
+ }
2265
+ return value;
2266
+ }
2267
+ function nullableString(value, resource, path) {
2268
+ if (value !== null && typeof value !== "string") {
2269
+ fail(resource, path, "string or null");
2270
+ }
2271
+ }
2272
+ function cartLineQuantity(value, resource, path) {
2273
+ const quantity = positiveInteger(value, resource, path);
2274
+ if (quantity > MAX_CART_LINE_QUANTITY) {
2275
+ fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
2276
+ }
2277
+ return quantity;
2278
+ }
2279
+ function boolean(value, resource, path) {
2280
+ if (typeof value !== "boolean") fail(resource, path, "boolean");
2281
+ }
2282
+ function safeMinor(value, resource, path) {
2283
+ if (!Number.isSafeInteger(value) || value < 0) {
2284
+ fail(resource, path, "non-negative safe integer");
2285
+ }
2286
+ return value;
2287
+ }
2288
+ function positiveInteger(value, resource, path) {
2289
+ if (!Number.isSafeInteger(value) || value <= 0) {
2290
+ fail(resource, path, "positive safe integer");
2291
+ }
2292
+ return value;
2293
+ }
2294
+ function enumValue(value, values, resource, path) {
2295
+ if (typeof value !== "string" || !values.includes(value)) {
2296
+ fail(resource, path, values.join(" | "));
2297
+ }
2298
+ return value;
2299
+ }
2300
+ function timestamp(value, resource, path) {
2301
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
2302
+ fail(resource, path, "ISO 8601 timestamp with offset");
2303
+ }
2304
+ }
2305
+ function currency(value, resource, path) {
2306
+ if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
2307
+ fail(resource, path, "three-letter uppercase currency code");
2308
+ }
2309
+ }
2310
+ function array(value, resource, path) {
2311
+ if (!Array.isArray(value)) fail(resource, path, "array");
2312
+ return value;
2313
+ }
2314
+ function optionalNullableNumber(value, resource, path) {
2315
+ if (value !== void 0 && value !== null && typeof value !== "number") {
2316
+ fail(resource, path, "number or null");
2317
+ }
2318
+ }
2319
+ function validateMediaSize(value, resource, path) {
2320
+ const item = record(value, resource, path);
2321
+ exact(
2322
+ item,
2323
+ [],
2324
+ ["width", "height", "mimeType", "filename", "url"],
2325
+ resource,
2326
+ path
2327
+ );
2328
+ optionalNullableNumber(item.width, resource, `${path}.width`);
2329
+ optionalNullableNumber(item.height, resource, `${path}.height`);
2330
+ for (const key of ["mimeType", "filename", "url"]) {
2331
+ if (item[key] !== void 0)
2332
+ nullableString(item[key], resource, `${path}.${key}`);
2333
+ }
2334
+ }
2335
+ function validateMedia(value, resource, path) {
2336
+ if (typeof value === "string") return;
2337
+ const media = record(value, resource, path);
2338
+ exact(
2339
+ media,
2340
+ [],
2341
+ ["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
2342
+ resource,
2343
+ path
2344
+ );
2345
+ if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
2346
+ fail(resource, `${path}.id`, "string, number, or null");
2347
+ }
2348
+ for (const key of ["alt", "mimeType", "filename", "url"]) {
2349
+ if (media[key] !== void 0)
2350
+ nullableString(media[key], resource, `${path}.${key}`);
2351
+ }
2352
+ optionalNullableNumber(media.width, resource, `${path}.width`);
2353
+ optionalNullableNumber(media.height, resource, `${path}.height`);
2354
+ if (media.sizes !== void 0) {
2355
+ const sizes = record(media.sizes, resource, `${path}.sizes`);
2356
+ Object.entries(sizes).forEach(
2357
+ ([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
2358
+ );
2359
+ }
2360
+ }
2361
+ function validateReference(value, resource, path) {
2362
+ const ref = record(value, resource, path);
2363
+ exact(ref, ["id", "title", "handle", "image"], [], resource, path);
2364
+ string(ref.id, resource, `${path}.id`);
2365
+ string(ref.title, resource, `${path}.title`);
2366
+ if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
2367
+ if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
2368
+ }
2369
+ function validateAdmission(value, resource, path) {
2370
+ const admission = record(value, resource, path);
2371
+ exact(
2372
+ admission,
2373
+ ["eventId", "occurrenceId", "admissionTypeId"],
2374
+ [],
2375
+ resource,
2376
+ path
2377
+ );
2378
+ string(admission.eventId, resource, `${path}.eventId`);
2379
+ string(admission.occurrenceId, resource, `${path}.occurrenceId`);
2380
+ string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
2381
+ }
2382
+ function compareAdmissions(left, right) {
2383
+ for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
2384
+ if (left[field] < right[field]) return -1;
2385
+ if (left[field] > right[field]) return 1;
2386
+ }
2387
+ return 0;
2388
+ }
2389
+ function validateAdmissions(value, resource, path) {
2390
+ const admissions = array(value, resource, path);
2391
+ if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
2392
+ let prior;
2393
+ admissions.forEach((admission, index) => {
2394
+ validateAdmission(admission, resource, `${path}[${index}]`);
2395
+ const item = admission;
2396
+ const comparison = prior ? compareAdmissions(item, prior) : void 0;
2397
+ if (comparison !== void 0 && comparison <= 0) {
2398
+ fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
2399
+ }
2400
+ prior = item;
2401
+ });
2402
+ }
2403
+ function validateAttributes(value, resource, path) {
2404
+ const attributes = array(value, resource, path);
2405
+ if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
2406
+ const keys = /* @__PURE__ */ new Set();
2407
+ attributes.forEach((value2, index) => {
2408
+ const itemPath = `${path}[${index}]`;
2409
+ const attribute = record(value2, resource, itemPath);
2410
+ exact(attribute, ["key", "value"], [], resource, itemPath);
2411
+ const key = string(attribute.key, resource, `${itemPath}.key`);
2412
+ if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
2413
+ fail(
2414
+ resource,
2415
+ `${itemPath}.key`,
2416
+ "unique, non-reserved key of at most 40 characters"
2417
+ );
2418
+ }
2419
+ keys.add(key);
2420
+ if (typeof attribute.value !== "string" || attribute.value.length > 500) {
2421
+ fail(resource, `${itemPath}.value`, "string of at most 500 characters");
2422
+ }
2423
+ });
2424
+ }
2425
+ function validateCustomer(value, resource, path) {
2426
+ const customer = record(value, resource, path);
2427
+ exact(customer, ["email"], ["name", "phone"], resource, path);
2428
+ const email = boundedString(
2429
+ customer.email,
2430
+ MAX_COMMERCE_EMAIL_LENGTH,
2431
+ resource,
2432
+ `${path}.email`
2433
+ );
2434
+ if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
2435
+ email
2436
+ )) {
2437
+ fail(resource, `${path}.email`, "email address");
2438
+ }
2439
+ if (customer.name !== void 0)
2440
+ boundedString(
2441
+ customer.name,
2442
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2443
+ resource,
2444
+ `${path}.name`
2445
+ );
2446
+ if (customer.phone !== void 0)
2447
+ boundedString(
2448
+ customer.phone,
2449
+ MAX_COMMERCE_PHONE_LENGTH,
2450
+ resource,
2451
+ `${path}.phone`
2452
+ );
2453
+ }
2454
+ function validateShippingAddress(value, resource, path) {
2455
+ const address = record(value, resource, path);
2456
+ exact(
2457
+ address,
2458
+ ["recipientName", "phone", "postalCode", "address", "detailAddress"],
2459
+ ["countryCode", "regionCode", "deliveryMessage"],
2460
+ resource,
2461
+ path
2462
+ );
2463
+ boundedString(
2464
+ address.recipientName,
2465
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2466
+ resource,
2467
+ `${path}.recipientName`
2468
+ );
2469
+ boundedString(
2470
+ address.phone,
2471
+ MAX_COMMERCE_PHONE_LENGTH,
2472
+ resource,
2473
+ `${path}.phone`
2474
+ );
2475
+ boundedString(
2476
+ address.postalCode,
2477
+ MAX_COMMERCE_POSTAL_CODE_LENGTH,
2478
+ resource,
2479
+ `${path}.postalCode`
2480
+ );
2481
+ for (const key of ["address", "detailAddress"]) {
2482
+ boundedString(
2483
+ address[key],
2484
+ MAX_COMMERCE_ADDRESS_LENGTH,
2485
+ resource,
2486
+ `${path}.${key}`
2487
+ );
2488
+ }
2489
+ if (address.countryCode !== void 0) {
2490
+ if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
2491
+ fail(resource, `${path}.countryCode`, "two-letter country code");
2492
+ }
2493
+ }
2494
+ if (address.regionCode !== void 0) {
2495
+ if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
2496
+ fail(
2497
+ resource,
2498
+ `${path}.regionCode`,
2499
+ "trimmed string of at most 64 characters"
2500
+ );
2501
+ }
2502
+ }
2503
+ if (address.deliveryMessage !== void 0) {
2504
+ boundedString(
2505
+ address.deliveryMessage,
2506
+ MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
2507
+ resource,
2508
+ `${path}.deliveryMessage`,
2509
+ true
2510
+ );
2511
+ }
2512
+ }
2513
+ function validateOrderReference(value, resource, path) {
2514
+ const order = record(value, resource, path);
2515
+ exact(order, ["id", "orderNumber"], [], resource, path);
2516
+ string(order.id, resource, `${path}.id`);
2517
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2518
+ }
2519
+ function validateIntegrationMetadata(value, resource, path) {
2520
+ const metadata = record(value, resource, path);
2521
+ if (Object.keys(metadata).length > 50)
2522
+ fail(resource, path, "at most 50 entries");
2523
+ Object.entries(metadata).forEach(([key, entry]) => {
2524
+ if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
2525
+ fail(resource, `${path}.${key}`, "valid metadata key");
2526
+ }
2527
+ if (typeof entry !== "string" || entry.length > 500) {
2528
+ fail(resource, `${path}.${key}`, "string of at most 500 characters");
2529
+ }
2530
+ });
2531
+ }
2532
+ function validateCartItem(value, resource, path) {
2533
+ const item = record(value, resource, path);
2534
+ exact(
2535
+ item,
2536
+ [
2537
+ "id",
2538
+ "product",
2539
+ "variant",
2540
+ "admissions",
2541
+ "quantity",
2542
+ "unitPriceMinor",
2543
+ "discountMinor",
2544
+ "estimatedLineTotalMinor",
2545
+ "requiresShipping"
2546
+ ],
2547
+ [],
2548
+ resource,
2549
+ path
2550
+ );
2551
+ string(item.id, resource, `${path}.id`);
2552
+ validateReference(item.product, resource, `${path}.product`);
2553
+ validateReference(item.variant, resource, `${path}.variant`);
2554
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2555
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2556
+ const unitPrice = safeMinor(
2557
+ item.unitPriceMinor,
2558
+ resource,
2559
+ `${path}.unitPriceMinor`
2560
+ );
2561
+ const discount = safeMinor(
2562
+ item.discountMinor,
2563
+ resource,
2564
+ `${path}.discountMinor`
2565
+ );
2566
+ const estimatedLineTotal = safeMinor(
2567
+ item.estimatedLineTotalMinor,
2568
+ resource,
2569
+ `${path}.estimatedLineTotalMinor`
2570
+ );
2571
+ const quantity = item.quantity;
2572
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2573
+ if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
2574
+ fail(
2575
+ resource,
2576
+ `${path}.estimatedLineTotalMinor`,
2577
+ "unitPriceMinor * quantity - discountMinor"
2578
+ );
2579
+ }
2580
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2581
+ }
2582
+ function validatePublicCart(value, resource = "Cart") {
2583
+ const cart = record(value, resource, "$");
2584
+ exact(
2585
+ cart,
2586
+ [
2587
+ "id",
2588
+ "status",
2589
+ "revision",
2590
+ "currency",
2591
+ "market",
2592
+ "subtotalMinor",
2593
+ "discountMinor",
2594
+ "estimatedTotalMinor",
2595
+ "discountCodes",
2596
+ "attributes",
2597
+ "items",
2598
+ "expiresAt",
2599
+ "createdAt",
2600
+ "updatedAt"
2601
+ ],
2602
+ [],
2603
+ resource,
2604
+ "$"
2605
+ );
2606
+ string(cart.id, resource, "$.id");
2607
+ enumValue(cart.status, CART_STATUSES, resource, "$.status");
2608
+ safeMinor(cart.revision, resource, "$.revision");
2609
+ currency(cart.currency, resource, "$.currency");
2610
+ const market = record(cart.market, resource, "$.market");
2611
+ exact(market, ["id", "handle", "name"], [], resource, "$.market");
2612
+ for (const key of ["id", "handle", "name"])
2613
+ string(market[key], resource, `$.market.${key}`);
2614
+ const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
2615
+ const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
2616
+ const estimatedTotal = safeMinor(
2617
+ cart.estimatedTotalMinor,
2618
+ resource,
2619
+ "$.estimatedTotalMinor"
2620
+ );
2621
+ array(cart.discountCodes, resource, "$.discountCodes").forEach(
2622
+ (value2, index) => {
2623
+ const itemPath = `$.discountCodes[${index}]`;
2624
+ const code = record(value2, resource, itemPath);
2625
+ exact(code, ["code", "applicable"], [], resource, itemPath);
2626
+ boundedString(
2627
+ code.code,
2628
+ MAX_CART_DISCOUNT_CODE_LENGTH,
2629
+ resource,
2630
+ `${itemPath}.code`
2631
+ );
2632
+ boolean(code.applicable, resource, `${itemPath}.applicable`);
2633
+ }
2634
+ );
2635
+ validateAttributes(cart.attributes, resource, "$.attributes");
2636
+ const items = array(cart.items, resource, "$.items");
2637
+ items.forEach(
2638
+ (item, index) => validateCartItem(item, resource, `$.items[${index}]`)
2639
+ );
2640
+ const expectedSubtotal = items.reduce((total, value2) => {
2641
+ const item = value2;
2642
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2643
+ }, 0n);
2644
+ const expectedDiscount = items.reduce((total, value2) => {
2645
+ const item = value2;
2646
+ return total + BigInt(item.discountMinor);
2647
+ }, 0n);
2648
+ if (BigInt(subtotal) !== expectedSubtotal) {
2649
+ fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
2650
+ }
2651
+ if (BigInt(discount) !== expectedDiscount) {
2652
+ fail(resource, "$.discountMinor", "sum of cart line discounts");
2653
+ }
2654
+ if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
2655
+ fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
2656
+ }
2657
+ timestamp(cart.expiresAt, resource, "$.expiresAt");
2658
+ timestamp(cart.createdAt, resource, "$.createdAt");
2659
+ timestamp(cart.updatedAt, resource, "$.updatedAt");
2660
+ return value;
2661
+ }
2662
+ function validateWarnings(value, resource, path) {
2663
+ array(value, resource, path).forEach((value2, index) => {
2664
+ const itemPath = `${path}[${index}]`;
2665
+ const warning = record(value2, resource, itemPath);
2666
+ exact(warning, ["code", "message", "target"], [], resource, itemPath);
2667
+ enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
2668
+ string(warning.message, resource, `${itemPath}.message`);
2669
+ string(warning.target, resource, `${itemPath}.target`);
2670
+ });
2671
+ }
2672
+ function validateCartMutationResult(value) {
2673
+ const result = record(value, "Cart mutation result", "$");
2674
+ exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
2675
+ validatePublicCart(result.cart);
2676
+ validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
2677
+ return value;
2678
+ }
2679
+ function validateCreateCartResult(value) {
2680
+ const result = record(value, "Cart create result", "$");
2681
+ exact(
2682
+ result,
2683
+ ["cart", "warnings", "cartToken"],
2684
+ [],
2685
+ "Cart create result",
2686
+ "$"
2687
+ );
2688
+ const cart = record(result.cart, "Cart create result", "$.cart");
2689
+ validatePublicCart(cart);
2690
+ if (cart.revision !== 0) {
2691
+ fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
2692
+ }
2693
+ validateWarnings(result.warnings, "Cart create result", "$.warnings");
2694
+ boundedString(
2695
+ result.cartToken,
2696
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2697
+ "Cart create result",
2698
+ "$.cartToken"
2699
+ );
2700
+ return value;
2701
+ }
2702
+ function validateCartMineResult(value) {
2703
+ const result = record(value, "Cart mine result", "$");
2704
+ exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
2705
+ if (result.cart === null || result.cartToken === null) {
2706
+ if (result.cart !== null || result.cartToken !== null) {
2707
+ fail("Cart mine result", "$", "cart and cartToken must both be null");
2708
+ }
2709
+ } else {
2710
+ validatePublicCart(result.cart);
2711
+ boundedString(
2712
+ result.cartToken,
2713
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2714
+ "Cart mine result",
2715
+ "$.cartToken"
2716
+ );
2717
+ }
2718
+ return value;
2719
+ }
2720
+ function validateCartMergeResult(value) {
2721
+ const result = record(value, "Cart merge result", "$");
2722
+ exact(
2723
+ result,
2724
+ ["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
2725
+ [],
2726
+ "Cart merge result",
2727
+ "$"
2728
+ );
2729
+ validatePublicCart(result.cart);
2730
+ validateWarnings(result.warnings, "Cart merge result", "$.warnings");
2731
+ boundedString(
2732
+ result.cartToken,
2733
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2734
+ "Cart merge result",
2735
+ "$.cartToken"
2736
+ );
2737
+ const resolution = enumValue(
2738
+ result.resolution,
2739
+ ["unchanged", "claimed", "merged"],
2740
+ "Cart merge result",
2741
+ "$.resolution"
2742
+ );
2743
+ boolean(result.merged, "Cart merge result", "$.merged");
2744
+ boolean(result.claimed, "Cart merge result", "$.claimed");
2745
+ const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
2746
+ if (result.merged !== expected[0] || result.claimed !== expected[1]) {
2747
+ fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
2748
+ }
2749
+ return value;
2750
+ }
2751
+ function validateCheckoutItem(value, resource, path) {
2752
+ const item = record(value, resource, path);
2753
+ exact(
2754
+ item,
2755
+ [
2756
+ "id",
2757
+ "product",
2758
+ "variant",
2759
+ "productTitle",
2760
+ "variantTitle",
2761
+ "sku",
2762
+ "admissions",
2763
+ "quantity",
2764
+ "unitPriceMinor",
2765
+ "discountMinor",
2766
+ "lineTotalMinor",
2767
+ "requiresShipping"
2768
+ ],
2769
+ [],
2770
+ resource,
2771
+ path
2772
+ );
2773
+ string(item.id, resource, `${path}.id`);
2774
+ validateReference(item.product, resource, `${path}.product`);
2775
+ validateReference(item.variant, resource, `${path}.variant`);
2776
+ string(item.productTitle, resource, `${path}.productTitle`);
2777
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2778
+ nullableString(item.sku, resource, `${path}.sku`);
2779
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2780
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2781
+ const unitPrice = safeMinor(
2782
+ item.unitPriceMinor,
2783
+ resource,
2784
+ `${path}.unitPriceMinor`
2785
+ );
2786
+ const discount = safeMinor(
2787
+ item.discountMinor,
2788
+ resource,
2789
+ `${path}.discountMinor`
2790
+ );
2791
+ const lineTotal = safeMinor(
2792
+ item.lineTotalMinor,
2793
+ resource,
2794
+ `${path}.lineTotalMinor`
2795
+ );
2796
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
2797
+ if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
2798
+ fail(
2799
+ resource,
2800
+ `${path}.lineTotalMinor`,
2801
+ "unitPriceMinor * quantity - discountMinor"
2802
+ );
2803
+ }
2804
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2805
+ }
2806
+ function validateCheckoutAmounts(value, resource, path) {
2807
+ const amounts = record(value, resource, path);
2808
+ exact(
2809
+ amounts,
2810
+ [
2811
+ "currency",
2812
+ "subtotalMinor",
2813
+ "shippingMinor",
2814
+ "discountMinor",
2815
+ "totalMinor"
2816
+ ],
2817
+ [],
2818
+ resource,
2819
+ path
2820
+ );
2821
+ currency(amounts.currency, resource, `${path}.currency`);
2822
+ const subtotal = safeMinor(
2823
+ amounts.subtotalMinor,
2824
+ resource,
2825
+ `${path}.subtotalMinor`
2826
+ );
2827
+ const shipping = safeMinor(
2828
+ amounts.shippingMinor,
2829
+ resource,
2830
+ `${path}.shippingMinor`
2831
+ );
2832
+ const discount = safeMinor(
2833
+ amounts.discountMinor,
2834
+ resource,
2835
+ `${path}.discountMinor`
2836
+ );
2837
+ const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
2838
+ if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
2839
+ fail(
2840
+ resource,
2841
+ `${path}.totalMinor`,
2842
+ "subtotalMinor + shippingMinor - discountMinor"
2843
+ );
2844
+ }
2845
+ }
2846
+ function validatePaymentSessionReference(value, resource, path) {
2847
+ const session = record(value, resource, path);
2848
+ exact(session, ["id", "provider", "providerStatus"], [], resource, path);
2849
+ string(session.id, resource, `${path}.id`);
2850
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
2851
+ enumValue(
2852
+ session.providerStatus,
2853
+ PAYMENT_PROVIDER_STATUSES,
2854
+ resource,
2855
+ `${path}.providerStatus`
2856
+ );
2857
+ }
2858
+ function checkoutVariantKeys(status, placedVia) {
2859
+ const base = [
2860
+ "id",
2861
+ "amounts",
2862
+ "items",
2863
+ "customerSnapshot",
2864
+ "shippingAddress",
2865
+ "attributes",
2866
+ "expiresAt",
2867
+ "createdAt",
2868
+ "updatedAt",
2869
+ "status",
2870
+ "paymentState",
2871
+ "order"
2872
+ ];
2873
+ if (status === "open") return { required: base, optional: [] };
2874
+ if (status === "abandoned") {
2875
+ return {
2876
+ required: [...base, "abandonedAt", "abandonedReason"],
2877
+ optional: []
2878
+ };
2879
+ }
2880
+ return placedVia === "late_capture" ? {
2881
+ required: [
2882
+ ...base,
2883
+ "placedAt",
2884
+ "placedVia",
2885
+ "abandonedAt",
2886
+ "abandonedReason"
2887
+ ],
2888
+ optional: []
2889
+ } : { required: [...base, "placedAt"], optional: [] };
2890
+ }
2891
+ function validateCheckoutCore(value, resource, list, server) {
2892
+ const checkout = record(value, resource, "$");
2893
+ const status = enumValue(
2894
+ checkout.status,
2895
+ CHECKOUT_STATUSES,
2896
+ resource,
2897
+ "$.status"
2898
+ );
2899
+ const keys = checkoutVariantKeys(status, checkout.placedVia);
2900
+ if (list) {
2901
+ keys.required = keys.required.filter(
2902
+ (key) => !["items", "shippingAddress", "attributes"].includes(key)
2903
+ );
2904
+ keys.required.push("clientReferenceId");
2905
+ } else if (server) {
2906
+ keys.required.push("clientReferenceId", "integrationMetadata");
2907
+ }
2908
+ exact(checkout, keys.required, keys.optional, resource, "$");
2909
+ string(checkout.id, resource, "$.id");
2910
+ validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
2911
+ if (!list) {
2912
+ const items = array(checkout.items, resource, "$.items");
2913
+ if (items.length === 0) fail(resource, "$.items", "non-empty array");
2914
+ items.forEach(
2915
+ (item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
2916
+ );
2917
+ const expectedSubtotal = items.reduce((total, value2) => {
2918
+ const item = value2;
2919
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2920
+ }, 0n);
2921
+ const expectedDiscount = items.reduce((total, value2) => {
2922
+ const item = value2;
2923
+ return total + BigInt(item.discountMinor);
2924
+ }, 0n);
2925
+ const amounts = checkout.amounts;
2926
+ if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
2927
+ fail(
2928
+ resource,
2929
+ "$.amounts.subtotalMinor",
2930
+ "sum of undiscounted checkout line totals"
2931
+ );
2932
+ }
2933
+ if (BigInt(amounts.discountMinor) !== expectedDiscount) {
2934
+ fail(
2935
+ resource,
2936
+ "$.amounts.discountMinor",
2937
+ "sum of checkout line discounts"
2938
+ );
2939
+ }
2940
+ if (checkout.shippingAddress !== null) {
2941
+ validateShippingAddress(
2942
+ checkout.shippingAddress,
2943
+ resource,
2944
+ "$.shippingAddress"
2945
+ );
2946
+ }
2947
+ validateAttributes(checkout.attributes, resource, "$.attributes");
2948
+ }
2949
+ validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
2950
+ timestamp(checkout.expiresAt, resource, "$.expiresAt");
2951
+ timestamp(checkout.createdAt, resource, "$.createdAt");
2952
+ timestamp(checkout.updatedAt, resource, "$.updatedAt");
2953
+ const paymentState = record(checkout.paymentState, resource, "$.paymentState");
2954
+ exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
2955
+ if (status === "open") {
2956
+ if (paymentState.activePaymentSession !== null) {
2957
+ validatePaymentSessionReference(
2958
+ paymentState.activePaymentSession,
2959
+ resource,
2960
+ "$.paymentState.activePaymentSession"
2961
+ );
2962
+ }
2963
+ if (checkout.order !== null)
2964
+ fail(resource, "$.order", "null for open Checkout");
2965
+ } else {
2966
+ if (paymentState.activePaymentSession !== null) {
2967
+ fail(
2968
+ resource,
2969
+ "$.paymentState.activePaymentSession",
2970
+ "null for spent Checkout"
2971
+ );
2972
+ }
2973
+ if (status === "placed") {
2974
+ timestamp(checkout.placedAt, resource, "$.placedAt");
2975
+ validateOrderReference(checkout.order, resource, "$.order");
2976
+ if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
2977
+ fail(resource, "$.placedVia", "late_capture");
2978
+ }
2979
+ if (checkout.placedVia === "late_capture") {
2980
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2981
+ enumValue(
2982
+ checkout.abandonedReason,
2983
+ ABANDONED_REASONS,
2984
+ resource,
2985
+ "$.abandonedReason"
2986
+ );
2987
+ }
2988
+ } else {
2989
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2990
+ enumValue(
2991
+ checkout.abandonedReason,
2992
+ ABANDONED_REASONS,
2993
+ resource,
2994
+ "$.abandonedReason"
2995
+ );
2996
+ if (checkout.order !== null)
2997
+ fail(resource, "$.order", "null for abandoned Checkout");
2998
+ }
2999
+ }
3000
+ if (list || server) {
3001
+ if (checkout.clientReferenceId !== null) {
3002
+ boundedString(
3003
+ checkout.clientReferenceId,
3004
+ MAX_COMMERCE_RESOURCE_ID_LENGTH,
3005
+ resource,
3006
+ "$.clientReferenceId"
3007
+ );
3008
+ }
3009
+ }
3010
+ if (server)
3011
+ validateIntegrationMetadata(
3012
+ checkout.integrationMetadata,
3013
+ resource,
3014
+ "$.integrationMetadata"
3015
+ );
3016
+ }
3017
+ function validatePublicCheckout(value) {
3018
+ validateCheckoutCore(value, "Checkout", false, false);
3019
+ return value;
3020
+ }
3021
+ function validateServerCheckout(value) {
3022
+ validateCheckoutCore(value, "Server Checkout", false, true);
3023
+ return value;
3024
+ }
3025
+ function validateCreateCheckoutResult(value, server) {
3026
+ const resource = server ? "Server Checkout create result" : "Checkout create result";
3027
+ const result = record(value, resource, "$");
3028
+ exact(result, ["checkout", "checkoutToken"], [], resource, "$");
3029
+ if (server) validateServerCheckout(result.checkout);
3030
+ else validatePublicCheckout(result.checkout);
3031
+ boundedString(
3032
+ result.checkoutToken,
3033
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3034
+ resource,
3035
+ "$.checkoutToken"
3036
+ );
3037
+ return value;
3038
+ }
3039
+ function validateCheckoutQueryResult(value) {
3040
+ const result = record(value, "Checkout query result", "$");
3041
+ exact(
3042
+ result,
3043
+ ["data", "hasMore", "nextCursor"],
3044
+ [],
3045
+ "Checkout query result",
3046
+ "$"
3047
+ );
3048
+ array(result.data, "Checkout query result", "$.data").forEach(
3049
+ (item) => validateCheckoutCore(item, "Checkout list item", true, false)
3050
+ );
3051
+ boolean(result.hasMore, "Checkout query result", "$.hasMore");
3052
+ if (result.nextCursor !== null)
3053
+ boundedString(
3054
+ result.nextCursor,
3055
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3056
+ "Checkout query result",
3057
+ "$.nextCursor"
3058
+ );
3059
+ if (result.hasMore === true && result.nextCursor === null) {
3060
+ fail(
3061
+ "Checkout query result",
3062
+ "$.nextCursor",
3063
+ "non-null when hasMore is true"
3064
+ );
3065
+ }
3066
+ return value;
3067
+ }
3068
+ function validateMoney(value, resource, path) {
3069
+ const money = record(value, resource, path);
3070
+ exact(money, ["amountMinor", "currency"], [], resource, path);
3071
+ safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3072
+ currency(money.currency, resource, `${path}.currency`);
3073
+ }
3074
+ function validateCaptureEvidence(value, resource, path) {
3075
+ const evidence = record(value, resource, path);
3076
+ exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
3077
+ safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
3078
+ currency(evidence.currency, resource, `${path}.currency`);
3079
+ timestamp(evidence.observedAt, resource, `${path}.observedAt`);
3080
+ }
3081
+ function validateNoReconciliation(value, resource, path) {
3082
+ const reconciliation = record(value, resource, path);
3083
+ exact(reconciliation, ["status"], [], resource, path);
3084
+ if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
3085
+ }
3086
+ function validateRequiredReconciliation(value, allowed, resource, path) {
3087
+ const reconciliation = record(value, resource, path);
3088
+ exact(reconciliation, ["status", "reasons"], [], resource, path);
3089
+ if (reconciliation.status !== "required")
3090
+ fail(resource, `${path}.status`, "required");
3091
+ const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
3092
+ if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
3093
+ let previous = -1;
3094
+ reasons.forEach((reason, index) => {
3095
+ const current = allowed.indexOf(reason);
3096
+ if (current < 0 || current <= previous) {
3097
+ fail(
3098
+ resource,
3099
+ `${path}.reasons[${index}]`,
3100
+ "unique canonical-sorted reconciliation reason"
3101
+ );
3102
+ }
3103
+ previous = current;
3104
+ });
3105
+ }
3106
+ function validateNextAction(value, resource, path) {
3107
+ const action = record(value, resource, path);
3108
+ exact(
3109
+ action,
3110
+ [
3111
+ "type",
3112
+ "clientKey",
3113
+ "paymentMethodVariantKey",
3114
+ "agreementVariantKey",
3115
+ "providerOrderId",
3116
+ "providerCustomerKey",
3117
+ "orderName"
3118
+ ],
3119
+ ["customerName", "customerEmail"],
3120
+ resource,
3121
+ path
3122
+ );
3123
+ if (action.type !== "toss_widget")
3124
+ fail(resource, `${path}.type`, "toss_widget");
3125
+ for (const key of [
3126
+ "clientKey",
3127
+ "paymentMethodVariantKey",
3128
+ "agreementVariantKey"
3129
+ ]) {
3130
+ boundedString(action[key], 255, resource, `${path}.${key}`);
3131
+ }
3132
+ string(action.providerOrderId, resource, `${path}.providerOrderId`);
3133
+ string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
3134
+ boundedString(
3135
+ action.orderName,
3136
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3137
+ resource,
3138
+ `${path}.orderName`
3139
+ );
3140
+ if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
3141
+ fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
3142
+ }
3143
+ 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(
3144
+ action.providerCustomerKey
3145
+ )) {
3146
+ fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
3147
+ }
3148
+ if (action.customerName !== void 0)
3149
+ boundedString(
3150
+ action.customerName,
3151
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3152
+ resource,
3153
+ `${path}.customerName`
3154
+ );
3155
+ if (action.customerEmail !== void 0)
3156
+ validateCustomer({ email: action.customerEmail }, resource, path);
3157
+ }
3158
+ function validatePublicPaymentSession(value) {
3159
+ const resource = "PaymentSession";
3160
+ const session = record(value, resource, "$");
3161
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
3162
+ const status = enumValue(
3163
+ session.providerStatus,
3164
+ PAYMENT_PROVIDER_STATUSES,
3165
+ resource,
3166
+ "$.providerStatus"
3167
+ );
3168
+ const common = [
3169
+ "id",
3170
+ "money",
3171
+ "expiresAt",
3172
+ "sessionRole",
3173
+ "provider",
3174
+ "providerStatus",
3175
+ "presentationStatus",
3176
+ "finalizationStatus",
3177
+ "reconciliation",
3178
+ "order"
3179
+ ];
3180
+ const optional = [];
3181
+ if (status === "requires_payment_method" || status === "requires_action")
3182
+ optional.push("nextAction");
3183
+ else if (status === "captured") common.push("providerEvidence");
3184
+ else if (status === "failed") common.push("failure");
3185
+ else if (status === "canceled") common.push("cancellationReason");
3186
+ exact(session, common, optional, resource, "$");
3187
+ string(session.id, resource, "$.id");
3188
+ validateMoney(session.money, resource, "$.money");
3189
+ if (session.expiresAt !== null)
3190
+ timestamp(session.expiresAt, resource, "$.expiresAt");
3191
+ if (status === "requires_payment_method" || status === "requires_action") {
3192
+ if (session.sessionRole === "active") {
3193
+ if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
3194
+ fail(resource, "$", "actionable active not-ready state");
3195
+ }
3196
+ if (!("nextAction" in session))
3197
+ fail(resource, "$.nextAction", "required field");
3198
+ validateNextAction(session.nextAction, resource, "$.nextAction");
3199
+ } else if (session.sessionRole === "residual") {
3200
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3201
+ fail(resource, "$", "suppressed residual not-ready state");
3202
+ }
3203
+ if ("nextAction" in session)
3204
+ fail(resource, "$.nextAction", "absent for suppressed state");
3205
+ } else fail(resource, "$.sessionRole", "active | residual");
3206
+ validateNoReconciliation(
3207
+ session.reconciliation,
3208
+ resource,
3209
+ "$.reconciliation"
3210
+ );
3211
+ if (session.order !== null) fail(resource, "$.order", "null");
3212
+ } else if ([
3213
+ "requires_confirmation",
3214
+ "initializing",
3215
+ "processing",
3216
+ "authorized",
3217
+ "canceling"
3218
+ ].includes(status)) {
3219
+ enumValue(
3220
+ session.sessionRole,
3221
+ ["active", "residual"],
3222
+ resource,
3223
+ "$.sessionRole"
3224
+ );
3225
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3226
+ fail(resource, "$", "suppressed not-ready state");
1679
3227
  }
1680
- this.publishableKey = requirePublishableKeyForSecret(
1681
- apiName,
1682
- options.publishableKey,
1683
- options.secretKey
3228
+ validateNoReconciliation(
3229
+ session.reconciliation,
3230
+ resource,
3231
+ "$.reconciliation"
1684
3232
  );
1685
- this.secretKey = options.secretKey;
1686
- this.apiUrl = options.apiUrl;
1687
- this.onRequestId = options.onRequestId;
1688
- }
1689
- async request(endpoint, body, options) {
1690
- const method = options?.method ?? "POST";
1691
- try {
1692
- const response = await httpFetch(endpoint, {
1693
- method,
1694
- apiUrl: this.apiUrl,
1695
- publishableKey: this.publishableKey,
1696
- secretKey: this.secretKey,
1697
- ...body !== void 0 && { body: JSON.stringify(body) },
1698
- ...options?.headers && { headers: options.headers }
1699
- });
1700
- this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1701
- return parseApiResponse(response, endpoint);
1702
- } catch (err) {
1703
- const id = err instanceof SDKError ? err.requestId ?? null : null;
1704
- this.onRequestId?.(id);
1705
- throw err;
3233
+ if (session.order !== null) fail(resource, "$.order", "null");
3234
+ } else if (status === "unknown") {
3235
+ enumValue(
3236
+ session.sessionRole,
3237
+ ["active", "residual"],
3238
+ resource,
3239
+ "$.sessionRole"
3240
+ );
3241
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3242
+ fail(resource, "$", "suppressed not-ready state");
1706
3243
  }
1707
- }
1708
- };
1709
-
1710
- // src/core/community/moderation-api.ts
1711
- var ModerationApi = class extends BaseApi {
1712
- constructor(options) {
1713
- super("ModerationApi", options);
1714
- }
1715
- banCustomer(params) {
1716
- return this.request(
1717
- "/api/community-bans/ban-bearer",
1718
- params,
1719
- { method: "POST" }
3244
+ validateRequiredReconciliation(
3245
+ session.reconciliation,
3246
+ ["provider_outcome_unknown"],
3247
+ resource,
3248
+ "$.reconciliation"
1720
3249
  );
1721
- }
1722
- unbanCustomer(params) {
1723
- return this.request(
1724
- "/api/community-bans/unban-bearer",
1725
- params,
1726
- { method: "POST" }
3250
+ if (session.order !== null) fail(resource, "$.order", "null");
3251
+ } else if (status === "captured") {
3252
+ validateCaptureEvidence(
3253
+ session.providerEvidence,
3254
+ resource,
3255
+ "$.providerEvidence"
3256
+ );
3257
+ if (session.presentationStatus !== "suppressed")
3258
+ fail(resource, "$.presentationStatus", "suppressed");
3259
+ if (session.finalizationStatus === "pending") {
3260
+ enumValue(
3261
+ session.sessionRole,
3262
+ ["canonical_candidate", "residual"],
3263
+ resource,
3264
+ "$.sessionRole"
3265
+ );
3266
+ if (session.order !== null)
3267
+ fail(resource, "$.order", "null for pending finalization");
3268
+ const reconciliation = record(
3269
+ session.reconciliation,
3270
+ resource,
3271
+ "$.reconciliation"
3272
+ );
3273
+ if (reconciliation.status === "none")
3274
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3275
+ else
3276
+ validateRequiredReconciliation(
3277
+ reconciliation,
3278
+ [
3279
+ "local_commit_ambiguous",
3280
+ "amount_mismatch",
3281
+ "currency_mismatch",
3282
+ "excess_capture_pending_order"
3283
+ ],
3284
+ resource,
3285
+ "$.reconciliation"
3286
+ );
3287
+ } else if (session.finalizationStatus === "committed") {
3288
+ validateOrderReference(session.order, resource, "$.order");
3289
+ const reconciliation = record(
3290
+ session.reconciliation,
3291
+ resource,
3292
+ "$.reconciliation"
3293
+ );
3294
+ if (reconciliation.status === "none") {
3295
+ enumValue(
3296
+ session.sessionRole,
3297
+ ["canonical", "historical"],
3298
+ resource,
3299
+ "$.sessionRole"
3300
+ );
3301
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3302
+ } else {
3303
+ enumValue(
3304
+ session.sessionRole,
3305
+ ["canonical", "residual"],
3306
+ resource,
3307
+ "$.sessionRole"
3308
+ );
3309
+ validateRequiredReconciliation(
3310
+ reconciliation,
3311
+ [
3312
+ "inventory_unavailable",
3313
+ "admission_unavailable",
3314
+ "amount_mismatch",
3315
+ "currency_mismatch",
3316
+ "excess_capture",
3317
+ "late_capture",
3318
+ "cross_checkout_duplicate"
3319
+ ],
3320
+ resource,
3321
+ "$.reconciliation"
3322
+ );
3323
+ }
3324
+ } else fail(resource, "$.finalizationStatus", "pending | committed");
3325
+ } else if (status === "failed") {
3326
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3327
+ fail(resource, "$", "historical suppressed failed state");
3328
+ }
3329
+ validateNoReconciliation(
3330
+ session.reconciliation,
3331
+ resource,
3332
+ "$.reconciliation"
3333
+ );
3334
+ const failure = record(session.failure, resource, "$.failure");
3335
+ exact(failure, ["reason"], ["message"], resource, "$.failure");
3336
+ enumValue(
3337
+ failure.reason,
3338
+ PAYMENT_FAILURE_REASONS,
3339
+ resource,
3340
+ "$.failure.reason"
3341
+ );
3342
+ if (failure.message !== void 0)
3343
+ string(failure.message, resource, "$.failure.message");
3344
+ } else {
3345
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3346
+ fail(resource, "$", "historical suppressed canceled state");
3347
+ }
3348
+ validateNoReconciliation(
3349
+ session.reconciliation,
3350
+ resource,
3351
+ "$.reconciliation"
3352
+ );
3353
+ enumValue(
3354
+ session.cancellationReason,
3355
+ ["expired", "customer", "operator", "provider"],
3356
+ resource,
3357
+ "$.cancellationReason"
1727
3358
  );
1728
3359
  }
1729
- };
3360
+ return value;
3361
+ }
3362
+
3363
+ // src/core/api/commerce-idempotency.ts
3364
+ 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;
3365
+ var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
3366
+ function isCommerceIdempotencyKey(value) {
3367
+ return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
3368
+ }
3369
+ function assertCommerceIdempotencyKey(value) {
3370
+ if (isCommerceIdempotencyKey(value)) return;
3371
+ throw createValidationError(
3372
+ "idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
3373
+ { field: "idempotencyKey" }
3374
+ );
3375
+ }
1730
3376
 
1731
3377
  // src/core/api/cart-api.ts
1732
3378
  var CartApi = class extends CustomerScopedApi {
1733
3379
  constructor(options) {
1734
3380
  super("CartApi", { ...options, requiresCredential: false });
3381
+ this.serverTransport = Boolean(options.secretKey);
1735
3382
  }
1736
- async execute(endpoint, method, body) {
1737
- return this.request(endpoint, { method, body });
3383
+ endpoint(key) {
3384
+ return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
1738
3385
  }
1739
- /**
1740
- * Create a cart and receive its `cartToken`. Store the token and pass it to
1741
- * every subsequent cart operation.
1742
- */
1743
- createCart(params = {}) {
1744
- return this.execute("/api/carts/create", "POST", params);
3386
+ execute(endpoint2, body, idempotencyKey) {
3387
+ return this.requestEndpoint(endpoint2, body, {
3388
+ ...idempotencyKey && {
3389
+ headers: { "X-Idempotency-Key": idempotencyKey }
3390
+ }
3391
+ });
1745
3392
  }
1746
- getCart(cartToken) {
1747
- return this.execute("/api/carts/get", "POST", { cartToken });
3393
+ create(params = {}) {
3394
+ return this.execute(this.endpoint("create"), params).then(
3395
+ (value) => validateCreateCartResult(value)
3396
+ );
1748
3397
  }
1749
- merge(params) {
1750
- return this.execute(
1751
- COMMERCE_ENDPOINTS.carts.merge,
1752
- "POST",
1753
- params
3398
+ retrieve(params) {
3399
+ return this.execute(this.endpoint("retrieve"), params).then(
3400
+ (value) => validatePublicCart(value)
1754
3401
  );
1755
3402
  }
1756
- /**
1757
- * Resolve the authenticated customer's active cart by JWT (no `cartToken`
1758
- * required). Returns the cart and its capability handle, or both `null` when
1759
- * the customer has no active cart. Requires a customer token.
1760
- */
1761
- mine() {
1762
- return this.execute(
1763
- COMMERCE_ENDPOINTS.carts.mine,
1764
- "POST",
1765
- {}
3403
+ mine(params = {}) {
3404
+ const endpoint2 = this.endpoint("mine");
3405
+ return this.execute(endpoint2, params).then(
3406
+ (value) => validateCartMineResult(value)
3407
+ );
3408
+ }
3409
+ merge(params) {
3410
+ const { idempotencyKey, ...body } = params;
3411
+ assertCommerceIdempotencyKey(idempotencyKey);
3412
+ const endpoint2 = this.endpoint("merge");
3413
+ return this.execute(endpoint2, body, idempotencyKey).then(
3414
+ (value) => validateCartMergeResult(value)
1766
3415
  );
1767
3416
  }
1768
3417
  addItem(params) {
1769
- return this.execute(
1770
- COMMERCE_ENDPOINTS.carts.addItem,
1771
- "POST",
1772
- params
3418
+ return this.mutate(this.endpoint("addItem"), params);
3419
+ }
3420
+ mutate(endpoint2, params) {
3421
+ const { idempotencyKey, ...body } = params;
3422
+ assertCommerceIdempotencyKey(idempotencyKey);
3423
+ return this.execute(endpoint2, body, idempotencyKey).then(
3424
+ (value) => validateCartMutationResult(value)
1773
3425
  );
1774
3426
  }
1775
3427
  updateItem(params) {
1776
- return this.execute(
1777
- COMMERCE_ENDPOINTS.carts.updateItem,
1778
- "POST",
1779
- params
1780
- );
3428
+ return this.mutate(this.endpoint("updateItem"), params);
1781
3429
  }
1782
3430
  removeItem(params) {
1783
- return this.execute(
1784
- COMMERCE_ENDPOINTS.carts.removeItem,
1785
- "POST",
1786
- params
1787
- );
3431
+ return this.mutate(this.endpoint("removeItem"), params);
1788
3432
  }
1789
- applyDiscount(params) {
1790
- return this.execute(
1791
- COMMERCE_ENDPOINTS.carts.applyDiscount,
1792
- "POST",
1793
- params
1794
- );
3433
+ clear(params) {
3434
+ return this.mutate(this.endpoint("clear"), params);
1795
3435
  }
1796
- removeDiscount(params) {
1797
- return this.execute(
1798
- COMMERCE_ENDPOINTS.carts.removeDiscount,
1799
- "POST",
1800
- params
1801
- );
3436
+ updateDiscountCodes(params) {
3437
+ return this.mutate(this.endpoint("updateDiscountCodes"), params);
1802
3438
  }
1803
- clearCart(params) {
1804
- return this.execute(
1805
- COMMERCE_ENDPOINTS.carts.clear,
1806
- "POST",
1807
- params
1808
- );
3439
+ updateAttributes(params) {
3440
+ return this.mutate(this.endpoint("updateAttributes"), params);
1809
3441
  }
1810
3442
  };
1811
3443
 
@@ -2612,6 +4244,9 @@ function compareVariantOrder(a, b) {
2612
4244
  }
2613
4245
  function getVariantAvailableForSale(variant) {
2614
4246
  if (variant.isActive === false) return false;
4247
+ if (typeof variant.availableForSale === "boolean") {
4248
+ return variant.availableForSale;
4249
+ }
2615
4250
  if (variant.isUnlimited) return true;
2616
4251
  if (variant.inventoryPolicy === "continue") return true;
2617
4252
  return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
@@ -2721,7 +4356,7 @@ function buildProductListingCard(item, options = {}) {
2721
4356
  { listing: { selectionHintVariant } },
2722
4357
  options
2723
4358
  ),
2724
- title: product.title,
4359
+ title: product.title ?? "",
2725
4360
  representativeVariant,
2726
4361
  primaryImage: listingPrimaryMedia,
2727
4362
  priceRange,
@@ -2849,6 +4484,11 @@ function productDetailResultFromError(error) {
2849
4484
  if (!reason) return void 0;
2850
4485
  return { found: false, reason };
2851
4486
  }
4487
+ var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
4488
+ var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
4489
+ "priceRange.minVariantPrice.amount",
4490
+ "priceRange.maxVariantPrice.amount"
4491
+ ]);
2852
4492
  function nonEmpty(values) {
2853
4493
  return values?.length ? values : void 0;
2854
4494
  }
@@ -2896,14 +4536,34 @@ function buildProductListingPageWhere(params) {
2896
4536
  if (clauses.length === 1) return clauses[0];
2897
4537
  return { and: clauses };
2898
4538
  }
2899
- function buildProductListingPageUrl(params) {
4539
+ function productListingPageUsesBasePriceSort(sort) {
4540
+ const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
4541
+ return values.some(
4542
+ (value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
4543
+ );
4544
+ }
4545
+ function assertMarketListingPageQuerySupported(params) {
4546
+ if (!params.market?.trim()) return;
4547
+ const priceFilter = params.filters?.price;
4548
+ if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
4549
+ throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
4550
+ }
4551
+ }
4552
+ function buildProductListingPageRequest(params) {
4553
+ assertMarketListingPageQuerySupported(params);
2900
4554
  const options = {
4555
+ market: params.market,
4556
+ locale: params.locale,
4557
+ fallbackLocale: params.fallbackLocale,
2901
4558
  page: params.page,
2902
4559
  limit: params.limit,
2903
4560
  sort: params.sort,
2904
4561
  where: buildProductListingPageWhere(params)
2905
4562
  };
2906
- return params.mode === "full" ? listingGroupsQueryUrl(options) : listingGroupsQueryCatalogUrl(options);
4563
+ return {
4564
+ operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
4565
+ query: listingPageSearchParams(options)
4566
+ };
2907
4567
  }
2908
4568
  function withProductListingCards(response, options) {
2909
4569
  return {
@@ -2952,38 +4612,40 @@ var ProductApi = class extends BaseApi {
2952
4612
  * to remain available by the time an order is placed.
2953
4613
  */
2954
4614
  stockCheck(params) {
2955
- return this.request(
2956
- COMMERCE_ENDPOINTS.products.stockCheck,
4615
+ return this.requestEndpoint(
4616
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
2957
4617
  params
2958
4618
  );
2959
4619
  }
2960
4620
  stockSnapshot(params) {
2961
- return this.request(
2962
- stockSnapshotQuery(params),
4621
+ return this.requestEndpoint(
4622
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
2963
4623
  void 0,
2964
- { method: "GET" }
4624
+ { query: stockSnapshotSearchParams(params) }
2965
4625
  );
2966
4626
  }
2967
4627
  listingGroups(params) {
2968
- return this.request(
2969
- listingGroupsQuery(params),
4628
+ return this.requestEndpoint(
4629
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups,
2970
4630
  void 0,
2971
- { method: "GET" }
4631
+ { query: listingGroupsSearchParams(params) }
2972
4632
  );
2973
4633
  }
2974
4634
  listingGroupsCatalog(params) {
2975
- return this.request(
2976
- listingGroupsCatalogQuery(params),
4635
+ return this.requestEndpoint(
4636
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
2977
4637
  void 0,
2978
- { method: "GET" }
4638
+ { query: listingGroupsSearchParams(params) }
2979
4639
  );
2980
4640
  }
2981
4641
  async listingPage(params = {}) {
2982
4642
  if (params.mode === "full") {
2983
- const response2 = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4643
+ const request2 = buildProductListingPageRequest(params);
4644
+ const response2 = await this.requestEndpoint(request2.operation, void 0, { query: request2.query });
2984
4645
  return withProductListingCards(response2, params);
2985
4646
  }
2986
- const response = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4647
+ const request = buildProductListingPageRequest(params);
4648
+ const response = await this.requestEndpoint(request.operation, void 0, { query: request.query });
2987
4649
  return withProductListingCards(response, params);
2988
4650
  }
2989
4651
  /**
@@ -2998,10 +4660,10 @@ var ProductApi = class extends BaseApi {
2998
4660
  */
2999
4661
  async detail(params) {
3000
4662
  try {
3001
- const product = await this.request(
3002
- productDetailQuery(params),
4663
+ const product = await this.requestEndpoint(
4664
+ COMMERCE_ENDPOINT_OPERATIONS.products.detail,
3003
4665
  void 0,
3004
- { method: "GET" }
4666
+ { query: productDetailSearchParams(params) }
3005
4667
  );
3006
4668
  return { found: true, product };
3007
4669
  } catch (err) {
@@ -3012,10 +4674,10 @@ var ProductApi = class extends BaseApi {
3012
4674
  }
3013
4675
  async detailCatalog(params) {
3014
4676
  try {
3015
- const product = await this.request(
3016
- productDetailCatalogQuery(params),
4677
+ const product = await this.requestEndpoint(
4678
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
3017
4679
  void 0,
3018
- { method: "GET" }
4680
+ { query: productDetailSearchParams(params) }
3019
4681
  );
3020
4682
  return { found: true, product };
3021
4683
  } catch (err) {
@@ -3031,8 +4693,8 @@ var ProductApi = class extends BaseApi {
3031
4693
  * `product-upsert` tool.
3032
4694
  */
3033
4695
  upsert(params) {
3034
- return this.request(
3035
- COMMERCE_ENDPOINTS.products.upsert,
4696
+ return this.requestEndpoint(
4697
+ COMMERCE_ENDPOINT_OPERATIONS.products.upsert,
3036
4698
  normalizeProductUpsertParams(params)
3037
4699
  );
3038
4700
  }
@@ -3044,7 +4706,10 @@ var DiscountApi = class extends BaseApi {
3044
4706
  super("DiscountApi", options);
3045
4707
  }
3046
4708
  validate(params) {
3047
- return this.request("/api/discounts/validate", params);
4709
+ return this.requestEndpoint(
4710
+ COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
4711
+ params
4712
+ );
3048
4713
  }
3049
4714
  };
3050
4715
 
@@ -3054,7 +4719,10 @@ var ShippingApi = class extends BaseApi {
3054
4719
  super("ShippingApi", options);
3055
4720
  }
3056
4721
  calculate(params) {
3057
- return this.request("/api/shipping-policies/calculate", params);
4722
+ return this.requestEndpoint(
4723
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
4724
+ params
4725
+ );
3058
4726
  }
3059
4727
  };
3060
4728
 
@@ -3066,44 +4734,12 @@ function splitIdempotencyKey(params) {
3066
4734
  const { idempotencyKey, ...body } = params;
3067
4735
  return { body, idempotencyKey };
3068
4736
  }
3069
- function normalizeCreateOrderBody(params) {
3070
- if (params.items !== void 0) {
3071
- const { idempotencyKey: _idempotencyKey2, items, ...rest } = params;
3072
- return { ...rest, orderItems: items };
3073
- }
3074
- const { idempotencyKey: _idempotencyKey, ...body } = params;
3075
- return body;
3076
- }
3077
4737
  var OrderApi = class extends BaseApi {
3078
4738
  constructor(options) {
3079
4739
  super("OrderApi", options);
3080
4740
  }
3081
- createOrder(params) {
3082
- const { idempotencyKey } = params;
3083
- const normalizedBody = normalizeCreateOrderBody(params);
3084
- return this.request(
3085
- COMMERCE_ENDPOINTS.orders.create,
3086
- normalizedBody,
3087
- idempotencyRequestOptions(idempotencyKey)
3088
- );
3089
- }
3090
4741
  updateOrder(params) {
3091
- return this.request(COMMERCE_ENDPOINTS.orders.update, params);
3092
- }
3093
- updateTransaction(params) {
3094
- return this.request(
3095
- COMMERCE_ENDPOINTS.transactions.update,
3096
- params
3097
- );
3098
- }
3099
- confirmPayment(params) {
3100
- const { body, idempotencyKey } = splitIdempotencyKey(params);
3101
- const headerKey = idempotencyKey ?? params.providerEventId;
3102
- return this.request(
3103
- COMMERCE_ENDPOINTS.orders.confirmPayment,
3104
- body,
3105
- idempotencyRequestOptions(headerKey)
3106
- );
4742
+ return this.requestEndpoint(COMMERCE_ENDPOINTS.orders.update, params);
3107
4743
  }
3108
4744
  /**
3109
4745
  * Resolve an order + its payment transaction by PG payment id. Replaces raw
@@ -3115,28 +4751,12 @@ var OrderApi = class extends BaseApi {
3115
4751
  pgProvider: params.pgProvider,
3116
4752
  pgPaymentId: params.pgPaymentId
3117
4753
  }).toString();
3118
- return this.request(
3119
- `${COMMERCE_ENDPOINTS.orders.byPayment}?${query}`,
4754
+ return this.requestEndpoint(
4755
+ COMMERCE_ENDPOINTS.orders.byPayment,
3120
4756
  void 0,
3121
- { method: "GET" }
4757
+ { query }
3122
4758
  );
3123
4759
  }
3124
- /**
3125
- * Composed facade: confirm a provider payment, then resolve the
3126
- * depth-populated order/transaction by the same payment id. `confirmPayment`'s
3127
- * wire response carries only IDs (its contract is `.strict()`); this returns
3128
- * the populated `Order` so storefronts stop reconstructing order state
3129
- * locally. Two round trips by design — the alternative (widening the strict
3130
- * confirm-payment wire contract to embed a full Order) is rejected.
3131
- */
3132
- async confirmPaymentReturningOrder(params) {
3133
- const confirmation = await this.confirmPayment(params);
3134
- const { order, transaction } = await this.getByPaymentId({
3135
- pgProvider: params.pgProvider,
3136
- pgPaymentId: params.pgPaymentId
3137
- });
3138
- return { ...confirmation, order, transaction };
3139
- }
3140
4760
  cancelOrder(params) {
3141
4761
  const { idempotencyKey } = params;
3142
4762
  const body = {
@@ -3144,14 +4764,14 @@ var OrderApi = class extends BaseApi {
3144
4764
  reasonCode: params.reasonCode,
3145
4765
  reasonDetail: params.reasonDetail
3146
4766
  };
3147
- return this.request(
4767
+ return this.requestEndpoint(
3148
4768
  COMMERCE_ENDPOINTS.orders.cancel,
3149
4769
  body,
3150
4770
  idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0
3151
4771
  );
3152
4772
  }
3153
4773
  resolveCancelRefund(params) {
3154
- return this.request(
4774
+ return this.requestEndpoint(
3155
4775
  COMMERCE_ENDPOINTS.orders.resolveCancelRefund,
3156
4776
  {
3157
4777
  orderNumber: params.orderNumber,
@@ -3164,49 +4784,35 @@ var OrderApi = class extends BaseApi {
3164
4784
  idempotencyRequestOptions(params.idempotencyKey)
3165
4785
  );
3166
4786
  }
3167
- /**
3168
- * Returns a `PublicOrder`-compatible shape even when the server backs the
3169
- * response with a Checkout (checkout/order separation, #1285). `orderNumber`
3170
- * stays the stable cross-window key. A breaking `PublicCheckout` split is a
3171
- * deferred follow-up (design D10 / Q3-b); do not change this return type here.
3172
- */
3173
- checkout(params) {
3174
- const { body, idempotencyKey } = splitIdempotencyKey(params);
3175
- return this.request(
3176
- COMMERCE_ENDPOINTS.orders.checkout,
3177
- body,
3178
- idempotencyRequestOptions(idempotencyKey)
3179
- );
3180
- }
3181
4787
  createFulfillment(params) {
3182
4788
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3183
- return this.request(
4789
+ return this.requestEndpoint(
3184
4790
  COMMERCE_ENDPOINTS.orders.createFulfillment,
3185
4791
  body,
3186
4792
  idempotencyRequestOptions(idempotencyKey)
3187
4793
  );
3188
4794
  }
3189
4795
  prepareFulfillmentOrder(params) {
3190
- return this.request(
4796
+ return this.requestEndpoint(
3191
4797
  COMMERCE_ENDPOINTS.fulfillmentOrders.prepare,
3192
4798
  params
3193
4799
  );
3194
4800
  }
3195
4801
  updateFulfillment(params) {
3196
- return this.request(
4802
+ return this.requestEndpoint(
3197
4803
  COMMERCE_ENDPOINTS.orders.updateFulfillment,
3198
4804
  params
3199
4805
  );
3200
4806
  }
3201
4807
  bulkImportFulfillments(params) {
3202
- return this.request(
4808
+ return this.requestEndpoint(
3203
4809
  COMMERCE_ENDPOINTS.fulfillments.bulkImport,
3204
4810
  params
3205
4811
  );
3206
4812
  }
3207
4813
  returnWithRefund(params) {
3208
4814
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3209
- return this.request(
4815
+ return this.requestEndpoint(
3210
4816
  COMMERCE_ENDPOINTS.returns.returnRefund,
3211
4817
  body,
3212
4818
  idempotencyRequestOptions(idempotencyKey)
@@ -3214,19 +4820,139 @@ var OrderApi = class extends BaseApi {
3214
4820
  }
3215
4821
  createReturn(params) {
3216
4822
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3217
- return this.request(
4823
+ return this.requestEndpoint(
3218
4824
  COMMERCE_ENDPOINTS.returns.create,
3219
4825
  body,
3220
4826
  idempotencyRequestOptions(idempotencyKey)
3221
4827
  );
3222
4828
  }
3223
4829
  updateReturn(params) {
3224
- return this.request(COMMERCE_ENDPOINTS.returns.update, params);
4830
+ return this.requestEndpoint(
4831
+ COMMERCE_ENDPOINTS.returns.update,
4832
+ params
4833
+ );
4834
+ }
4835
+ };
4836
+
4837
+ // src/core/api/checkout-api.ts
4838
+ var CheckoutApi = class extends CustomerScopedApi {
4839
+ constructor(options) {
4840
+ super("CheckoutApi", { ...options, requiresCredential: false });
4841
+ }
4842
+ post(endpoint2, body, idempotencyKey) {
4843
+ return this.requestEndpoint(endpoint2, body, {
4844
+ ...idempotencyKey && {
4845
+ headers: { "X-Idempotency-Key": idempotencyKey }
4846
+ }
4847
+ });
4848
+ }
4849
+ async publicCheckout(result) {
4850
+ return validatePublicCheckout(await result);
4851
+ }
4852
+ async serverCheckout(result) {
4853
+ return validateServerCheckout(await result);
4854
+ }
4855
+ async createResult(result) {
4856
+ return validateCreateCheckoutResult(
4857
+ await result,
4858
+ false
4859
+ );
4860
+ }
4861
+ async createServerResult(result) {
4862
+ return validateCreateCheckoutResult(
4863
+ await result,
4864
+ true
4865
+ );
4866
+ }
4867
+ create(params) {
4868
+ const { idempotencyKey, ...body } = params;
4869
+ assertCommerceIdempotencyKey(idempotencyKey);
4870
+ return this.createResult(
4871
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
4872
+ );
4873
+ }
4874
+ createServer(params) {
4875
+ const { idempotencyKey, ...body } = params;
4876
+ assertCommerceIdempotencyKey(idempotencyKey);
4877
+ return this.createServerResult(
4878
+ this.post(
4879
+ COMMERCE_ENDPOINTS.checkouts.server.create,
4880
+ body,
4881
+ idempotencyKey
4882
+ )
4883
+ );
4884
+ }
4885
+ retrieve(params) {
4886
+ return this.publicCheckout(
4887
+ this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
4888
+ );
4889
+ }
4890
+ retrieveServer(params) {
4891
+ return this.serverCheckout(
4892
+ this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
4893
+ );
4894
+ }
4895
+ async query(params = {}) {
4896
+ const result = await this.post(
4897
+ COMMERCE_ENDPOINTS.checkouts.server.query,
4898
+ params
4899
+ );
4900
+ return validateCheckoutQueryResult(result);
4901
+ }
4902
+ };
4903
+
4904
+ // src/core/api/payment-session-api.ts
4905
+ var PaymentSessionApi = class extends CustomerScopedApi {
4906
+ constructor(options) {
4907
+ super("PaymentSessionApi", { ...options, requiresCredential: false });
4908
+ this.serverTransport = Boolean(options.secretKey);
4909
+ }
4910
+ post(endpoint2, body, idempotencyKey) {
4911
+ return this.requestEndpoint(endpoint2, body, {
4912
+ ...idempotencyKey && {
4913
+ headers: { "X-Idempotency-Key": idempotencyKey }
4914
+ }
4915
+ });
4916
+ }
4917
+ async paymentSession(result) {
4918
+ return validatePublicPaymentSession(await result);
4919
+ }
4920
+ create(params) {
4921
+ const { idempotencyKey, ...body } = params;
4922
+ assertCommerceIdempotencyKey(idempotencyKey);
4923
+ return this.paymentSession(
4924
+ this.post(
4925
+ this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
4926
+ body,
4927
+ idempotencyKey
4928
+ )
4929
+ );
4930
+ }
4931
+ retrieve(params) {
4932
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4933
+ return this.paymentSession(this.post(endpoint2, params));
4934
+ }
4935
+ cancel(params) {
4936
+ const { idempotencyKey, ...body } = params;
4937
+ assertCommerceIdempotencyKey(idempotencyKey);
4938
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4939
+ return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
4940
+ }
4941
+ confirm(params) {
4942
+ const { idempotencyKey, ...body } = params;
4943
+ assertCommerceIdempotencyKey(idempotencyKey);
4944
+ return this.paymentSession(
4945
+ this.post(
4946
+ COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
4947
+ body,
4948
+ idempotencyKey
4949
+ )
4950
+ );
3225
4951
  }
3226
4952
  };
3227
4953
 
3228
4954
  // src/core/preview/server-preview-client.ts
3229
- var ServerPreviewClient = class extends BaseApi {
4955
+ var ServerPreviewClient = class extends RawBaseApi {
3230
4956
  constructor(options) {
3231
4957
  super("ServerPreviewClient", options);
3232
4958
  }
@@ -3282,6 +5008,7 @@ var PreviewProductApi = class extends ProductApi {
3282
5008
  };
3283
5009
  var ServerCommerceClient = class {
3284
5010
  constructor(options) {
5011
+ this.market = options.market;
3285
5012
  const publishableKey = requirePublishableKeyForSecret(
3286
5013
  "ServerCommerceClient",
3287
5014
  options.publishableKey,
@@ -3298,33 +5025,33 @@ var ServerCommerceClient = class {
3298
5025
  const discountApi = new DiscountApi(serverOptions);
3299
5026
  const shippingApi = new ShippingApi(serverOptions);
3300
5027
  const orderApi = new OrderApi(serverOptions);
5028
+ const checkoutApi = new CheckoutApi(serverOptions);
5029
+ const paymentSessionApi = new PaymentSessionApi(serverOptions);
3301
5030
  this.product = {
3302
5031
  stockCheck: productApi.stockCheck.bind(productApi),
3303
- listingGroups: productApi.listingGroups.bind(productApi),
3304
- listingPage: productApi.listingPage.bind(productApi),
3305
- detail: productApi.detail.bind(productApi),
5032
+ listingGroups: (params) => productApi.listingGroups(this.withMarket(params)),
5033
+ listingPage: ((params = {}) => productApi.listingPage(
5034
+ this.withMarket(params)
5035
+ )),
5036
+ detail: (params) => productApi.detail(this.withMarket(params)),
5037
+ detailCatalog: (params) => productApi.detailCatalog(this.withMarket(params)),
3306
5038
  previewDetail: productApi.previewDetail.bind(productApi),
3307
5039
  upsert: productApi.upsert.bind(productApi)
3308
5040
  };
3309
- this.cart = {
3310
- create: cartApi.createCart.bind(cartApi),
3311
- get: cartApi.getCart.bind(cartApi),
5041
+ this.carts = {
5042
+ create: (params) => cartApi.create(this.withMarket(params ?? {})),
5043
+ retrieve: cartApi.retrieve.bind(cartApi),
3312
5044
  addItem: cartApi.addItem.bind(cartApi),
3313
5045
  updateItem: cartApi.updateItem.bind(cartApi),
3314
5046
  removeItem: cartApi.removeItem.bind(cartApi),
3315
- applyDiscount: cartApi.applyDiscount.bind(cartApi),
3316
- removeDiscount: cartApi.removeDiscount.bind(cartApi),
3317
- clear: cartApi.clearCart.bind(cartApi),
3318
- merge: cartApi.merge.bind(cartApi),
3319
- mine: cartApi.mine.bind(cartApi)
5047
+ updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
5048
+ updateAttributes: cartApi.updateAttributes.bind(cartApi),
5049
+ clear: cartApi.clear.bind(cartApi),
5050
+ merge: (params) => cartApi.merge(params),
5051
+ mine: (params) => cartApi.mine(params)
3320
5052
  };
3321
5053
  this.orders = {
3322
- checkout: orderApi.checkout.bind(orderApi),
3323
- create: orderApi.createOrder.bind(orderApi),
3324
5054
  update: orderApi.updateOrder.bind(orderApi),
3325
- updateTransaction: orderApi.updateTransaction.bind(orderApi),
3326
- confirmPayment: orderApi.confirmPayment.bind(orderApi),
3327
- confirmPaymentReturningOrder: orderApi.confirmPaymentReturningOrder.bind(orderApi),
3328
5055
  getByPaymentId: orderApi.getByPaymentId.bind(orderApi),
3329
5056
  cancelOrder: orderApi.cancelOrder.bind(orderApi),
3330
5057
  resolveCancelRefund: orderApi.resolveCancelRefund.bind(orderApi),
@@ -3336,6 +5063,17 @@ var ServerCommerceClient = class {
3336
5063
  updateReturn: orderApi.updateReturn.bind(orderApi),
3337
5064
  returnWithRefund: orderApi.returnWithRefund.bind(orderApi)
3338
5065
  };
5066
+ this.checkouts = {
5067
+ create: checkoutApi.createServer.bind(checkoutApi),
5068
+ retrieve: checkoutApi.retrieveServer.bind(checkoutApi),
5069
+ query: checkoutApi.query.bind(checkoutApi)
5070
+ };
5071
+ this.paymentSessions = {
5072
+ create: paymentSessionApi.create.bind(paymentSessionApi),
5073
+ retrieve: (params) => paymentSessionApi.retrieve(params),
5074
+ cancel: (params) => paymentSessionApi.cancel(params),
5075
+ confirm: paymentSessionApi.confirm.bind(paymentSessionApi)
5076
+ };
3339
5077
  this.discounts = {
3340
5078
  validate: discountApi.validate.bind(discountApi)
3341
5079
  };
@@ -3343,6 +5081,14 @@ var ServerCommerceClient = class {
3343
5081
  calculate: shippingApi.calculate.bind(shippingApi)
3344
5082
  };
3345
5083
  }
5084
+ getDefaultMarket() {
5085
+ return this.market;
5086
+ }
5087
+ withMarket(params) {
5088
+ const defaultMarket = this.market?.trim();
5089
+ if (!defaultMarket || params.market?.trim()) return params;
5090
+ return { ...params, market: defaultMarket };
5091
+ }
3346
5092
  };
3347
5093
 
3348
5094
  // src/core/events/events-client.ts
@@ -3362,7 +5108,17 @@ var EventsClient = class {
3362
5108
  getRange(params) {
3363
5109
  return this.execute(
3364
5110
  buildRangeEndpoint(params),
3365
- "GET",
5111
+ resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
5112
+ void 0,
5113
+ { useCustomerAuth: false }
5114
+ );
5115
+ }
5116
+ getAdmissionAvailability(params) {
5117
+ return this.execute(
5118
+ buildAdmissionAvailabilityEndpoint(params),
5119
+ resolveOperationMethod(
5120
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
5121
+ ),
3366
5122
  void 0,
3367
5123
  { useCustomerAuth: false }
3368
5124
  );
@@ -3391,11 +5147,11 @@ var EventsClient = class {
3391
5147
  { useCustomerAuth: false }
3392
5148
  );
3393
5149
  }
3394
- async execute(endpoint, method, body, options = {}) {
5150
+ async execute(endpoint2, method, body, options = {}) {
3395
5151
  const useCustomerAuth = options.useCustomerAuth === true;
3396
5152
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
3397
5153
  try {
3398
- const response = await httpFetch(endpoint, {
5154
+ const response = await httpFetch(endpoint2, {
3399
5155
  method,
3400
5156
  apiUrl: this.apiUrl,
3401
5157
  publishableKey: this.publishableKey,
@@ -3404,7 +5160,7 @@ var EventsClient = class {
3404
5160
  ...body !== void 0 && { body: JSON.stringify(body) }
3405
5161
  });
3406
5162
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
3407
- return parseApiResponse(response, endpoint);
5163
+ return parseApiResponse(response, endpoint2);
3408
5164
  } catch (err) {
3409
5165
  const id = err instanceof SDKError ? err.requestId ?? null : null;
3410
5166
  this.onRequestId?.(id);
@@ -3443,7 +5199,17 @@ function buildRangeEndpoint(params) {
3443
5199
  appendValues(urlParams, "categorySlug", params.categorySlug);
3444
5200
  appendValues(urlParams, "tag", params.tag);
3445
5201
  appendValues(urlParams, "tagSlug", params.tagSlug);
3446
- return `/api/event-occurrences/range?${urlParams.toString()}`;
5202
+ return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
5203
+ query: urlParams
5204
+ });
5205
+ }
5206
+ function buildAdmissionAvailabilityEndpoint(params) {
5207
+ const urlParams = new URLSearchParams();
5208
+ urlParams.set("occurrence", params.occurrence);
5209
+ return resolveOperationPath(
5210
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
5211
+ { query: urlParams }
5212
+ );
3447
5213
  }
3448
5214
  function formatDateParam(value) {
3449
5215
  return value instanceof Date ? value.toISOString() : value;
@@ -3456,11 +5222,56 @@ function appendValues(params, key, value) {
3456
5222
  }
3457
5223
  }
3458
5224
 
5225
+ // src/core/market/market-discovery.ts
5226
+ function toMarketDTO(row) {
5227
+ return {
5228
+ id: row.id,
5229
+ handle: row.handle,
5230
+ name: row.name,
5231
+ countryCode: row.countryCode,
5232
+ targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
5233
+ currency: row.currency,
5234
+ isPrimary: row.isPrimary === true,
5235
+ isActive: row.isActive === true
5236
+ };
5237
+ }
5238
+ var MarketDiscovery = class {
5239
+ constructor(read) {
5240
+ this.read = read;
5241
+ }
5242
+ async list() {
5243
+ const res = await this.read({
5244
+ where: { isActive: { equals: true } },
5245
+ limit: 100
5246
+ });
5247
+ if (res.hasNextPage) {
5248
+ console.warn(
5249
+ "[markets.list] more than 100 active markets; results truncated to 100."
5250
+ );
5251
+ }
5252
+ return res.docs.map(toMarketDTO);
5253
+ }
5254
+ async default() {
5255
+ const res = await this.read({
5256
+ where: { isPrimary: { equals: true }, isActive: { equals: true } },
5257
+ limit: 1
5258
+ });
5259
+ const row = res.docs[0];
5260
+ return row ? toMarketDTO(row) : null;
5261
+ }
5262
+ };
5263
+
3459
5264
  // src/core/api/tenant-introspection-api.ts
3460
- var TenantIntrospectionApi = class extends BaseApi {
5265
+ var TenantIntrospectionApi = class extends RawBaseApi {
3461
5266
  constructor(options) {
3462
5267
  super("TenantIntrospectionApi", options);
3463
5268
  }
5269
+ context(params = {}) {
5270
+ const endpoint2 = params.includeCounts ? "/api/tenants/context?counts=true" : "/api/tenants/context";
5271
+ return this.request(endpoint2, void 0, {
5272
+ method: "GET"
5273
+ });
5274
+ }
3464
5275
  collectionSchema(collection) {
3465
5276
  return this.request(
3466
5277
  `/api/tenants/schema/${encodeURIComponent(collection)}`,
@@ -3494,40 +5305,30 @@ var MembershipApi = class extends BaseApi {
3494
5305
  */
3495
5306
  subscribe(params) {
3496
5307
  const { subscribeIntentKey, ...body } = params;
3497
- return this.request(
3498
- MEMBERSHIP_ENDPOINTS.subscribe,
5308
+ return this.requestEndpoint(
5309
+ MEMBERSHIP_ENDPOINT_OPERATIONS.subscribe,
3499
5310
  body,
3500
5311
  idempotencyRequestOptions(subscribeIntentKey)
3501
5312
  );
3502
5313
  }
3503
5314
  /**
3504
5315
  * Cancel a membership by id.
3505
- * `immediate=false` (default) sets `cancelAtPeriodEnd`; the customer retains
3506
- * benefits until `currentPeriodEnd`. `immediate=true` cancels now and revokes
3507
- * membership groups immediately.
5316
+ * By default this sets `cancelAtPeriodEnd`, keeps benefits until
5317
+ * `currentPeriodEnd`, and stops renewal. Pass `immediate=true` to cancel
5318
+ * immediately and revoke membership groups now.
3508
5319
  */
3509
5320
  cancel(params) {
3510
5321
  const { id, immediate } = params;
3511
- return this.request(
3512
- MEMBERSHIP_ENDPOINTS.cancel(id),
3513
- immediate !== void 0 ? { immediate } : {}
3514
- );
3515
- }
3516
- /**
3517
- * Retrieve the authenticated customer's own membership view.
3518
- * Never returns payment tokens or internal keys.
3519
- */
3520
- me() {
3521
- return this.request(
3522
- MEMBERSHIP_ENDPOINTS.me,
3523
- void 0,
3524
- { method: "GET" }
5322
+ return this.requestEndpoint(
5323
+ MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
5324
+ immediate !== void 0 ? { immediate } : {},
5325
+ { pathParams: { id } }
3525
5326
  );
3526
5327
  }
3527
5328
  };
3528
5329
 
3529
5330
  // src/core/client/client.server.ts
3530
- var ServerClient = class {
5331
+ var ServerClient = class _ServerClient {
3531
5332
  constructor(options) {
3532
5333
  this.lastRequestId = null;
3533
5334
  if (typeof window !== "undefined") {
@@ -3556,17 +5357,18 @@ var ServerClient = class {
3556
5357
  publishableKey: this.config.publishableKey,
3557
5358
  secretKey: this.config.secretKey,
3558
5359
  apiUrl: this.config.apiUrl,
5360
+ market: this.config.market,
3559
5361
  onRequestId
3560
5362
  };
3561
5363
  this.commerce = new ServerCommerceClient(serverOptions);
3562
5364
  const membershipApi = new MembershipApi(serverOptions);
3563
5365
  this.memberships = {
3564
5366
  subscribe: membershipApi.subscribe.bind(membershipApi),
3565
- cancel: membershipApi.cancel.bind(membershipApi),
3566
- me: membershipApi.me.bind(membershipApi)
5367
+ cancel: membershipApi.cancel.bind(membershipApi)
3567
5368
  };
3568
5369
  const tenantIntrospectionApi = new TenantIntrospectionApi(serverOptions);
3569
5370
  this.tenant = {
5371
+ context: tenantIntrospectionApi.context.bind(tenantIntrospectionApi),
3570
5372
  collectionSchema: tenantIntrospectionApi.collectionSchema.bind(
3571
5373
  tenantIntrospectionApi
3572
5374
  ),
@@ -3594,6 +5396,9 @@ var ServerClient = class {
3594
5396
  onRequestId,
3595
5397
  this.config.apiUrl
3596
5398
  );
5399
+ this.markets = new MarketDiscovery(
5400
+ (options2) => this.collections.from("markets").find(options2)
5401
+ );
3597
5402
  }
3598
5403
  get events() {
3599
5404
  if (!this._events) {
@@ -3615,6 +5420,9 @@ var ServerClient = class {
3615
5420
  getState() {
3616
5421
  return { ...this.state };
3617
5422
  }
5423
+ withMarket(market) {
5424
+ return new _ServerClient({ ...this.config, market });
5425
+ }
3618
5426
  getConfig() {
3619
5427
  const { secretKey: _, ...safeConfig } = this.config;
3620
5428
  return safeConfig;