@01.software/sdk 0.44.0 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +366 -2
  2. package/MIGRATION.md +108 -10
  3. package/README.md +486 -98
  4. package/dist/{server-nXOezi4b.d.cts → catalog-mappers-sIshKNb3.d.cts} +14 -3
  5. package/dist/{server-nXOezi4b.d.ts → catalog-mappers-sIshKNb3.d.ts} +14 -3
  6. package/dist/client.cjs +2693 -345
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.d.cts +10 -7
  9. package/dist/client.d.ts +10 -7
  10. package/dist/client.js +2693 -345
  11. package/dist/client.js.map +1 -1
  12. package/dist/{collection-client-DWooaiTr.d.ts → collection-client-D6kKrYdq.d.ts} +8 -5
  13. package/dist/{collection-client-Dyl-CDcj.d.cts → collection-client-DolMjCoC.d.cts} +8 -5
  14. package/dist/{const-pGDnsy0o.d.ts → const-BAG0MH0u.d.cts} +13 -10
  15. package/dist/{const-1vleZ6ov.d.cts → const-CaPq2AE4.d.ts} +13 -10
  16. package/dist/errors.cjs +74 -1
  17. package/dist/errors.cjs.map +1 -1
  18. package/dist/errors.d.cts +38 -1
  19. package/dist/errors.d.ts +38 -1
  20. package/dist/errors.js +74 -1
  21. package/dist/errors.js.map +1 -1
  22. package/dist/{index-DUNySyxV.d.ts → index-BNICJxBL.d.ts} +4 -4
  23. package/dist/{index-a6g7vqAD.d.cts → index-YGrZrxNn.d.cts} +4 -4
  24. package/dist/index.cjs +2754 -368
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +18 -19
  27. package/dist/index.d.ts +18 -19
  28. package/dist/index.js +2754 -368
  29. package/dist/index.js.map +1 -1
  30. package/dist/{payload-types-CDsuOEfM.d.cts → payload-types-CJZuXcgF.d.cts} +6671 -4001
  31. package/dist/{payload-types-CDsuOEfM.d.ts → payload-types-CJZuXcgF.d.ts} +6671 -4001
  32. package/dist/query.cjs +558 -101
  33. package/dist/query.cjs.map +1 -1
  34. package/dist/query.d.cts +43 -45
  35. package/dist/query.d.ts +43 -45
  36. package/dist/query.js +558 -101
  37. package/dist/query.js.map +1 -1
  38. package/dist/realtime.cjs.map +1 -1
  39. package/dist/realtime.d.cts +2 -2
  40. package/dist/realtime.d.ts +2 -2
  41. package/dist/realtime.js.map +1 -1
  42. package/dist/server.cjs +2343 -437
  43. package/dist/server.cjs.map +1 -1
  44. package/dist/server.d.cts +11 -10
  45. package/dist/server.d.ts +11 -10
  46. package/dist/server.js +2343 -437
  47. package/dist/server.js.map +1 -1
  48. package/dist/storefront-cache.cjs +65 -1
  49. package/dist/storefront-cache.cjs.map +1 -1
  50. package/dist/storefront-cache.js +65 -1
  51. package/dist/storefront-cache.js.map +1 -1
  52. package/dist/types-BC6rVmJa.d.ts +47 -0
  53. package/dist/{types-CDND3hzq.d.cts → types-C60vHIkY.d.ts} +1134 -509
  54. package/dist/types-D5p7-m1l.d.cts +47 -0
  55. package/dist/{types-Dt9FJisi.d.ts → types-xlqBeW2N.d.cts} +1134 -509
  56. package/dist/ui/canvas/server.cjs +244 -2
  57. package/dist/ui/canvas/server.cjs.map +1 -1
  58. package/dist/ui/canvas/server.d.cts +27 -1
  59. package/dist/ui/canvas/server.d.ts +27 -1
  60. package/dist/ui/canvas/server.js +244 -2
  61. package/dist/ui/canvas/server.js.map +1 -1
  62. package/dist/ui/canvas.cjs +419 -103
  63. package/dist/ui/canvas.cjs.map +1 -1
  64. package/dist/ui/canvas.d.cts +19 -7
  65. package/dist/ui/canvas.d.ts +19 -7
  66. package/dist/ui/canvas.js +419 -103
  67. package/dist/ui/canvas.js.map +1 -1
  68. package/dist/ui/form.d.cts +1 -1
  69. package/dist/ui/form.d.ts +1 -1
  70. package/dist/ui/video.d.cts +1 -1
  71. package/dist/ui/video.d.ts +1 -1
  72. package/dist/webhook.cjs +2 -1
  73. package/dist/webhook.cjs.map +1 -1
  74. package/dist/webhook.d.cts +4 -4
  75. package/dist/webhook.d.ts +4 -4
  76. package/dist/webhook.js +2 -1
  77. package/dist/webhook.js.map +1 -1
  78. package/package.json +10 -9
  79. package/dist/types-SoXsbKhj.d.cts +0 -33
  80. package/dist/types-oiae_LMm.d.ts +0 -33
package/dist/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;
@@ -283,6 +410,11 @@ function redactSensitiveHeaders(headers) {
283
410
  redacted["x-preview-token"]
284
411
  );
285
412
  }
413
+ if (redacted["x-custom-payment-signature"]) {
414
+ redacted["x-custom-payment-signature"] = redactSensitiveHeader(
415
+ redacted["x-custom-payment-signature"]
416
+ );
417
+ }
286
418
  return redacted;
287
419
  }
288
420
  function getErrorSuggestion(status) {
@@ -374,116 +506,129 @@ function attachRequestId(err, id) {
374
506
  }
375
507
  function parseRetryAfter(response) {
376
508
  const raw = response.headers.get("Retry-After");
377
- if (!raw) return void 0;
378
- return parseInt(raw, 10) || void 0;
509
+ if (!raw) return { permitsAutomaticRetry: true };
510
+ const trimmed = raw.trim();
511
+ let seconds;
512
+ if (/^\d+$/.test(trimmed)) {
513
+ seconds = Number(trimmed);
514
+ if (!Number.isSafeInteger(seconds)) {
515
+ return { permitsAutomaticRetry: false };
516
+ }
517
+ } else {
518
+ const retryAt = Date.parse(trimmed);
519
+ if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
520
+ seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
521
+ }
522
+ return {
523
+ seconds,
524
+ permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
525
+ };
379
526
  }
380
- function mapResponseToError(status, parsed, details, requestId, retryAfter) {
527
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
381
528
  const errorDetails = {
382
529
  ...details,
383
530
  ...parsed.errors && { errors: parsed.errors },
384
- ...parsed.body && { body: parsed.body }
531
+ ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
385
532
  };
386
533
  const suggestion = getParsedErrorSuggestion(status, parsed);
534
+ const finalize = (error) => {
535
+ const withRequestId = attachRequestId(error, requestId);
536
+ if (retryAfter !== void 0) {
537
+ Object.assign(withRequestId, { retryAfter });
538
+ }
539
+ return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
540
+ };
387
541
  if (status === 400 || status === 422) {
388
- return attachRequestId(
542
+ return finalize(
389
543
  createValidationError(
390
544
  parsed.errorMessage,
391
545
  errorDetails,
392
546
  parsed.userMessage,
393
547
  suggestion,
394
548
  status
395
- ),
396
- requestId
549
+ )
397
550
  );
398
551
  }
399
552
  if (status === 401) {
400
- return attachRequestId(
553
+ return finalize(
401
554
  createAuthError(
402
555
  parsed.errorMessage,
403
556
  errorDetails,
404
557
  parsed.userMessage,
405
558
  suggestion
406
- ),
407
- requestId
559
+ )
408
560
  );
409
561
  }
410
562
  if (status === 403) {
411
- return attachRequestId(
563
+ return finalize(
412
564
  createPermissionError(
413
565
  parsed.errorMessage,
414
566
  errorDetails,
415
567
  parsed.userMessage,
416
568
  suggestion
417
- ),
418
- requestId
569
+ )
419
570
  );
420
571
  }
421
572
  if (status === 404) {
422
- return attachRequestId(
573
+ return finalize(
423
574
  createNotFoundError(
424
575
  parsed.errorMessage,
425
576
  errorDetails,
426
577
  parsed.userMessage,
427
578
  suggestion
428
- ),
429
- requestId
579
+ )
430
580
  );
431
581
  }
432
582
  if (status === 409) {
433
- return attachRequestId(
583
+ return finalize(
434
584
  createConflictError(
435
585
  parsed.errorMessage,
436
586
  errorDetails,
437
587
  parsed.userMessage,
438
588
  suggestion
439
- ),
440
- requestId
589
+ )
441
590
  );
442
591
  }
443
592
  if (status === 410) {
444
- return attachRequestId(
593
+ return finalize(
445
594
  createGoneError(
446
595
  parsed.errorMessage,
447
596
  errorDetails,
448
597
  parsed.userMessage,
449
598
  suggestion
450
- ),
451
- requestId
599
+ )
452
600
  );
453
601
  }
454
602
  if (status === 429) {
455
- return attachRequestId(
603
+ return finalize(
456
604
  createRateLimitError(
457
605
  parsed.errorMessage,
458
606
  retryAfter,
459
607
  errorDetails,
460
608
  parsed.userMessage,
461
609
  suggestion
462
- ),
463
- requestId
610
+ )
464
611
  );
465
612
  }
466
613
  if (status === 503) {
467
- return attachRequestId(
614
+ return finalize(
468
615
  createServiceUnavailableError(
469
616
  parsed.errorMessage,
470
617
  retryAfter,
471
618
  errorDetails,
472
619
  parsed.userMessage,
473
620
  suggestion
474
- ),
475
- requestId
621
+ )
476
622
  );
477
623
  }
478
- return attachRequestId(
624
+ return finalize(
479
625
  createNetworkError(
480
626
  parsed.errorMessage,
481
627
  status,
482
628
  errorDetails,
483
629
  parsed.userMessage,
484
630
  suggestion
485
- ),
486
- requestId
631
+ )
487
632
  );
488
633
  }
489
634
  async function httpFetch(url, options) {
@@ -496,6 +641,7 @@ async function httpFetch(url, options) {
496
641
  debug,
497
642
  retry,
498
643
  onUnauthorized,
644
+ errorFamily,
499
645
  ...requestInit
500
646
  } = options || {};
501
647
  const baseUrl = resolveApiUrl(apiUrl);
@@ -548,6 +694,8 @@ async function httpFetch(url, options) {
548
694
  headers: redactSensitiveHeaders(response.headers)
549
695
  });
550
696
  if (!response.ok) {
697
+ const parsed = await parseErrorBody(response);
698
+ const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
551
699
  if (isUsageLimitExceededResponse(response)) {
552
700
  const limit = parseInt(
553
701
  response.headers.get("X-Usage-Limit") || "0",
@@ -561,7 +709,7 @@ async function httpFetch(url, options) {
561
709
  response.headers.get("X-Usage-Remaining") || "0",
562
710
  10
563
711
  );
564
- throw attachRequestId(
712
+ const usageError = attachRequestId(
565
713
  createUsageLimitError(
566
714
  `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
567
715
  { limit, current, remaining },
@@ -575,9 +723,9 @@ async function httpFetch(url, options) {
575
723
  ),
576
724
  requestId
577
725
  );
726
+ throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
578
727
  }
579
- const parsed = await parseErrorBody(response);
580
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
728
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
581
729
  hasRetried401 = true;
582
730
  try {
583
731
  const newToken = await onUnauthorized();
@@ -599,13 +747,18 @@ async function httpFetch(url, options) {
599
747
  parsed,
600
748
  details,
601
749
  requestId,
602
- retryAfter
750
+ retryAfter.seconds,
751
+ errorFamily
603
752
  );
604
753
  const method2 = (requestInit.method || "GET").toUpperCase();
605
754
  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)) {
755
+ const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
756
+ if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
607
757
  lastError = error;
608
- const retryDelay = retryConfig.retryDelay(attempt);
758
+ const retryDelay = Math.max(
759
+ retryConfig.retryDelay(attempt),
760
+ (retryAfter.seconds ?? 0) * 1e3
761
+ );
609
762
  debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
610
763
  await delay(retryDelay);
611
764
  continue;
@@ -675,90 +828,45 @@ async function httpFetch(url, options) {
675
828
  throw lastError ?? new NetworkError("Request failed after retries");
676
829
  }
677
830
 
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
831
  // 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);
832
+ function normalizedMarket(value) {
833
+ const market = value?.trim();
834
+ return market || void 0;
835
+ }
836
+ function appendProductLocaleSearchParams(search, options) {
837
+ if (options?.locale) search.set("locale", options.locale);
838
+ if (options?.fallbackLocale !== void 0) {
839
+ search.set(
840
+ "fallbackLocale",
841
+ options.fallbackLocale === false ? "none" : options.fallbackLocale
842
+ );
743
843
  }
744
- return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
745
844
  }
746
- function productDetailCatalogQuery(params) {
845
+ function productDetailSearchParams(params) {
747
846
  const search = new URLSearchParams();
748
847
  if ("slug" in params) {
749
848
  search.set("slug", params.slug);
750
849
  } else {
751
850
  search.set("id", params.id);
752
851
  }
753
- return `${COMMERCE_ENDPOINTS.products.detailCatalog}?${search}`;
754
- }
755
- function listingGroupsQuery(params) {
756
- return `${COMMERCE_ENDPOINTS.products.listingGroups}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
852
+ const market = normalizedMarket(params.market);
853
+ if (market) search.set("market", market);
854
+ appendProductLocaleSearchParams(search, params);
855
+ return search.toString();
757
856
  }
758
- function listingGroupsCatalogQuery(params) {
759
- return `${COMMERCE_ENDPOINTS.products.listingGroupsCatalog}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
857
+ function listingGroupsSearchParams(params) {
858
+ const ids = params.productIds.map(encodeURIComponent).join(",");
859
+ const search = new URLSearchParams();
860
+ const market = normalizedMarket(params.market);
861
+ if (market) search.set("market", market);
862
+ appendProductLocaleSearchParams(search, params);
863
+ const query = search.toString();
864
+ return `ids=${ids}${query ? `&${query}` : ""}`;
760
865
  }
761
866
  function appendListingGroupsQuerySearchParams(search, options) {
867
+ const market = normalizedMarket(options?.market);
868
+ if (market) search.set("market", market);
869
+ appendProductLocaleSearchParams(search, options);
762
870
  if (options?.page != null) search.set("page", String(options.page));
763
871
  if (options?.limit != null) search.set("limit", String(options.limit));
764
872
  if (options?.sort != null) {
@@ -769,20 +877,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
769
877
  search.set("whereJson", JSON.stringify(options.where));
770
878
  }
771
879
  }
772
- function listingGroupsQueryUrl(options) {
880
+ function listingPageSearchParams(options) {
773
881
  const search = new URLSearchParams();
774
882
  appendListingGroupsQuerySearchParams(search, options);
775
- const query = search.toString();
776
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
883
+ return search.toString();
777
884
  }
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(",")}`;
885
+ function stockSnapshotSearchParams(params) {
886
+ return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
786
887
  }
787
888
 
788
889
  // src/core/collection/http-client.ts
@@ -825,10 +926,15 @@ var HttpClient = class {
825
926
  throw err;
826
927
  }
827
928
  }
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;
929
+ buildUrl(endpoint2, options) {
930
+ if (!options) return endpoint2;
931
+ const { fallbackLocale, ...rest } = options;
932
+ const queryOptions = fallbackLocale === void 0 ? rest : {
933
+ ...rest,
934
+ "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
935
+ };
936
+ const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
937
+ return queryString ? `${endpoint2}${queryString}` : endpoint2;
832
938
  }
833
939
  assertJsonResponse(response) {
834
940
  const contentType = response.headers.get("content-type");
@@ -1019,16 +1125,16 @@ var CollectionQueryBuilder = class {
1019
1125
  * @returns Payload CMS mutation response with doc and message
1020
1126
  */
1021
1127
  async create(data, options) {
1022
- const endpoint = `/api/${String(this.collection)}`;
1128
+ const endpoint2 = `/api/${String(this.collection)}`;
1023
1129
  if (options?.file) {
1024
1130
  return this.api.requestCreateWithFile(
1025
- endpoint,
1131
+ endpoint2,
1026
1132
  data,
1027
1133
  options.file,
1028
1134
  options.filename
1029
1135
  );
1030
1136
  }
1031
- return this.api.requestCreate(endpoint, data);
1137
+ return this.api.requestCreate(endpoint2, data);
1032
1138
  }
1033
1139
  /**
1034
1140
  * Update a document by ID
@@ -1036,16 +1142,16 @@ var CollectionQueryBuilder = class {
1036
1142
  * @returns Payload CMS mutation response with doc and message
1037
1143
  */
1038
1144
  async update(id, data, options) {
1039
- const endpoint = `/api/${String(this.collection)}/${String(id)}`;
1145
+ const endpoint2 = `/api/${String(this.collection)}/${String(id)}`;
1040
1146
  if (options?.file) {
1041
1147
  return this.api.requestUpdateWithFile(
1042
- endpoint,
1148
+ endpoint2,
1043
1149
  data,
1044
1150
  options.file,
1045
1151
  options.filename
1046
1152
  );
1047
1153
  }
1048
- return this.api.requestUpdate(endpoint, data);
1154
+ return this.api.requestUpdate(endpoint2, data);
1049
1155
  }
1050
1156
  /**
1051
1157
  * Count documents
@@ -1141,8 +1247,8 @@ var CollectionClient = class extends HttpClient {
1141
1247
  * Find documents (list query)
1142
1248
  * GET /api/{collection}
1143
1249
  */
1144
- async requestFind(endpoint, options) {
1145
- const url = this.buildUrl(endpoint, options);
1250
+ async requestFind(endpoint2, options) {
1251
+ const url = this.buildUrl(endpoint2, options);
1146
1252
  const response = await this.fetchWithTracking(url, {
1147
1253
  ...this.defaultOptions,
1148
1254
  method: "GET"
@@ -1153,8 +1259,8 @@ var CollectionClient = class extends HttpClient {
1153
1259
  * Find-like response from a custom endpoint
1154
1260
  * POST /api/...custom-endpoint
1155
1261
  */
1156
- async requestFindEndpoint(endpoint, data) {
1157
- const response = await this.fetchWithTracking(endpoint, {
1262
+ async requestFindEndpoint(endpoint2, data) {
1263
+ const response = await this.fetchWithTracking(endpoint2, {
1158
1264
  ...this.defaultOptions,
1159
1265
  method: "POST",
1160
1266
  body: data ? JSON.stringify(data) : void 0
@@ -1164,8 +1270,8 @@ var CollectionClient = class extends HttpClient {
1164
1270
  /**
1165
1271
  * Find-like response from a cacheable GET custom endpoint.
1166
1272
  */
1167
- async requestFindEndpointGet(endpoint) {
1168
- const response = await this.fetchWithTracking(endpoint, {
1273
+ async requestFindEndpointGet(endpoint2) {
1274
+ const response = await this.fetchWithTracking(endpoint2, {
1169
1275
  ...this.defaultOptions,
1170
1276
  method: "GET"
1171
1277
  });
@@ -1175,8 +1281,8 @@ var CollectionClient = class extends HttpClient {
1175
1281
  * Find document by ID
1176
1282
  * GET /api/{collection}/{id}
1177
1283
  */
1178
- async requestFindById(endpoint, options) {
1179
- const url = this.buildUrl(endpoint, options);
1284
+ async requestFindById(endpoint2, options) {
1285
+ const url = this.buildUrl(endpoint2, options);
1180
1286
  const response = await this.fetchWithTracking(url, {
1181
1287
  ...this.defaultOptions,
1182
1288
  method: "GET"
@@ -1187,8 +1293,8 @@ var CollectionClient = class extends HttpClient {
1187
1293
  * Create document
1188
1294
  * POST /api/{collection}
1189
1295
  */
1190
- async requestCreate(endpoint, data) {
1191
- const response = await this.fetchWithTracking(endpoint, {
1296
+ async requestCreate(endpoint2, data) {
1297
+ const response = await this.fetchWithTracking(endpoint2, {
1192
1298
  ...this.defaultOptions,
1193
1299
  method: "POST",
1194
1300
  body: data ? JSON.stringify(data) : void 0
@@ -1199,8 +1305,8 @@ var CollectionClient = class extends HttpClient {
1199
1305
  * Update document
1200
1306
  * PATCH /api/{collection}/{id}
1201
1307
  */
1202
- async requestUpdate(endpoint, data) {
1203
- const response = await this.fetchWithTracking(endpoint, {
1308
+ async requestUpdate(endpoint2, data) {
1309
+ const response = await this.fetchWithTracking(endpoint2, {
1204
1310
  ...this.defaultOptions,
1205
1311
  method: "PATCH",
1206
1312
  body: data ? JSON.stringify(data) : void 0
@@ -1211,8 +1317,8 @@ var CollectionClient = class extends HttpClient {
1211
1317
  * Count documents
1212
1318
  * GET /api/{collection}/count
1213
1319
  */
1214
- async requestCount(endpoint, options) {
1215
- const url = this.buildUrl(endpoint, options);
1320
+ async requestCount(endpoint2, options) {
1321
+ const url = this.buildUrl(endpoint2, options);
1216
1322
  const response = await this.fetchWithTracking(url, {
1217
1323
  ...this.defaultOptions,
1218
1324
  method: "GET"
@@ -1223,8 +1329,8 @@ var CollectionClient = class extends HttpClient {
1223
1329
  * Update multiple documents (bulk update)
1224
1330
  * PATCH /api/{collection}
1225
1331
  */
1226
- async requestUpdateMany(endpoint, data) {
1227
- const response = await this.fetchWithTracking(endpoint, {
1332
+ async requestUpdateMany(endpoint2, data) {
1333
+ const response = await this.fetchWithTracking(endpoint2, {
1228
1334
  ...this.defaultOptions,
1229
1335
  method: "PATCH",
1230
1336
  body: JSON.stringify(data)
@@ -1235,8 +1341,8 @@ var CollectionClient = class extends HttpClient {
1235
1341
  * Delete document
1236
1342
  * DELETE /api/{collection}/{id}
1237
1343
  */
1238
- async requestDelete(endpoint, options) {
1239
- const url = this.buildUrl(endpoint, options);
1344
+ async requestDelete(endpoint2, options) {
1345
+ const url = this.buildUrl(endpoint2, options);
1240
1346
  const response = await this.fetchWithTracking(url, {
1241
1347
  ...this.defaultOptions,
1242
1348
  method: "DELETE"
@@ -1247,8 +1353,8 @@ var CollectionClient = class extends HttpClient {
1247
1353
  * Delete multiple documents (bulk delete)
1248
1354
  * DELETE /api/{collection}
1249
1355
  */
1250
- async requestDeleteMany(endpoint, data) {
1251
- const response = await this.fetchWithTracking(endpoint, {
1356
+ async requestDeleteMany(endpoint2, data) {
1357
+ const response = await this.fetchWithTracking(endpoint2, {
1252
1358
  ...this.defaultOptions,
1253
1359
  method: "DELETE",
1254
1360
  body: JSON.stringify(data)
@@ -1259,8 +1365,8 @@ var CollectionClient = class extends HttpClient {
1259
1365
  * Create document with file upload
1260
1366
  * POST /api/{collection} (multipart/form-data)
1261
1367
  */
1262
- async requestCreateWithFile(endpoint, data, file, filename) {
1263
- const response = await this.fetchWithTracking(endpoint, {
1368
+ async requestCreateWithFile(endpoint2, data, file, filename) {
1369
+ const response = await this.fetchWithTracking(endpoint2, {
1264
1370
  ...this.defaultOptions,
1265
1371
  method: "POST",
1266
1372
  body: buildPayloadFormData(data, file, filename)
@@ -1271,8 +1377,8 @@ var CollectionClient = class extends HttpClient {
1271
1377
  * Update document with file upload
1272
1378
  * PATCH /api/{collection}/{id} (multipart/form-data)
1273
1379
  */
1274
- async requestUpdateWithFile(endpoint, data, file, filename) {
1275
- const response = await this.fetchWithTracking(endpoint, {
1380
+ async requestUpdateWithFile(endpoint2, data, file, filename) {
1381
+ const response = await this.fetchWithTracking(endpoint2, {
1276
1382
  ...this.defaultOptions,
1277
1383
  method: "PATCH",
1278
1384
  body: buildPayloadFormData(data, file, filename)
@@ -1287,53 +1393,347 @@ var ServerCollectionClient = class extends CollectionClient {
1287
1393
  };
1288
1394
 
1289
1395
  // src/core/api/parse-response.ts
1290
- async function parseApiResponse(response, endpoint) {
1291
- let data;
1396
+ async function parseApiResponse(response, endpoint2, options = {}) {
1397
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
1398
+ return void 0;
1399
+ }
1400
+ let parsed;
1292
1401
  try {
1293
- data = await response.json();
1402
+ parsed = await response.json();
1294
1403
  } catch {
1295
1404
  throw createApiError(
1296
- `Invalid JSON response from ${endpoint}`,
1405
+ `Invalid JSON response from ${endpoint2}`,
1297
1406
  response.status,
1298
1407
  void 0,
1299
1408
  "Server returned an invalid response.",
1300
1409
  "Check if the API endpoint is available."
1301
1410
  );
1302
1411
  }
1412
+ if (parsed === null || typeof parsed !== "object") {
1413
+ return parsed;
1414
+ }
1415
+ const data = parsed;
1303
1416
  if (data.error) {
1304
1417
  const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1305
1418
  const reason = typeof data.reason === "string" ? data.reason : void 0;
1306
1419
  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;
1420
+ const retryAfter = parseRetryAfter(response).seconds;
1421
+ let error;
1309
1422
  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);
1423
+ error = createValidationError(errorMessage, data, errorMessage);
1424
+ } else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1425
+ error = createAuthError(errorMessage, data, errorMessage);
1426
+ } else if (reason === "forbidden") {
1427
+ error = createPermissionError(errorMessage, data, errorMessage);
1428
+ } else if (reason === "rate_limit_exceeded") {
1429
+ error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
1430
+ } else if (reason === "not_found") {
1431
+ error = createNotFoundError(errorMessage, data, errorMessage);
1432
+ } else if (reason === "conflict") {
1433
+ error = createConflictError(errorMessage, data, errorMessage);
1434
+ } else {
1435
+ error = createApiError(
1436
+ errorMessage,
1437
+ response.status,
1438
+ data,
1439
+ errorMessage,
1440
+ "An error occurred while processing the request."
1441
+ );
1314
1442
  }
1315
- if (reason === "forbidden") {
1316
- throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1443
+ const withRequestId = attachRequestId(error, requestId);
1444
+ if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
1445
+ throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
1446
+ }
1447
+ return data;
1448
+ }
1449
+
1450
+ // ../../internal/http-contracts/src/index.ts
1451
+ var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1452
+ var operation = (collection, method, path) => Object.freeze({
1453
+ [operationBrand]: true,
1454
+ collection,
1455
+ method,
1456
+ path
1457
+ });
1458
+ var COMMERCE_ENDPOINT_OPERATIONS = {
1459
+ products: {
1460
+ detail: operation("products", "get", "/detail"),
1461
+ detailCatalog: operation("products", "get", "/detail/catalog"),
1462
+ listingGroups: operation("products", "get", "/listing-groups"),
1463
+ listingGroupsCatalog: operation(
1464
+ "products",
1465
+ "get",
1466
+ "/listing-groups/catalog"
1467
+ ),
1468
+ listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
1469
+ listingGroupsQueryGet: operation(
1470
+ "products",
1471
+ "get",
1472
+ "/listing-groups/query"
1473
+ ),
1474
+ listingGroupsQueryCatalog: operation(
1475
+ "products",
1476
+ "get",
1477
+ "/listing-groups/query/catalog"
1478
+ ),
1479
+ stockCheck: operation("products", "post", "/stock-check"),
1480
+ stockSnapshot: operation("products", "get", "/stock"),
1481
+ upsert: operation("products", "post", "/upsert")
1482
+ },
1483
+ orders: {
1484
+ create: operation("orders", "post", "/create"),
1485
+ update: operation("orders", "post", "/update"),
1486
+ confirmPayment: operation("orders", "post", "/confirm-payment"),
1487
+ byPayment: operation("orders", "get", "/by-payment"),
1488
+ cancel: operation("orders", "post", "/cancel"),
1489
+ resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1490
+ checkout: operation("orders", "post", "/checkout"),
1491
+ createFulfillment: operation("orders", "post", "/create-fulfillment"),
1492
+ updateFulfillment: operation("orders", "post", "/update-fulfillment")
1493
+ },
1494
+ checkouts: {
1495
+ detail: operation("checkouts", "post", "/detail"),
1496
+ query: operation("checkouts", "post", "/query")
1497
+ },
1498
+ transactions: {
1499
+ update: operation("transactions", "post", "/update")
1500
+ },
1501
+ returns: {
1502
+ create: operation("returns", "post", "/create"),
1503
+ update: operation("returns", "post", "/update"),
1504
+ returnRefund: operation("returns", "post", "/return-refund")
1505
+ },
1506
+ fulfillmentOrders: {
1507
+ prepare: operation(
1508
+ "fulfillment-orders",
1509
+ "post",
1510
+ "/prepare-fulfillment-order"
1511
+ )
1512
+ },
1513
+ fulfillments: {
1514
+ bulkImport: operation("fulfillments", "post", "/bulk-import")
1515
+ },
1516
+ carts: {
1517
+ create: operation("carts", "post", "/create"),
1518
+ retrieve: operation("carts", "post", "/retrieve"),
1519
+ mine: operation("carts", "post", "/mine"),
1520
+ merge: operation("carts", "post", "/merge"),
1521
+ addItem: operation("carts", "post", "/add-item"),
1522
+ updateItem: operation("carts", "post", "/update-item"),
1523
+ removeItem: operation("carts", "post", "/remove-item"),
1524
+ updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
1525
+ updateAttributes: operation("carts", "post", "/update-attributes"),
1526
+ clear: operation("carts", "post", "/clear")
1527
+ },
1528
+ paymentSessions: {
1529
+ create: operation("payment-sessions", "post", "/create"),
1530
+ retrieve: operation("payment-sessions", "post", "/retrieve"),
1531
+ cancel: operation("payment-sessions", "post", "/cancel"),
1532
+ server: {
1533
+ create: operation("payment-sessions", "post", "/server/create"),
1534
+ retrieve: operation("payment-sessions", "post", "/server/retrieve"),
1535
+ cancel: operation("payment-sessions", "post", "/server/cancel"),
1536
+ confirm: operation("payment-sessions", "post", "/server/confirm")
1537
+ },
1538
+ custom: {
1539
+ create: operation("orders", "post", "/custom-payment-sessions"),
1540
+ confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
1317
1541
  }
1318
- if (reason === "rate_limit_exceeded") {
1319
- throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1542
+ },
1543
+ shippingPolicies: {
1544
+ calculate: operation("shipping-policies", "post", "/calculate")
1545
+ },
1546
+ discounts: {
1547
+ validate: operation("discounts", "post", "/validate")
1548
+ }
1549
+ };
1550
+ var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1551
+ subscribe: operation(null, "post", "/memberships/subscribe"),
1552
+ cancel: operation(null, "post", "/memberships/:id/cancel"),
1553
+ me: operation(null, "get", "/memberships/me")
1554
+ };
1555
+ var EVENTS_ENDPOINT_OPERATIONS = {
1556
+ occurrences: {
1557
+ range: operation("event-occurrences", "get", "/range"),
1558
+ admissionAvailability: operation(
1559
+ "event-occurrences",
1560
+ "get",
1561
+ "/admission-availability"
1562
+ )
1563
+ }
1564
+ };
1565
+ function resolveOperationTemplate(descriptor) {
1566
+ return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
1567
+ }
1568
+ function resolveOperationPath(descriptor, options) {
1569
+ const path = resolveOperationTemplate(descriptor).replace(
1570
+ /:([A-Za-z][A-Za-z0-9_]*)/g,
1571
+ (_, key) => {
1572
+ const value = options?.pathParams?.[key];
1573
+ if (value === void 0) {
1574
+ throw new TypeError(`Missing path parameter: ${key}`);
1575
+ }
1576
+ return encodeURIComponent(value);
1320
1577
  }
1321
- if (reason === "not_found") {
1322
- throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1578
+ );
1579
+ const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
1580
+ if (unresolved) {
1581
+ throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
1582
+ }
1583
+ const query = options?.query?.toString().replace(/^\?/, "");
1584
+ return query ? `${path}?${query}` : path;
1585
+ }
1586
+ function resolveOperationMethod(descriptor) {
1587
+ return descriptor.method.toUpperCase();
1588
+ }
1589
+
1590
+ // src/core/api/endpoints.ts
1591
+ var endpoint = (method, path) => ({ method, path });
1592
+ var sharedEndpoint = (descriptor) => descriptor;
1593
+ function resolveOperationMethod2(descriptor) {
1594
+ return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1595
+ }
1596
+ function resolveOperationPath2(descriptor, options) {
1597
+ if ("collection" in descriptor) {
1598
+ return resolveOperationPath(descriptor, options);
1599
+ }
1600
+ const query = options?.query?.toString().replace(/^\?/, "");
1601
+ return query ? `${descriptor.path}?${query}` : descriptor.path;
1602
+ }
1603
+ var COMMERCE_ENDPOINTS = {
1604
+ products: {
1605
+ detail: endpoint("GET", "/api/products/detail"),
1606
+ detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1607
+ listingGroups: endpoint("GET", "/api/products/listing-groups"),
1608
+ listingGroupsCatalog: endpoint(
1609
+ "GET",
1610
+ "/api/products/listing-groups/catalog"
1611
+ ),
1612
+ listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1613
+ listingGroupsQueryCatalog: endpoint(
1614
+ "GET",
1615
+ "/api/products/listing-groups/query/catalog"
1616
+ ),
1617
+ stockCheck: endpoint("POST", "/api/products/stock-check"),
1618
+ stockSnapshot: endpoint("GET", "/api/products/stock"),
1619
+ upsert: endpoint("POST", "/api/products/upsert")
1620
+ },
1621
+ orders: {
1622
+ update: endpoint("POST", "/api/orders/update"),
1623
+ byPayment: endpoint("GET", "/api/orders/by-payment"),
1624
+ cancel: endpoint("POST", "/api/orders/cancel"),
1625
+ resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1626
+ createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1627
+ updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1628
+ },
1629
+ checkouts: {
1630
+ create: endpoint("POST", "/api/orders/checkout"),
1631
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1632
+ server: {
1633
+ create: endpoint("POST", "/api/orders/checkout"),
1634
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1635
+ query: endpoint("POST", "/api/checkouts/query")
1323
1636
  }
1324
- if (reason === "conflict") {
1325
- throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1637
+ },
1638
+ returns: {
1639
+ create: endpoint("POST", "/api/returns/create"),
1640
+ update: endpoint("POST", "/api/returns/update"),
1641
+ returnRefund: endpoint("POST", "/api/returns/return-refund")
1642
+ },
1643
+ fulfillmentOrders: {
1644
+ prepare: endpoint(
1645
+ "POST",
1646
+ "/api/fulfillment-orders/prepare-fulfillment-order"
1647
+ )
1648
+ },
1649
+ fulfillments: {
1650
+ bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1651
+ },
1652
+ carts: {
1653
+ create: endpoint("POST", "/api/carts/create"),
1654
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1655
+ mine: endpoint("POST", "/api/carts/mine"),
1656
+ merge: endpoint("POST", "/api/carts/merge"),
1657
+ server: {
1658
+ // Server credentials are an authorization lane, not a second Cart
1659
+ // transport. These must stay bound to the registered shared operations.
1660
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
1661
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1662
+ mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
1663
+ merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
1664
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1665
+ updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
1666
+ removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
1667
+ updateDiscountCodes: sharedEndpoint(
1668
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
1669
+ ),
1670
+ updateAttributes: sharedEndpoint(
1671
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
1672
+ ),
1673
+ clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
1674
+ },
1675
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1676
+ updateItem: endpoint("POST", "/api/carts/update-item"),
1677
+ removeItem: endpoint("POST", "/api/carts/remove-item"),
1678
+ updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
1679
+ updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
1680
+ clear: endpoint("POST", "/api/carts/clear")
1681
+ },
1682
+ paymentSessions: {
1683
+ create: endpoint("POST", "/api/payment-sessions/create"),
1684
+ retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
1685
+ cancel: endpoint("POST", "/api/payment-sessions/cancel"),
1686
+ custom: {
1687
+ create: sharedEndpoint(
1688
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.create
1689
+ ),
1690
+ confirm: sharedEndpoint(
1691
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.confirm
1692
+ )
1693
+ },
1694
+ server: {
1695
+ create: endpoint("POST", "/api/payment-sessions/server/create"),
1696
+ retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
1697
+ cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
1698
+ confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
1326
1699
  }
1327
- throw attachRequestId(
1328
- createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1329
- requestId
1330
- );
1700
+ },
1701
+ shippingPolicies: {
1702
+ calculate: endpoint("POST", "/api/shipping-policies/calculate")
1331
1703
  }
1332
- return data;
1704
+ };
1705
+ function isCommerceEndpointDescriptor(value) {
1706
+ if (!value || typeof value !== "object") return false;
1707
+ const candidate = value;
1708
+ return typeof candidate.method === "string" && typeof candidate.path === "string";
1709
+ }
1710
+ function flattenEndpointPaths(value) {
1711
+ if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1712
+ if (!value || typeof value !== "object") return [];
1713
+ return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1714
+ }
1715
+ function flattenEndpointDescriptors(value) {
1716
+ if (isCommerceEndpointDescriptor(value)) return [value];
1717
+ if (!value || typeof value !== "object") return [];
1718
+ return Object.values(value).flatMap(
1719
+ (entry) => flattenEndpointDescriptors(entry)
1720
+ );
1333
1721
  }
1722
+ var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1723
+ var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1724
+ var MEMBERSHIP_ENDPOINTS = {
1725
+ subscribe: "/api/memberships/subscribe",
1726
+ cancel: (id) => `/api/memberships/${id}/cancel`,
1727
+ me: "/api/memberships/me"
1728
+ };
1729
+ var MEMBERSHIP_ENDPOINT_PATHS = [
1730
+ MEMBERSHIP_ENDPOINTS.subscribe,
1731
+ MEMBERSHIP_ENDPOINTS.cancel(":id"),
1732
+ MEMBERSHIP_ENDPOINTS.me
1733
+ ];
1334
1734
 
1335
1735
  // src/core/api/customer-scoped-api.ts
1336
- var CustomerScopedApi = class {
1736
+ var CustomerScopedTransport = class {
1337
1737
  constructor(apiName, options) {
1338
1738
  if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
1339
1739
  throw createConfigError(
@@ -1351,10 +1751,10 @@ var CustomerScopedApi = class {
1351
1751
  this.onUnauthorized = options.onUnauthorized;
1352
1752
  this.onRequestId = options.onRequestId;
1353
1753
  }
1354
- async request(endpoint, options) {
1754
+ async request(endpoint2, options) {
1355
1755
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1356
1756
  try {
1357
- const response = await httpFetch(endpoint, {
1757
+ const response = await httpFetch(endpoint2, {
1358
1758
  method: options.method,
1359
1759
  apiUrl: this.apiUrl,
1360
1760
  publishableKey: this.publishableKey,
@@ -1364,10 +1764,13 @@ var CustomerScopedApi = class {
1364
1764
  ...options.body !== void 0 && {
1365
1765
  body: JSON.stringify(options.body)
1366
1766
  },
1367
- ...options.headers && { headers: options.headers }
1767
+ ...options.headers && { headers: options.headers },
1768
+ ...options.errorFamily && { errorFamily: options.errorFamily }
1368
1769
  });
1369
1770
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1370
- return parseApiResponse(response, endpoint);
1771
+ return parseApiResponse(response, endpoint2, {
1772
+ errorFamily: options.errorFamily
1773
+ });
1371
1774
  } catch (err) {
1372
1775
  const id = err instanceof SDKError ? err.requestId ?? null : null;
1373
1776
  this.onRequestId?.(id);
@@ -1375,6 +1778,26 @@ var CustomerScopedApi = class {
1375
1778
  }
1376
1779
  }
1377
1780
  };
1781
+ var CustomerScopedApi = class {
1782
+ constructor(apiName, options) {
1783
+ this.transport = new CustomerScopedTransport(apiName, options);
1784
+ }
1785
+ requestEndpoint(endpoint2, body, options) {
1786
+ return this.transport.request(resolveOperationPath2(endpoint2, options), {
1787
+ method: resolveOperationMethod2(endpoint2),
1788
+ body,
1789
+ headers: options?.headers
1790
+ });
1791
+ }
1792
+ };
1793
+ var RawCustomerScopedApi = class {
1794
+ constructor(apiName, options) {
1795
+ this.transport = new CustomerScopedTransport(apiName, options);
1796
+ }
1797
+ request(endpoint2, options) {
1798
+ return this.transport.request(endpoint2, options);
1799
+ }
1800
+ };
1378
1801
 
1379
1802
  // src/core/community/community-client.ts
1380
1803
  var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
@@ -1385,7 +1808,7 @@ function unwrapPayloadDoc(value) {
1385
1808
  }
1386
1809
  return value;
1387
1810
  }
1388
- var CommunityClient = class extends CustomerScopedApi {
1811
+ var CommunityClient = class extends RawCustomerScopedApi {
1389
1812
  constructor(options) {
1390
1813
  super("CommunityClient", { ...options, requiresCredential: false });
1391
1814
  }
@@ -1429,11 +1852,11 @@ var CommunityClient = class extends CustomerScopedApi {
1429
1852
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1430
1853
  return `/api/comments/public?${urlParams.toString()}`;
1431
1854
  }
1432
- async execute(endpoint, method, body) {
1433
- return this.request(endpoint, { method, body });
1855
+ async execute(endpoint2, method, body) {
1856
+ return this.request(endpoint2, { method, body });
1434
1857
  }
1435
- async executeDoc(endpoint, method, body) {
1436
- const response = await this.execute(endpoint, method, body);
1858
+ async executeDoc(endpoint2, method, body) {
1859
+ const response = await this.execute(endpoint2, method, body);
1437
1860
  return unwrapPayloadDoc(response);
1438
1861
  }
1439
1862
  createPost(params) {
@@ -1672,140 +2095,1399 @@ var CommunityClient = class extends CustomerScopedApi {
1672
2095
  };
1673
2096
 
1674
2097
  // src/core/api/base-api.ts
1675
- var BaseApi = class {
2098
+ var ServerApiTransport = class {
1676
2099
  constructor(apiName, options) {
1677
2100
  if (!options.secretKey) {
1678
2101
  throw createConfigError(`secretKey is required for ${apiName}.`);
1679
2102
  }
1680
- this.publishableKey = requirePublishableKeyForSecret(
1681
- apiName,
1682
- options.publishableKey,
1683
- options.secretKey
2103
+ this.publishableKey = requirePublishableKeyForSecret(
2104
+ apiName,
2105
+ options.publishableKey,
2106
+ options.secretKey
2107
+ );
2108
+ this.secretKey = options.secretKey;
2109
+ this.apiUrl = options.apiUrl;
2110
+ this.onRequestId = options.onRequestId;
2111
+ }
2112
+ async request(endpoint2, body, options) {
2113
+ const method = options?.method ?? "POST";
2114
+ try {
2115
+ const response = await httpFetch(endpoint2, {
2116
+ method,
2117
+ apiUrl: this.apiUrl,
2118
+ publishableKey: this.publishableKey,
2119
+ secretKey: this.secretKey,
2120
+ ...body !== void 0 && { body: JSON.stringify(body) },
2121
+ ...options?.headers && { headers: options.headers },
2122
+ ...options?.errorFamily && { errorFamily: options.errorFamily }
2123
+ });
2124
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
2125
+ return parseApiResponse(response, endpoint2, {
2126
+ errorFamily: options?.errorFamily
2127
+ });
2128
+ } catch (err) {
2129
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
2130
+ this.onRequestId?.(id);
2131
+ throw err;
2132
+ }
2133
+ }
2134
+ };
2135
+ var BaseApi = class {
2136
+ constructor(apiName, options) {
2137
+ this.transport = new ServerApiTransport(apiName, options);
2138
+ }
2139
+ requestEndpoint(endpoint2, body, options) {
2140
+ return this.transport.request(
2141
+ resolveOperationPath2(endpoint2, options),
2142
+ body,
2143
+ {
2144
+ method: resolveOperationMethod2(endpoint2),
2145
+ headers: options?.headers
2146
+ }
2147
+ );
2148
+ }
2149
+ };
2150
+ var RawBaseApi = class {
2151
+ constructor(apiName, options) {
2152
+ this.transport = new ServerApiTransport(apiName, options);
2153
+ this.publishableKey = requirePublishableKeyForSecret(
2154
+ apiName,
2155
+ options.publishableKey,
2156
+ options.secretKey
2157
+ );
2158
+ this.secretKey = options.secretKey;
2159
+ this.apiUrl = options.apiUrl;
2160
+ this.onRequestId = options.onRequestId;
2161
+ }
2162
+ request(endpoint2, body, options) {
2163
+ return this.transport.request(endpoint2, body, options);
2164
+ }
2165
+ };
2166
+
2167
+ // src/core/community/moderation-api.ts
2168
+ var ModerationApi = class extends RawBaseApi {
2169
+ constructor(options) {
2170
+ super("ModerationApi", options);
2171
+ }
2172
+ banCustomer(params) {
2173
+ return this.request(
2174
+ "/api/community-bans/ban-bearer",
2175
+ params,
2176
+ { method: "POST" }
2177
+ );
2178
+ }
2179
+ unbanCustomer(params) {
2180
+ return this.request(
2181
+ "/api/community-bans/unban-bearer",
2182
+ params,
2183
+ { method: "POST" }
2184
+ );
2185
+ }
2186
+ };
2187
+
2188
+ // src/core/api/canonical-response.ts
2189
+ var CART_STATUSES = ["active", "completed", "abandoned"];
2190
+ var MAX_CART_LINE_QUANTITY = 99;
2191
+ var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
2192
+ var MAX_COMMERCE_ADDRESS_LENGTH = 500;
2193
+ var MAX_COMMERCE_EMAIL_LENGTH = 254;
2194
+ var MAX_COMMERCE_PHONE_LENGTH = 32;
2195
+ var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
2196
+ var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
2197
+ var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
2198
+ var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
2199
+ var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
2200
+ var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
2201
+ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2202
+ var PAYMENT_PROVIDERS = ["toss"];
2203
+ var PAYMENT_PROVIDER_STATUSES = [
2204
+ "requires_payment_method",
2205
+ "requires_action",
2206
+ "requires_confirmation",
2207
+ "initializing",
2208
+ "processing",
2209
+ "authorized",
2210
+ "canceling",
2211
+ "unknown",
2212
+ "captured",
2213
+ "failed",
2214
+ "canceled"
2215
+ ];
2216
+ var PAYMENT_FAILURE_REASONS = [
2217
+ "payment_declined",
2218
+ "authentication_failed",
2219
+ "authorization_expired",
2220
+ "payment_method_unavailable",
2221
+ "provider_terminal_failure",
2222
+ "unknown_provider_terminal_failure"
2223
+ ];
2224
+ var CART_WARNING_CODES = [
2225
+ "DISCOUNT_CODE_NOT_HONOURED",
2226
+ "DISCOUNT_CURRENTLY_INACTIVE",
2227
+ "DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
2228
+ "DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
2229
+ "DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
2230
+ "DISCOUNT_NO_ENTITLED_LINE_ITEMS",
2231
+ "DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
2232
+ "DISCOUNT_NOT_FOUND",
2233
+ "DISCOUNT_PURCHASE_NOT_IN_RANGE",
2234
+ "DISCOUNT_USAGE_LIMIT_REACHED",
2235
+ "MERCHANDISE_NOT_ENOUGH_STOCK",
2236
+ "MERCHANDISE_OUT_OF_STOCK"
2237
+ ];
2238
+ function invalidCanonicalResponse(resource, details) {
2239
+ throw createApiError(
2240
+ `Invalid canonical ${resource} response.`,
2241
+ 502,
2242
+ { resource, ...details },
2243
+ `The server returned an incompatible ${resource} response.`,
2244
+ "Verify that the Console commerce contract is deployed before using this SDK version."
2245
+ );
2246
+ }
2247
+ function fail(resource, path, expected) {
2248
+ invalidCanonicalResponse(resource, { path, expected });
2249
+ }
2250
+ function record(value, resource, path) {
2251
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2252
+ fail(resource, path, "object");
2253
+ }
2254
+ return value;
2255
+ }
2256
+ function exact(value, required, optional, resource, path) {
2257
+ for (const key of required) {
2258
+ if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
2259
+ }
2260
+ const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
2261
+ const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2262
+ if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2263
+ }
2264
+ function string(value, resource, path) {
2265
+ if (typeof value !== "string" || value.length === 0) {
2266
+ fail(resource, path, "non-empty string");
2267
+ }
2268
+ return value;
2269
+ }
2270
+ function boundedString(value, maxLength, resource, path, allowEmpty = false) {
2271
+ if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
2272
+ fail(
2273
+ resource,
2274
+ path,
2275
+ `${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
2276
+ );
2277
+ }
2278
+ return value;
2279
+ }
2280
+ function nullableString(value, resource, path) {
2281
+ if (value !== null && typeof value !== "string") {
2282
+ fail(resource, path, "string or null");
2283
+ }
2284
+ }
2285
+ function cartLineQuantity(value, resource, path) {
2286
+ const quantity = positiveInteger(value, resource, path);
2287
+ if (quantity > MAX_CART_LINE_QUANTITY) {
2288
+ fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
2289
+ }
2290
+ return quantity;
2291
+ }
2292
+ function boolean(value, resource, path) {
2293
+ if (typeof value !== "boolean") fail(resource, path, "boolean");
2294
+ }
2295
+ function safeMinor(value, resource, path) {
2296
+ if (!Number.isSafeInteger(value) || value < 0) {
2297
+ fail(resource, path, "non-negative safe integer");
2298
+ }
2299
+ return value;
2300
+ }
2301
+ function positiveInteger(value, resource, path) {
2302
+ if (!Number.isSafeInteger(value) || value <= 0) {
2303
+ fail(resource, path, "positive safe integer");
2304
+ }
2305
+ return value;
2306
+ }
2307
+ function enumValue(value, values, resource, path) {
2308
+ if (typeof value !== "string" || !values.includes(value)) {
2309
+ fail(resource, path, values.join(" | "));
2310
+ }
2311
+ return value;
2312
+ }
2313
+ function timestamp(value, resource, path) {
2314
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
2315
+ fail(resource, path, "ISO 8601 timestamp with offset");
2316
+ }
2317
+ }
2318
+ function currency(value, resource, path) {
2319
+ if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
2320
+ fail(resource, path, "three-letter uppercase currency code");
2321
+ }
2322
+ }
2323
+ function array(value, resource, path) {
2324
+ if (!Array.isArray(value)) fail(resource, path, "array");
2325
+ return value;
2326
+ }
2327
+ function optionalNullableNumber(value, resource, path) {
2328
+ if (value !== void 0 && value !== null && typeof value !== "number") {
2329
+ fail(resource, path, "number or null");
2330
+ }
2331
+ }
2332
+ function validateMediaSize(value, resource, path) {
2333
+ const item = record(value, resource, path);
2334
+ exact(
2335
+ item,
2336
+ [],
2337
+ ["width", "height", "mimeType", "filename", "url"],
2338
+ resource,
2339
+ path
2340
+ );
2341
+ optionalNullableNumber(item.width, resource, `${path}.width`);
2342
+ optionalNullableNumber(item.height, resource, `${path}.height`);
2343
+ for (const key of ["mimeType", "filename", "url"]) {
2344
+ if (item[key] !== void 0)
2345
+ nullableString(item[key], resource, `${path}.${key}`);
2346
+ }
2347
+ }
2348
+ function validateMedia(value, resource, path) {
2349
+ if (typeof value === "string") return;
2350
+ const media = record(value, resource, path);
2351
+ exact(
2352
+ media,
2353
+ [],
2354
+ ["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
2355
+ resource,
2356
+ path
2357
+ );
2358
+ if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
2359
+ fail(resource, `${path}.id`, "string, number, or null");
2360
+ }
2361
+ for (const key of ["alt", "mimeType", "filename", "url"]) {
2362
+ if (media[key] !== void 0)
2363
+ nullableString(media[key], resource, `${path}.${key}`);
2364
+ }
2365
+ optionalNullableNumber(media.width, resource, `${path}.width`);
2366
+ optionalNullableNumber(media.height, resource, `${path}.height`);
2367
+ if (media.sizes !== void 0) {
2368
+ const sizes = record(media.sizes, resource, `${path}.sizes`);
2369
+ Object.entries(sizes).forEach(
2370
+ ([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
2371
+ );
2372
+ }
2373
+ }
2374
+ function validateReference(value, resource, path) {
2375
+ const ref = record(value, resource, path);
2376
+ exact(ref, ["id", "title", "handle", "image"], [], resource, path);
2377
+ string(ref.id, resource, `${path}.id`);
2378
+ string(ref.title, resource, `${path}.title`);
2379
+ if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
2380
+ if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
2381
+ }
2382
+ function validateAdmission(value, resource, path) {
2383
+ const admission = record(value, resource, path);
2384
+ exact(
2385
+ admission,
2386
+ ["eventId", "occurrenceId", "admissionTypeId"],
2387
+ [],
2388
+ resource,
2389
+ path
2390
+ );
2391
+ string(admission.eventId, resource, `${path}.eventId`);
2392
+ string(admission.occurrenceId, resource, `${path}.occurrenceId`);
2393
+ string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
2394
+ }
2395
+ function compareAdmissions(left, right) {
2396
+ for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
2397
+ if (left[field] < right[field]) return -1;
2398
+ if (left[field] > right[field]) return 1;
2399
+ }
2400
+ return 0;
2401
+ }
2402
+ function validateAdmissions(value, resource, path) {
2403
+ const admissions = array(value, resource, path);
2404
+ if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
2405
+ let prior;
2406
+ admissions.forEach((admission, index) => {
2407
+ validateAdmission(admission, resource, `${path}[${index}]`);
2408
+ const item = admission;
2409
+ const comparison = prior ? compareAdmissions(item, prior) : void 0;
2410
+ if (comparison !== void 0 && comparison <= 0) {
2411
+ fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
2412
+ }
2413
+ prior = item;
2414
+ });
2415
+ }
2416
+ function validateAttributes(value, resource, path) {
2417
+ const attributes = array(value, resource, path);
2418
+ if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
2419
+ const keys = /* @__PURE__ */ new Set();
2420
+ attributes.forEach((value2, index) => {
2421
+ const itemPath = `${path}[${index}]`;
2422
+ const attribute = record(value2, resource, itemPath);
2423
+ exact(attribute, ["key", "value"], [], resource, itemPath);
2424
+ const key = string(attribute.key, resource, `${itemPath}.key`);
2425
+ if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
2426
+ fail(
2427
+ resource,
2428
+ `${itemPath}.key`,
2429
+ "unique, non-reserved key of at most 40 characters"
2430
+ );
2431
+ }
2432
+ keys.add(key);
2433
+ if (typeof attribute.value !== "string" || attribute.value.length > 500) {
2434
+ fail(resource, `${itemPath}.value`, "string of at most 500 characters");
2435
+ }
2436
+ });
2437
+ }
2438
+ function validateCustomer(value, resource, path) {
2439
+ const customer = record(value, resource, path);
2440
+ exact(customer, ["email"], ["name", "phone"], resource, path);
2441
+ const email = boundedString(
2442
+ customer.email,
2443
+ MAX_COMMERCE_EMAIL_LENGTH,
2444
+ resource,
2445
+ `${path}.email`
2446
+ );
2447
+ if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
2448
+ email
2449
+ )) {
2450
+ fail(resource, `${path}.email`, "email address");
2451
+ }
2452
+ if (customer.name !== void 0)
2453
+ boundedString(
2454
+ customer.name,
2455
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2456
+ resource,
2457
+ `${path}.name`
2458
+ );
2459
+ if (customer.phone !== void 0)
2460
+ boundedString(
2461
+ customer.phone,
2462
+ MAX_COMMERCE_PHONE_LENGTH,
2463
+ resource,
2464
+ `${path}.phone`
2465
+ );
2466
+ }
2467
+ function validateShippingAddress(value, resource, path) {
2468
+ const address = record(value, resource, path);
2469
+ exact(
2470
+ address,
2471
+ ["recipientName", "phone", "postalCode", "address", "detailAddress"],
2472
+ ["countryCode", "regionCode", "deliveryMessage"],
2473
+ resource,
2474
+ path
2475
+ );
2476
+ boundedString(
2477
+ address.recipientName,
2478
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2479
+ resource,
2480
+ `${path}.recipientName`
2481
+ );
2482
+ boundedString(
2483
+ address.phone,
2484
+ MAX_COMMERCE_PHONE_LENGTH,
2485
+ resource,
2486
+ `${path}.phone`
2487
+ );
2488
+ boundedString(
2489
+ address.postalCode,
2490
+ MAX_COMMERCE_POSTAL_CODE_LENGTH,
2491
+ resource,
2492
+ `${path}.postalCode`
2493
+ );
2494
+ for (const key of ["address", "detailAddress"]) {
2495
+ boundedString(
2496
+ address[key],
2497
+ MAX_COMMERCE_ADDRESS_LENGTH,
2498
+ resource,
2499
+ `${path}.${key}`
2500
+ );
2501
+ }
2502
+ if (address.countryCode !== void 0) {
2503
+ if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
2504
+ fail(resource, `${path}.countryCode`, "two-letter country code");
2505
+ }
2506
+ }
2507
+ if (address.regionCode !== void 0) {
2508
+ if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
2509
+ fail(
2510
+ resource,
2511
+ `${path}.regionCode`,
2512
+ "trimmed string of at most 64 characters"
2513
+ );
2514
+ }
2515
+ }
2516
+ if (address.deliveryMessage !== void 0) {
2517
+ boundedString(
2518
+ address.deliveryMessage,
2519
+ MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
2520
+ resource,
2521
+ `${path}.deliveryMessage`,
2522
+ true
2523
+ );
2524
+ }
2525
+ }
2526
+ function validateOrderReference(value, resource, path) {
2527
+ const order = record(value, resource, path);
2528
+ exact(order, ["id", "orderNumber"], [], resource, path);
2529
+ string(order.id, resource, `${path}.id`);
2530
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2531
+ }
2532
+ function validateIntegrationMetadata(value, resource, path) {
2533
+ const metadata = record(value, resource, path);
2534
+ if (Object.keys(metadata).length > 50)
2535
+ fail(resource, path, "at most 50 entries");
2536
+ Object.entries(metadata).forEach(([key, entry]) => {
2537
+ if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
2538
+ fail(resource, `${path}.${key}`, "valid metadata key");
2539
+ }
2540
+ if (typeof entry !== "string" || entry.length > 500) {
2541
+ fail(resource, `${path}.${key}`, "string of at most 500 characters");
2542
+ }
2543
+ });
2544
+ }
2545
+ function validateCartItem(value, resource, path) {
2546
+ const item = record(value, resource, path);
2547
+ exact(
2548
+ item,
2549
+ [
2550
+ "id",
2551
+ "product",
2552
+ "variant",
2553
+ "admissions",
2554
+ "quantity",
2555
+ "unitPriceMinor",
2556
+ "discountMinor",
2557
+ "estimatedLineTotalMinor",
2558
+ "requiresShipping"
2559
+ ],
2560
+ [],
2561
+ resource,
2562
+ path
2563
+ );
2564
+ string(item.id, resource, `${path}.id`);
2565
+ validateReference(item.product, resource, `${path}.product`);
2566
+ validateReference(item.variant, resource, `${path}.variant`);
2567
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2568
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2569
+ const unitPrice = safeMinor(
2570
+ item.unitPriceMinor,
2571
+ resource,
2572
+ `${path}.unitPriceMinor`
2573
+ );
2574
+ const discount = safeMinor(
2575
+ item.discountMinor,
2576
+ resource,
2577
+ `${path}.discountMinor`
2578
+ );
2579
+ const estimatedLineTotal = safeMinor(
2580
+ item.estimatedLineTotalMinor,
2581
+ resource,
2582
+ `${path}.estimatedLineTotalMinor`
2583
+ );
2584
+ const quantity = item.quantity;
2585
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2586
+ if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
2587
+ fail(
2588
+ resource,
2589
+ `${path}.estimatedLineTotalMinor`,
2590
+ "unitPriceMinor * quantity - discountMinor"
2591
+ );
2592
+ }
2593
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2594
+ }
2595
+ function validatePublicCart(value, resource = "Cart") {
2596
+ const cart = record(value, resource, "$");
2597
+ exact(
2598
+ cart,
2599
+ [
2600
+ "id",
2601
+ "status",
2602
+ "revision",
2603
+ "currency",
2604
+ "market",
2605
+ "subtotalMinor",
2606
+ "discountMinor",
2607
+ "estimatedTotalMinor",
2608
+ "discountCodes",
2609
+ "attributes",
2610
+ "items",
2611
+ "expiresAt",
2612
+ "createdAt",
2613
+ "updatedAt"
2614
+ ],
2615
+ [],
2616
+ resource,
2617
+ "$"
2618
+ );
2619
+ string(cart.id, resource, "$.id");
2620
+ enumValue(cart.status, CART_STATUSES, resource, "$.status");
2621
+ safeMinor(cart.revision, resource, "$.revision");
2622
+ currency(cart.currency, resource, "$.currency");
2623
+ const market = record(cart.market, resource, "$.market");
2624
+ exact(market, ["id", "handle", "name"], [], resource, "$.market");
2625
+ for (const key of ["id", "handle", "name"])
2626
+ string(market[key], resource, `$.market.${key}`);
2627
+ const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
2628
+ const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
2629
+ const estimatedTotal = safeMinor(
2630
+ cart.estimatedTotalMinor,
2631
+ resource,
2632
+ "$.estimatedTotalMinor"
2633
+ );
2634
+ array(cart.discountCodes, resource, "$.discountCodes").forEach(
2635
+ (value2, index) => {
2636
+ const itemPath = `$.discountCodes[${index}]`;
2637
+ const code = record(value2, resource, itemPath);
2638
+ exact(code, ["code", "applicable"], [], resource, itemPath);
2639
+ boundedString(
2640
+ code.code,
2641
+ MAX_CART_DISCOUNT_CODE_LENGTH,
2642
+ resource,
2643
+ `${itemPath}.code`
2644
+ );
2645
+ boolean(code.applicable, resource, `${itemPath}.applicable`);
2646
+ }
2647
+ );
2648
+ validateAttributes(cart.attributes, resource, "$.attributes");
2649
+ const items = array(cart.items, resource, "$.items");
2650
+ items.forEach(
2651
+ (item, index) => validateCartItem(item, resource, `$.items[${index}]`)
2652
+ );
2653
+ const expectedSubtotal = items.reduce((total, value2) => {
2654
+ const item = value2;
2655
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2656
+ }, 0n);
2657
+ const expectedDiscount = items.reduce((total, value2) => {
2658
+ const item = value2;
2659
+ return total + BigInt(item.discountMinor);
2660
+ }, 0n);
2661
+ if (BigInt(subtotal) !== expectedSubtotal) {
2662
+ fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
2663
+ }
2664
+ if (BigInt(discount) !== expectedDiscount) {
2665
+ fail(resource, "$.discountMinor", "sum of cart line discounts");
2666
+ }
2667
+ if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
2668
+ fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
2669
+ }
2670
+ timestamp(cart.expiresAt, resource, "$.expiresAt");
2671
+ timestamp(cart.createdAt, resource, "$.createdAt");
2672
+ timestamp(cart.updatedAt, resource, "$.updatedAt");
2673
+ return value;
2674
+ }
2675
+ function validateWarnings(value, resource, path) {
2676
+ array(value, resource, path).forEach((value2, index) => {
2677
+ const itemPath = `${path}[${index}]`;
2678
+ const warning = record(value2, resource, itemPath);
2679
+ exact(warning, ["code", "message", "target"], [], resource, itemPath);
2680
+ enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
2681
+ string(warning.message, resource, `${itemPath}.message`);
2682
+ string(warning.target, resource, `${itemPath}.target`);
2683
+ });
2684
+ }
2685
+ function validateCartMutationResult(value) {
2686
+ const result = record(value, "Cart mutation result", "$");
2687
+ exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
2688
+ validatePublicCart(result.cart);
2689
+ validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
2690
+ return value;
2691
+ }
2692
+ function validateCreateCartResult(value) {
2693
+ const result = record(value, "Cart create result", "$");
2694
+ exact(
2695
+ result,
2696
+ ["cart", "warnings", "cartToken"],
2697
+ [],
2698
+ "Cart create result",
2699
+ "$"
2700
+ );
2701
+ const cart = record(result.cart, "Cart create result", "$.cart");
2702
+ validatePublicCart(cart);
2703
+ if (cart.revision !== 0) {
2704
+ fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
2705
+ }
2706
+ validateWarnings(result.warnings, "Cart create result", "$.warnings");
2707
+ boundedString(
2708
+ result.cartToken,
2709
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2710
+ "Cart create result",
2711
+ "$.cartToken"
2712
+ );
2713
+ return value;
2714
+ }
2715
+ function validateCartMineResult(value) {
2716
+ const result = record(value, "Cart mine result", "$");
2717
+ exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
2718
+ if (result.cart === null || result.cartToken === null) {
2719
+ if (result.cart !== null || result.cartToken !== null) {
2720
+ fail("Cart mine result", "$", "cart and cartToken must both be null");
2721
+ }
2722
+ } else {
2723
+ validatePublicCart(result.cart);
2724
+ boundedString(
2725
+ result.cartToken,
2726
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2727
+ "Cart mine result",
2728
+ "$.cartToken"
2729
+ );
2730
+ }
2731
+ return value;
2732
+ }
2733
+ function validateCartMergeResult(value) {
2734
+ const result = record(value, "Cart merge result", "$");
2735
+ exact(
2736
+ result,
2737
+ ["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
2738
+ [],
2739
+ "Cart merge result",
2740
+ "$"
2741
+ );
2742
+ validatePublicCart(result.cart);
2743
+ validateWarnings(result.warnings, "Cart merge result", "$.warnings");
2744
+ boundedString(
2745
+ result.cartToken,
2746
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2747
+ "Cart merge result",
2748
+ "$.cartToken"
2749
+ );
2750
+ const resolution = enumValue(
2751
+ result.resolution,
2752
+ ["unchanged", "claimed", "merged"],
2753
+ "Cart merge result",
2754
+ "$.resolution"
2755
+ );
2756
+ boolean(result.merged, "Cart merge result", "$.merged");
2757
+ boolean(result.claimed, "Cart merge result", "$.claimed");
2758
+ const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
2759
+ if (result.merged !== expected[0] || result.claimed !== expected[1]) {
2760
+ fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
2761
+ }
2762
+ return value;
2763
+ }
2764
+ function validateCheckoutItem(value, resource, path) {
2765
+ const item = record(value, resource, path);
2766
+ exact(
2767
+ item,
2768
+ [
2769
+ "id",
2770
+ "product",
2771
+ "variant",
2772
+ "productTitle",
2773
+ "variantTitle",
2774
+ "sku",
2775
+ "admissions",
2776
+ "quantity",
2777
+ "unitPriceMinor",
2778
+ "discountMinor",
2779
+ "lineTotalMinor",
2780
+ "requiresShipping"
2781
+ ],
2782
+ [],
2783
+ resource,
2784
+ path
2785
+ );
2786
+ string(item.id, resource, `${path}.id`);
2787
+ validateReference(item.product, resource, `${path}.product`);
2788
+ validateReference(item.variant, resource, `${path}.variant`);
2789
+ string(item.productTitle, resource, `${path}.productTitle`);
2790
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2791
+ nullableString(item.sku, resource, `${path}.sku`);
2792
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2793
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2794
+ const unitPrice = safeMinor(
2795
+ item.unitPriceMinor,
2796
+ resource,
2797
+ `${path}.unitPriceMinor`
2798
+ );
2799
+ const discount = safeMinor(
2800
+ item.discountMinor,
2801
+ resource,
2802
+ `${path}.discountMinor`
2803
+ );
2804
+ const lineTotal = safeMinor(
2805
+ item.lineTotalMinor,
2806
+ resource,
2807
+ `${path}.lineTotalMinor`
2808
+ );
2809
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
2810
+ if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
2811
+ fail(
2812
+ resource,
2813
+ `${path}.lineTotalMinor`,
2814
+ "unitPriceMinor * quantity - discountMinor"
2815
+ );
2816
+ }
2817
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2818
+ }
2819
+ function validateCheckoutAmounts(value, resource, path) {
2820
+ const amounts = record(value, resource, path);
2821
+ exact(
2822
+ amounts,
2823
+ [
2824
+ "currency",
2825
+ "subtotalMinor",
2826
+ "shippingMinor",
2827
+ "discountMinor",
2828
+ "totalMinor"
2829
+ ],
2830
+ [],
2831
+ resource,
2832
+ path
2833
+ );
2834
+ currency(amounts.currency, resource, `${path}.currency`);
2835
+ const subtotal = safeMinor(
2836
+ amounts.subtotalMinor,
2837
+ resource,
2838
+ `${path}.subtotalMinor`
2839
+ );
2840
+ const shipping = safeMinor(
2841
+ amounts.shippingMinor,
2842
+ resource,
2843
+ `${path}.shippingMinor`
2844
+ );
2845
+ const discount = safeMinor(
2846
+ amounts.discountMinor,
2847
+ resource,
2848
+ `${path}.discountMinor`
2849
+ );
2850
+ const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
2851
+ if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
2852
+ fail(
2853
+ resource,
2854
+ `${path}.totalMinor`,
2855
+ "subtotalMinor + shippingMinor - discountMinor"
2856
+ );
2857
+ }
2858
+ }
2859
+ function validatePaymentSessionReference(value, resource, path) {
2860
+ const session = record(value, resource, path);
2861
+ exact(session, ["id", "provider", "providerStatus"], [], resource, path);
2862
+ string(session.id, resource, `${path}.id`);
2863
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
2864
+ enumValue(
2865
+ session.providerStatus,
2866
+ PAYMENT_PROVIDER_STATUSES,
2867
+ resource,
2868
+ `${path}.providerStatus`
2869
+ );
2870
+ }
2871
+ function checkoutVariantKeys(status, placedVia) {
2872
+ const base = [
2873
+ "id",
2874
+ "amounts",
2875
+ "items",
2876
+ "customerSnapshot",
2877
+ "shippingAddress",
2878
+ "attributes",
2879
+ "expiresAt",
2880
+ "createdAt",
2881
+ "updatedAt",
2882
+ "status",
2883
+ "paymentState",
2884
+ "order"
2885
+ ];
2886
+ if (status === "open") return { required: base, optional: [] };
2887
+ if (status === "abandoned") {
2888
+ return {
2889
+ required: [...base, "abandonedAt", "abandonedReason"],
2890
+ optional: []
2891
+ };
2892
+ }
2893
+ return placedVia === "late_capture" ? {
2894
+ required: [
2895
+ ...base,
2896
+ "placedAt",
2897
+ "placedVia",
2898
+ "abandonedAt",
2899
+ "abandonedReason"
2900
+ ],
2901
+ optional: []
2902
+ } : { required: [...base, "placedAt"], optional: [] };
2903
+ }
2904
+ function validateCheckoutCore(value, resource, list, server) {
2905
+ const checkout = record(value, resource, "$");
2906
+ const status = enumValue(
2907
+ checkout.status,
2908
+ CHECKOUT_STATUSES,
2909
+ resource,
2910
+ "$.status"
2911
+ );
2912
+ const keys = checkoutVariantKeys(status, checkout.placedVia);
2913
+ if (list) {
2914
+ keys.required = keys.required.filter(
2915
+ (key) => !["items", "shippingAddress", "attributes"].includes(key)
2916
+ );
2917
+ keys.required.push("clientReferenceId");
2918
+ } else if (server) {
2919
+ keys.required.push("clientReferenceId", "integrationMetadata");
2920
+ }
2921
+ exact(checkout, keys.required, keys.optional, resource, "$");
2922
+ string(checkout.id, resource, "$.id");
2923
+ validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
2924
+ if (!list) {
2925
+ const items = array(checkout.items, resource, "$.items");
2926
+ if (items.length === 0) fail(resource, "$.items", "non-empty array");
2927
+ items.forEach(
2928
+ (item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
2929
+ );
2930
+ const expectedSubtotal = items.reduce((total, value2) => {
2931
+ const item = value2;
2932
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2933
+ }, 0n);
2934
+ const expectedDiscount = items.reduce((total, value2) => {
2935
+ const item = value2;
2936
+ return total + BigInt(item.discountMinor);
2937
+ }, 0n);
2938
+ const amounts = checkout.amounts;
2939
+ if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
2940
+ fail(
2941
+ resource,
2942
+ "$.amounts.subtotalMinor",
2943
+ "sum of undiscounted checkout line totals"
2944
+ );
2945
+ }
2946
+ if (BigInt(amounts.discountMinor) !== expectedDiscount) {
2947
+ fail(
2948
+ resource,
2949
+ "$.amounts.discountMinor",
2950
+ "sum of checkout line discounts"
2951
+ );
2952
+ }
2953
+ if (checkout.shippingAddress !== null) {
2954
+ validateShippingAddress(
2955
+ checkout.shippingAddress,
2956
+ resource,
2957
+ "$.shippingAddress"
2958
+ );
2959
+ }
2960
+ validateAttributes(checkout.attributes, resource, "$.attributes");
2961
+ }
2962
+ validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
2963
+ timestamp(checkout.expiresAt, resource, "$.expiresAt");
2964
+ timestamp(checkout.createdAt, resource, "$.createdAt");
2965
+ timestamp(checkout.updatedAt, resource, "$.updatedAt");
2966
+ const paymentState = record(checkout.paymentState, resource, "$.paymentState");
2967
+ exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
2968
+ if (status === "open") {
2969
+ if (paymentState.activePaymentSession !== null) {
2970
+ validatePaymentSessionReference(
2971
+ paymentState.activePaymentSession,
2972
+ resource,
2973
+ "$.paymentState.activePaymentSession"
2974
+ );
2975
+ }
2976
+ if (checkout.order !== null)
2977
+ fail(resource, "$.order", "null for open Checkout");
2978
+ } else {
2979
+ if (paymentState.activePaymentSession !== null) {
2980
+ fail(
2981
+ resource,
2982
+ "$.paymentState.activePaymentSession",
2983
+ "null for spent Checkout"
2984
+ );
2985
+ }
2986
+ if (status === "placed") {
2987
+ timestamp(checkout.placedAt, resource, "$.placedAt");
2988
+ validateOrderReference(checkout.order, resource, "$.order");
2989
+ if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
2990
+ fail(resource, "$.placedVia", "late_capture");
2991
+ }
2992
+ if (checkout.placedVia === "late_capture") {
2993
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2994
+ enumValue(
2995
+ checkout.abandonedReason,
2996
+ ABANDONED_REASONS,
2997
+ resource,
2998
+ "$.abandonedReason"
2999
+ );
3000
+ }
3001
+ } else {
3002
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
3003
+ enumValue(
3004
+ checkout.abandonedReason,
3005
+ ABANDONED_REASONS,
3006
+ resource,
3007
+ "$.abandonedReason"
3008
+ );
3009
+ if (checkout.order !== null)
3010
+ fail(resource, "$.order", "null for abandoned Checkout");
3011
+ }
3012
+ }
3013
+ if (list || server) {
3014
+ if (checkout.clientReferenceId !== null) {
3015
+ boundedString(
3016
+ checkout.clientReferenceId,
3017
+ MAX_COMMERCE_RESOURCE_ID_LENGTH,
3018
+ resource,
3019
+ "$.clientReferenceId"
3020
+ );
3021
+ }
3022
+ }
3023
+ if (server)
3024
+ validateIntegrationMetadata(
3025
+ checkout.integrationMetadata,
3026
+ resource,
3027
+ "$.integrationMetadata"
3028
+ );
3029
+ }
3030
+ function validatePublicCheckout(value) {
3031
+ validateCheckoutCore(value, "Checkout", false, false);
3032
+ return value;
3033
+ }
3034
+ function validateServerCheckout(value) {
3035
+ validateCheckoutCore(value, "Server Checkout", false, true);
3036
+ return value;
3037
+ }
3038
+ function validateCreateCheckoutResult(value, server) {
3039
+ const resource = server ? "Server Checkout create result" : "Checkout create result";
3040
+ const result = record(value, resource, "$");
3041
+ exact(result, ["checkout", "checkoutToken"], [], resource, "$");
3042
+ if (server) validateServerCheckout(result.checkout);
3043
+ else validatePublicCheckout(result.checkout);
3044
+ boundedString(
3045
+ result.checkoutToken,
3046
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3047
+ resource,
3048
+ "$.checkoutToken"
3049
+ );
3050
+ return value;
3051
+ }
3052
+ function validateCheckoutQueryResult(value) {
3053
+ const result = record(value, "Checkout query result", "$");
3054
+ exact(
3055
+ result,
3056
+ ["data", "hasMore", "nextCursor"],
3057
+ [],
3058
+ "Checkout query result",
3059
+ "$"
3060
+ );
3061
+ array(result.data, "Checkout query result", "$.data").forEach(
3062
+ (item) => validateCheckoutCore(item, "Checkout list item", true, false)
3063
+ );
3064
+ boolean(result.hasMore, "Checkout query result", "$.hasMore");
3065
+ if (result.nextCursor !== null)
3066
+ boundedString(
3067
+ result.nextCursor,
3068
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3069
+ "Checkout query result",
3070
+ "$.nextCursor"
3071
+ );
3072
+ if (result.hasMore === true && result.nextCursor === null) {
3073
+ fail(
3074
+ "Checkout query result",
3075
+ "$.nextCursor",
3076
+ "non-null when hasMore is true"
3077
+ );
3078
+ }
3079
+ return value;
3080
+ }
3081
+ function validateMoney(value, resource, path) {
3082
+ const money = record(value, resource, path);
3083
+ exact(money, ["amountMinor", "currency"], [], resource, path);
3084
+ safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3085
+ currency(money.currency, resource, `${path}.currency`);
3086
+ }
3087
+ function validateCustomPaymentSession(value) {
3088
+ const resource = "custom PaymentSession";
3089
+ const session = record(value, resource, "$");
3090
+ exact(
3091
+ session,
3092
+ ["id", "provider", "providerSessionId", "money"],
3093
+ [],
3094
+ resource,
3095
+ "$"
3096
+ );
3097
+ string(session.id, resource, "$.id");
3098
+ const provider = string(session.provider, resource, "$.provider");
3099
+ if (!/^[a-z0-9][a-z0-9_-]{0,63}$/i.test(provider)) {
3100
+ fail(resource, "$.provider", "provider slug");
3101
+ }
3102
+ string(session.providerSessionId, resource, "$.providerSessionId");
3103
+ validateMoney(session.money, resource, "$.money");
3104
+ return value;
3105
+ }
3106
+ function validateConfirmCustomPaymentSessionResponse(value) {
3107
+ const resource = "custom PaymentSession confirmation";
3108
+ const result = record(value, resource, "$");
3109
+ exact(
3110
+ result,
3111
+ ["orderId", "transactionId", "status"],
3112
+ ["alreadyConfirmed"],
3113
+ resource,
3114
+ "$"
3115
+ );
3116
+ string(result.orderId, resource, "$.orderId");
3117
+ string(result.transactionId, resource, "$.transactionId");
3118
+ if (result.status !== "paid") fail(resource, "$.status", "paid");
3119
+ if (result.alreadyConfirmed !== void 0) {
3120
+ boolean(result.alreadyConfirmed, resource, "$.alreadyConfirmed");
3121
+ }
3122
+ return value;
3123
+ }
3124
+ function validateCaptureEvidence(value, resource, path) {
3125
+ const evidence = record(value, resource, path);
3126
+ exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
3127
+ safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
3128
+ currency(evidence.currency, resource, `${path}.currency`);
3129
+ timestamp(evidence.observedAt, resource, `${path}.observedAt`);
3130
+ }
3131
+ function validateNoReconciliation(value, resource, path) {
3132
+ const reconciliation = record(value, resource, path);
3133
+ exact(reconciliation, ["status"], [], resource, path);
3134
+ if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
3135
+ }
3136
+ function validateRequiredReconciliation(value, allowed, resource, path) {
3137
+ const reconciliation = record(value, resource, path);
3138
+ exact(reconciliation, ["status", "reasons"], [], resource, path);
3139
+ if (reconciliation.status !== "required")
3140
+ fail(resource, `${path}.status`, "required");
3141
+ const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
3142
+ if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
3143
+ let previous = -1;
3144
+ reasons.forEach((reason, index) => {
3145
+ const current = allowed.indexOf(reason);
3146
+ if (current < 0 || current <= previous) {
3147
+ fail(
3148
+ resource,
3149
+ `${path}.reasons[${index}]`,
3150
+ "unique canonical-sorted reconciliation reason"
3151
+ );
3152
+ }
3153
+ previous = current;
3154
+ });
3155
+ }
3156
+ function validateNextAction(value, resource, path) {
3157
+ const action = record(value, resource, path);
3158
+ exact(
3159
+ action,
3160
+ [
3161
+ "type",
3162
+ "clientKey",
3163
+ "paymentMethodVariantKey",
3164
+ "agreementVariantKey",
3165
+ "providerOrderId",
3166
+ "providerCustomerKey",
3167
+ "orderName"
3168
+ ],
3169
+ ["customerName", "customerEmail"],
3170
+ resource,
3171
+ path
3172
+ );
3173
+ if (action.type !== "toss_widget")
3174
+ fail(resource, `${path}.type`, "toss_widget");
3175
+ for (const key of [
3176
+ "clientKey",
3177
+ "paymentMethodVariantKey",
3178
+ "agreementVariantKey"
3179
+ ]) {
3180
+ boundedString(action[key], 255, resource, `${path}.${key}`);
3181
+ }
3182
+ string(action.providerOrderId, resource, `${path}.providerOrderId`);
3183
+ string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
3184
+ boundedString(
3185
+ action.orderName,
3186
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3187
+ resource,
3188
+ `${path}.orderName`
3189
+ );
3190
+ if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
3191
+ fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
3192
+ }
3193
+ 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(
3194
+ action.providerCustomerKey
3195
+ )) {
3196
+ fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
3197
+ }
3198
+ if (action.customerName !== void 0)
3199
+ boundedString(
3200
+ action.customerName,
3201
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3202
+ resource,
3203
+ `${path}.customerName`
3204
+ );
3205
+ if (action.customerEmail !== void 0)
3206
+ validateCustomer({ email: action.customerEmail }, resource, path);
3207
+ }
3208
+ function validatePublicPaymentSession(value) {
3209
+ const resource = "PaymentSession";
3210
+ const session = record(value, resource, "$");
3211
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
3212
+ const status = enumValue(
3213
+ session.providerStatus,
3214
+ PAYMENT_PROVIDER_STATUSES,
3215
+ resource,
3216
+ "$.providerStatus"
3217
+ );
3218
+ const common = [
3219
+ "id",
3220
+ "money",
3221
+ "expiresAt",
3222
+ "sessionRole",
3223
+ "provider",
3224
+ "providerStatus",
3225
+ "presentationStatus",
3226
+ "finalizationStatus",
3227
+ "reconciliation",
3228
+ "order"
3229
+ ];
3230
+ const optional = [];
3231
+ if (status === "requires_payment_method" || status === "requires_action")
3232
+ optional.push("nextAction");
3233
+ else if (status === "captured") common.push("providerEvidence");
3234
+ else if (status === "failed") common.push("failure");
3235
+ else if (status === "canceled") common.push("cancellationReason");
3236
+ exact(session, common, optional, resource, "$");
3237
+ string(session.id, resource, "$.id");
3238
+ validateMoney(session.money, resource, "$.money");
3239
+ if (session.expiresAt !== null)
3240
+ timestamp(session.expiresAt, resource, "$.expiresAt");
3241
+ if (status === "requires_payment_method" || status === "requires_action") {
3242
+ if (session.sessionRole === "active") {
3243
+ if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
3244
+ fail(resource, "$", "actionable active not-ready state");
3245
+ }
3246
+ if (!("nextAction" in session))
3247
+ fail(resource, "$.nextAction", "required field");
3248
+ validateNextAction(session.nextAction, resource, "$.nextAction");
3249
+ } else if (session.sessionRole === "residual") {
3250
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3251
+ fail(resource, "$", "suppressed residual not-ready state");
3252
+ }
3253
+ if ("nextAction" in session)
3254
+ fail(resource, "$.nextAction", "absent for suppressed state");
3255
+ } else fail(resource, "$.sessionRole", "active | residual");
3256
+ validateNoReconciliation(
3257
+ session.reconciliation,
3258
+ resource,
3259
+ "$.reconciliation"
3260
+ );
3261
+ if (session.order !== null) fail(resource, "$.order", "null");
3262
+ } else if ([
3263
+ "requires_confirmation",
3264
+ "initializing",
3265
+ "processing",
3266
+ "authorized",
3267
+ "canceling"
3268
+ ].includes(status)) {
3269
+ enumValue(
3270
+ session.sessionRole,
3271
+ ["active", "residual"],
3272
+ resource,
3273
+ "$.sessionRole"
3274
+ );
3275
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3276
+ fail(resource, "$", "suppressed not-ready state");
3277
+ }
3278
+ validateNoReconciliation(
3279
+ session.reconciliation,
3280
+ resource,
3281
+ "$.reconciliation"
3282
+ );
3283
+ if (session.order !== null) fail(resource, "$.order", "null");
3284
+ } else if (status === "unknown") {
3285
+ enumValue(
3286
+ session.sessionRole,
3287
+ ["active", "residual"],
3288
+ resource,
3289
+ "$.sessionRole"
3290
+ );
3291
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3292
+ fail(resource, "$", "suppressed not-ready state");
3293
+ }
3294
+ validateRequiredReconciliation(
3295
+ session.reconciliation,
3296
+ ["provider_outcome_unknown"],
3297
+ resource,
3298
+ "$.reconciliation"
3299
+ );
3300
+ if (session.order !== null) fail(resource, "$.order", "null");
3301
+ } else if (status === "captured") {
3302
+ validateCaptureEvidence(
3303
+ session.providerEvidence,
3304
+ resource,
3305
+ "$.providerEvidence"
3306
+ );
3307
+ if (session.presentationStatus !== "suppressed")
3308
+ fail(resource, "$.presentationStatus", "suppressed");
3309
+ if (session.finalizationStatus === "pending") {
3310
+ enumValue(
3311
+ session.sessionRole,
3312
+ ["canonical_candidate", "residual"],
3313
+ resource,
3314
+ "$.sessionRole"
3315
+ );
3316
+ if (session.order !== null)
3317
+ fail(resource, "$.order", "null for pending finalization");
3318
+ const reconciliation = record(
3319
+ session.reconciliation,
3320
+ resource,
3321
+ "$.reconciliation"
3322
+ );
3323
+ if (reconciliation.status === "none")
3324
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3325
+ else
3326
+ validateRequiredReconciliation(
3327
+ reconciliation,
3328
+ [
3329
+ "local_commit_ambiguous",
3330
+ "amount_mismatch",
3331
+ "currency_mismatch",
3332
+ "excess_capture_pending_order"
3333
+ ],
3334
+ resource,
3335
+ "$.reconciliation"
3336
+ );
3337
+ } else if (session.finalizationStatus === "committed") {
3338
+ validateOrderReference(session.order, resource, "$.order");
3339
+ const reconciliation = record(
3340
+ session.reconciliation,
3341
+ resource,
3342
+ "$.reconciliation"
3343
+ );
3344
+ if (reconciliation.status === "none") {
3345
+ enumValue(
3346
+ session.sessionRole,
3347
+ ["canonical", "historical"],
3348
+ resource,
3349
+ "$.sessionRole"
3350
+ );
3351
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3352
+ } else {
3353
+ enumValue(
3354
+ session.sessionRole,
3355
+ ["canonical", "residual"],
3356
+ resource,
3357
+ "$.sessionRole"
3358
+ );
3359
+ validateRequiredReconciliation(
3360
+ reconciliation,
3361
+ [
3362
+ "inventory_unavailable",
3363
+ "admission_unavailable",
3364
+ "amount_mismatch",
3365
+ "currency_mismatch",
3366
+ "excess_capture",
3367
+ "late_capture",
3368
+ "cross_checkout_duplicate"
3369
+ ],
3370
+ resource,
3371
+ "$.reconciliation"
3372
+ );
3373
+ }
3374
+ } else fail(resource, "$.finalizationStatus", "pending | committed");
3375
+ } else if (status === "failed") {
3376
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3377
+ fail(resource, "$", "historical suppressed failed state");
3378
+ }
3379
+ validateNoReconciliation(
3380
+ session.reconciliation,
3381
+ resource,
3382
+ "$.reconciliation"
1684
3383
  );
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;
3384
+ const failure = record(session.failure, resource, "$.failure");
3385
+ exact(failure, ["reason"], ["message"], resource, "$.failure");
3386
+ enumValue(
3387
+ failure.reason,
3388
+ PAYMENT_FAILURE_REASONS,
3389
+ resource,
3390
+ "$.failure.reason"
3391
+ );
3392
+ if (failure.message !== void 0)
3393
+ string(failure.message, resource, "$.failure.message");
3394
+ } else {
3395
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3396
+ fail(resource, "$", "historical suppressed canceled state");
1706
3397
  }
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" }
3398
+ validateNoReconciliation(
3399
+ session.reconciliation,
3400
+ resource,
3401
+ "$.reconciliation"
1720
3402
  );
1721
- }
1722
- unbanCustomer(params) {
1723
- return this.request(
1724
- "/api/community-bans/unban-bearer",
1725
- params,
1726
- { method: "POST" }
3403
+ enumValue(
3404
+ session.cancellationReason,
3405
+ ["expired", "customer", "operator", "provider"],
3406
+ resource,
3407
+ "$.cancellationReason"
1727
3408
  );
1728
3409
  }
1729
- };
3410
+ return value;
3411
+ }
3412
+
3413
+ // src/core/api/commerce-idempotency.ts
3414
+ 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;
3415
+ var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
3416
+ function isCommerceIdempotencyKey(value) {
3417
+ return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
3418
+ }
3419
+ function assertCommerceIdempotencyKey(value) {
3420
+ if (isCommerceIdempotencyKey(value)) return;
3421
+ throw createValidationError(
3422
+ "idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
3423
+ { field: "idempotencyKey" }
3424
+ );
3425
+ }
1730
3426
 
1731
3427
  // src/core/api/cart-api.ts
1732
3428
  var CartApi = class extends CustomerScopedApi {
1733
3429
  constructor(options) {
1734
3430
  super("CartApi", { ...options, requiresCredential: false });
3431
+ this.serverTransport = Boolean(options.secretKey);
1735
3432
  }
1736
- async execute(endpoint, method, body) {
1737
- return this.request(endpoint, { method, body });
3433
+ endpoint(key) {
3434
+ return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
1738
3435
  }
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);
3436
+ execute(endpoint2, body, idempotencyKey) {
3437
+ return this.requestEndpoint(endpoint2, body, {
3438
+ ...idempotencyKey && {
3439
+ headers: { "X-Idempotency-Key": idempotencyKey }
3440
+ }
3441
+ });
1745
3442
  }
1746
- getCart(cartToken) {
1747
- return this.execute("/api/carts/get", "POST", { cartToken });
3443
+ create(params = {}) {
3444
+ return this.execute(this.endpoint("create"), params).then(
3445
+ (value) => validateCreateCartResult(value)
3446
+ );
1748
3447
  }
1749
- merge(params) {
1750
- return this.execute(
1751
- COMMERCE_ENDPOINTS.carts.merge,
1752
- "POST",
1753
- params
3448
+ retrieve(params) {
3449
+ return this.execute(this.endpoint("retrieve"), params).then(
3450
+ (value) => validatePublicCart(value)
1754
3451
  );
1755
3452
  }
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
- {}
3453
+ mine(params = {}) {
3454
+ const endpoint2 = this.endpoint("mine");
3455
+ return this.execute(endpoint2, params).then(
3456
+ (value) => validateCartMineResult(value)
3457
+ );
3458
+ }
3459
+ merge(params) {
3460
+ const { idempotencyKey, ...body } = params;
3461
+ assertCommerceIdempotencyKey(idempotencyKey);
3462
+ const endpoint2 = this.endpoint("merge");
3463
+ return this.execute(endpoint2, body, idempotencyKey).then(
3464
+ (value) => validateCartMergeResult(value)
1766
3465
  );
1767
3466
  }
1768
3467
  addItem(params) {
1769
- return this.execute(
1770
- COMMERCE_ENDPOINTS.carts.addItem,
1771
- "POST",
1772
- params
3468
+ return this.mutate(this.endpoint("addItem"), params);
3469
+ }
3470
+ mutate(endpoint2, params) {
3471
+ const { idempotencyKey, ...body } = params;
3472
+ assertCommerceIdempotencyKey(idempotencyKey);
3473
+ return this.execute(endpoint2, body, idempotencyKey).then(
3474
+ (value) => validateCartMutationResult(value)
1773
3475
  );
1774
3476
  }
1775
3477
  updateItem(params) {
1776
- return this.execute(
1777
- COMMERCE_ENDPOINTS.carts.updateItem,
1778
- "POST",
1779
- params
1780
- );
3478
+ return this.mutate(this.endpoint("updateItem"), params);
1781
3479
  }
1782
3480
  removeItem(params) {
1783
- return this.execute(
1784
- COMMERCE_ENDPOINTS.carts.removeItem,
1785
- "POST",
1786
- params
1787
- );
3481
+ return this.mutate(this.endpoint("removeItem"), params);
1788
3482
  }
1789
- applyDiscount(params) {
1790
- return this.execute(
1791
- COMMERCE_ENDPOINTS.carts.applyDiscount,
1792
- "POST",
1793
- params
1794
- );
3483
+ clear(params) {
3484
+ return this.mutate(this.endpoint("clear"), params);
1795
3485
  }
1796
- removeDiscount(params) {
1797
- return this.execute(
1798
- COMMERCE_ENDPOINTS.carts.removeDiscount,
1799
- "POST",
1800
- params
1801
- );
3486
+ updateDiscountCodes(params) {
3487
+ return this.mutate(this.endpoint("updateDiscountCodes"), params);
1802
3488
  }
1803
- clearCart(params) {
1804
- return this.execute(
1805
- COMMERCE_ENDPOINTS.carts.clear,
1806
- "POST",
1807
- params
1808
- );
3489
+ updateAttributes(params) {
3490
+ return this.mutate(this.endpoint("updateAttributes"), params);
1809
3491
  }
1810
3492
  };
1811
3493
 
@@ -2612,6 +4294,9 @@ function compareVariantOrder(a, b) {
2612
4294
  }
2613
4295
  function getVariantAvailableForSale(variant) {
2614
4296
  if (variant.isActive === false) return false;
4297
+ if (typeof variant.availableForSale === "boolean") {
4298
+ return variant.availableForSale;
4299
+ }
2615
4300
  if (variant.isUnlimited) return true;
2616
4301
  if (variant.inventoryPolicy === "continue") return true;
2617
4302
  return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
@@ -2721,7 +4406,7 @@ function buildProductListingCard(item, options = {}) {
2721
4406
  { listing: { selectionHintVariant } },
2722
4407
  options
2723
4408
  ),
2724
- title: product.title,
4409
+ title: product.title ?? "",
2725
4410
  representativeVariant,
2726
4411
  primaryImage: listingPrimaryMedia,
2727
4412
  priceRange,
@@ -2849,6 +4534,11 @@ function productDetailResultFromError(error) {
2849
4534
  if (!reason) return void 0;
2850
4535
  return { found: false, reason };
2851
4536
  }
4537
+ var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
4538
+ var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
4539
+ "priceRange.minVariantPrice.amount",
4540
+ "priceRange.maxVariantPrice.amount"
4541
+ ]);
2852
4542
  function nonEmpty(values) {
2853
4543
  return values?.length ? values : void 0;
2854
4544
  }
@@ -2896,14 +4586,34 @@ function buildProductListingPageWhere(params) {
2896
4586
  if (clauses.length === 1) return clauses[0];
2897
4587
  return { and: clauses };
2898
4588
  }
2899
- function buildProductListingPageUrl(params) {
4589
+ function productListingPageUsesBasePriceSort(sort) {
4590
+ const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
4591
+ return values.some(
4592
+ (value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
4593
+ );
4594
+ }
4595
+ function assertMarketListingPageQuerySupported(params) {
4596
+ if (!params.market?.trim()) return;
4597
+ const priceFilter = params.filters?.price;
4598
+ if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
4599
+ throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
4600
+ }
4601
+ }
4602
+ function buildProductListingPageRequest(params) {
4603
+ assertMarketListingPageQuerySupported(params);
2900
4604
  const options = {
4605
+ market: params.market,
4606
+ locale: params.locale,
4607
+ fallbackLocale: params.fallbackLocale,
2901
4608
  page: params.page,
2902
4609
  limit: params.limit,
2903
4610
  sort: params.sort,
2904
4611
  where: buildProductListingPageWhere(params)
2905
4612
  };
2906
- return params.mode === "full" ? listingGroupsQueryUrl(options) : listingGroupsQueryCatalogUrl(options);
4613
+ return {
4614
+ operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
4615
+ query: listingPageSearchParams(options)
4616
+ };
2907
4617
  }
2908
4618
  function withProductListingCards(response, options) {
2909
4619
  return {
@@ -2952,38 +4662,40 @@ var ProductApi = class extends BaseApi {
2952
4662
  * to remain available by the time an order is placed.
2953
4663
  */
2954
4664
  stockCheck(params) {
2955
- return this.request(
2956
- COMMERCE_ENDPOINTS.products.stockCheck,
4665
+ return this.requestEndpoint(
4666
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
2957
4667
  params
2958
4668
  );
2959
4669
  }
2960
4670
  stockSnapshot(params) {
2961
- return this.request(
2962
- stockSnapshotQuery(params),
4671
+ return this.requestEndpoint(
4672
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
2963
4673
  void 0,
2964
- { method: "GET" }
4674
+ { query: stockSnapshotSearchParams(params) }
2965
4675
  );
2966
4676
  }
2967
4677
  listingGroups(params) {
2968
- return this.request(
2969
- listingGroupsQuery(params),
4678
+ return this.requestEndpoint(
4679
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups,
2970
4680
  void 0,
2971
- { method: "GET" }
4681
+ { query: listingGroupsSearchParams(params) }
2972
4682
  );
2973
4683
  }
2974
4684
  listingGroupsCatalog(params) {
2975
- return this.request(
2976
- listingGroupsCatalogQuery(params),
4685
+ return this.requestEndpoint(
4686
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
2977
4687
  void 0,
2978
- { method: "GET" }
4688
+ { query: listingGroupsSearchParams(params) }
2979
4689
  );
2980
4690
  }
2981
4691
  async listingPage(params = {}) {
2982
4692
  if (params.mode === "full") {
2983
- const response2 = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4693
+ const request2 = buildProductListingPageRequest(params);
4694
+ const response2 = await this.requestEndpoint(request2.operation, void 0, { query: request2.query });
2984
4695
  return withProductListingCards(response2, params);
2985
4696
  }
2986
- const response = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4697
+ const request = buildProductListingPageRequest(params);
4698
+ const response = await this.requestEndpoint(request.operation, void 0, { query: request.query });
2987
4699
  return withProductListingCards(response, params);
2988
4700
  }
2989
4701
  /**
@@ -2998,10 +4710,10 @@ var ProductApi = class extends BaseApi {
2998
4710
  */
2999
4711
  async detail(params) {
3000
4712
  try {
3001
- const product = await this.request(
3002
- productDetailQuery(params),
4713
+ const product = await this.requestEndpoint(
4714
+ COMMERCE_ENDPOINT_OPERATIONS.products.detail,
3003
4715
  void 0,
3004
- { method: "GET" }
4716
+ { query: productDetailSearchParams(params) }
3005
4717
  );
3006
4718
  return { found: true, product };
3007
4719
  } catch (err) {
@@ -3012,10 +4724,10 @@ var ProductApi = class extends BaseApi {
3012
4724
  }
3013
4725
  async detailCatalog(params) {
3014
4726
  try {
3015
- const product = await this.request(
3016
- productDetailCatalogQuery(params),
4727
+ const product = await this.requestEndpoint(
4728
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
3017
4729
  void 0,
3018
- { method: "GET" }
4730
+ { query: productDetailSearchParams(params) }
3019
4731
  );
3020
4732
  return { found: true, product };
3021
4733
  } catch (err) {
@@ -3031,8 +4743,8 @@ var ProductApi = class extends BaseApi {
3031
4743
  * `product-upsert` tool.
3032
4744
  */
3033
4745
  upsert(params) {
3034
- return this.request(
3035
- COMMERCE_ENDPOINTS.products.upsert,
4746
+ return this.requestEndpoint(
4747
+ COMMERCE_ENDPOINT_OPERATIONS.products.upsert,
3036
4748
  normalizeProductUpsertParams(params)
3037
4749
  );
3038
4750
  }
@@ -3044,7 +4756,10 @@ var DiscountApi = class extends BaseApi {
3044
4756
  super("DiscountApi", options);
3045
4757
  }
3046
4758
  validate(params) {
3047
- return this.request("/api/discounts/validate", params);
4759
+ return this.requestEndpoint(
4760
+ COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
4761
+ params
4762
+ );
3048
4763
  }
3049
4764
  };
3050
4765
 
@@ -3054,7 +4769,10 @@ var ShippingApi = class extends BaseApi {
3054
4769
  super("ShippingApi", options);
3055
4770
  }
3056
4771
  calculate(params) {
3057
- return this.request("/api/shipping-policies/calculate", params);
4772
+ return this.requestEndpoint(
4773
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
4774
+ params
4775
+ );
3058
4776
  }
3059
4777
  };
3060
4778
 
@@ -3066,44 +4784,12 @@ function splitIdempotencyKey(params) {
3066
4784
  const { idempotencyKey, ...body } = params;
3067
4785
  return { body, idempotencyKey };
3068
4786
  }
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
4787
  var OrderApi = class extends BaseApi {
3078
4788
  constructor(options) {
3079
4789
  super("OrderApi", options);
3080
4790
  }
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
4791
  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
- );
4792
+ return this.requestEndpoint(COMMERCE_ENDPOINTS.orders.update, params);
3107
4793
  }
3108
4794
  /**
3109
4795
  * Resolve an order + its payment transaction by PG payment id. Replaces raw
@@ -3115,28 +4801,12 @@ var OrderApi = class extends BaseApi {
3115
4801
  pgProvider: params.pgProvider,
3116
4802
  pgPaymentId: params.pgPaymentId
3117
4803
  }).toString();
3118
- return this.request(
3119
- `${COMMERCE_ENDPOINTS.orders.byPayment}?${query}`,
4804
+ return this.requestEndpoint(
4805
+ COMMERCE_ENDPOINTS.orders.byPayment,
3120
4806
  void 0,
3121
- { method: "GET" }
4807
+ { query }
3122
4808
  );
3123
4809
  }
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
4810
  cancelOrder(params) {
3141
4811
  const { idempotencyKey } = params;
3142
4812
  const body = {
@@ -3144,14 +4814,14 @@ var OrderApi = class extends BaseApi {
3144
4814
  reasonCode: params.reasonCode,
3145
4815
  reasonDetail: params.reasonDetail
3146
4816
  };
3147
- return this.request(
4817
+ return this.requestEndpoint(
3148
4818
  COMMERCE_ENDPOINTS.orders.cancel,
3149
4819
  body,
3150
4820
  idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0
3151
4821
  );
3152
4822
  }
3153
4823
  resolveCancelRefund(params) {
3154
- return this.request(
4824
+ return this.requestEndpoint(
3155
4825
  COMMERCE_ENDPOINTS.orders.resolveCancelRefund,
3156
4826
  {
3157
4827
  orderNumber: params.orderNumber,
@@ -3164,49 +4834,35 @@ var OrderApi = class extends BaseApi {
3164
4834
  idempotencyRequestOptions(params.idempotencyKey)
3165
4835
  );
3166
4836
  }
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
4837
  createFulfillment(params) {
3182
4838
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3183
- return this.request(
4839
+ return this.requestEndpoint(
3184
4840
  COMMERCE_ENDPOINTS.orders.createFulfillment,
3185
4841
  body,
3186
4842
  idempotencyRequestOptions(idempotencyKey)
3187
4843
  );
3188
4844
  }
3189
4845
  prepareFulfillmentOrder(params) {
3190
- return this.request(
4846
+ return this.requestEndpoint(
3191
4847
  COMMERCE_ENDPOINTS.fulfillmentOrders.prepare,
3192
4848
  params
3193
4849
  );
3194
4850
  }
3195
4851
  updateFulfillment(params) {
3196
- return this.request(
4852
+ return this.requestEndpoint(
3197
4853
  COMMERCE_ENDPOINTS.orders.updateFulfillment,
3198
4854
  params
3199
4855
  );
3200
4856
  }
3201
4857
  bulkImportFulfillments(params) {
3202
- return this.request(
4858
+ return this.requestEndpoint(
3203
4859
  COMMERCE_ENDPOINTS.fulfillments.bulkImport,
3204
4860
  params
3205
4861
  );
3206
4862
  }
3207
4863
  returnWithRefund(params) {
3208
4864
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3209
- return this.request(
4865
+ return this.requestEndpoint(
3210
4866
  COMMERCE_ENDPOINTS.returns.returnRefund,
3211
4867
  body,
3212
4868
  idempotencyRequestOptions(idempotencyKey)
@@ -3214,19 +4870,182 @@ var OrderApi = class extends BaseApi {
3214
4870
  }
3215
4871
  createReturn(params) {
3216
4872
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3217
- return this.request(
4873
+ return this.requestEndpoint(
3218
4874
  COMMERCE_ENDPOINTS.returns.create,
3219
4875
  body,
3220
4876
  idempotencyRequestOptions(idempotencyKey)
3221
4877
  );
3222
4878
  }
3223
4879
  updateReturn(params) {
3224
- return this.request(COMMERCE_ENDPOINTS.returns.update, params);
4880
+ return this.requestEndpoint(
4881
+ COMMERCE_ENDPOINTS.returns.update,
4882
+ params
4883
+ );
4884
+ }
4885
+ };
4886
+
4887
+ // src/core/api/checkout-api.ts
4888
+ var CheckoutApi = class extends CustomerScopedApi {
4889
+ constructor(options) {
4890
+ super("CheckoutApi", { ...options, requiresCredential: false });
4891
+ }
4892
+ post(endpoint2, body, idempotencyKey) {
4893
+ return this.requestEndpoint(endpoint2, body, {
4894
+ ...idempotencyKey && {
4895
+ headers: { "X-Idempotency-Key": idempotencyKey }
4896
+ }
4897
+ });
4898
+ }
4899
+ async publicCheckout(result) {
4900
+ return validatePublicCheckout(await result);
4901
+ }
4902
+ async serverCheckout(result) {
4903
+ return validateServerCheckout(await result);
4904
+ }
4905
+ async createResult(result) {
4906
+ return validateCreateCheckoutResult(
4907
+ await result,
4908
+ false
4909
+ );
4910
+ }
4911
+ async createServerResult(result) {
4912
+ return validateCreateCheckoutResult(
4913
+ await result,
4914
+ true
4915
+ );
4916
+ }
4917
+ create(params) {
4918
+ const { idempotencyKey, ...body } = params;
4919
+ assertCommerceIdempotencyKey(idempotencyKey);
4920
+ return this.createResult(
4921
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
4922
+ );
4923
+ }
4924
+ createServer(params) {
4925
+ const { idempotencyKey, ...body } = params;
4926
+ assertCommerceIdempotencyKey(idempotencyKey);
4927
+ return this.createServerResult(
4928
+ this.post(
4929
+ COMMERCE_ENDPOINTS.checkouts.server.create,
4930
+ body,
4931
+ idempotencyKey
4932
+ )
4933
+ );
4934
+ }
4935
+ retrieve(params) {
4936
+ return this.publicCheckout(
4937
+ this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
4938
+ );
4939
+ }
4940
+ retrieveServer(params) {
4941
+ return this.serverCheckout(
4942
+ this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
4943
+ );
4944
+ }
4945
+ async query(params = {}) {
4946
+ const result = await this.post(
4947
+ COMMERCE_ENDPOINTS.checkouts.server.query,
4948
+ params
4949
+ );
4950
+ return validateCheckoutQueryResult(result);
4951
+ }
4952
+ };
4953
+
4954
+ // src/core/api/payment-session-api.ts
4955
+ var PaymentSessionApi = class extends CustomerScopedApi {
4956
+ constructor(options) {
4957
+ super("PaymentSessionApi", { ...options, requiresCredential: false });
4958
+ this.serverTransport = Boolean(options.secretKey);
4959
+ }
4960
+ post(endpoint2, body, idempotencyKey) {
4961
+ return this.requestEndpoint(endpoint2, body, {
4962
+ ...idempotencyKey && {
4963
+ headers: { "X-Idempotency-Key": idempotencyKey }
4964
+ }
4965
+ });
4966
+ }
4967
+ async paymentSession(result) {
4968
+ return validatePublicPaymentSession(await result);
4969
+ }
4970
+ create(params) {
4971
+ const { idempotencyKey, ...body } = params;
4972
+ assertCommerceIdempotencyKey(idempotencyKey);
4973
+ return this.paymentSession(
4974
+ this.post(
4975
+ this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
4976
+ body,
4977
+ idempotencyKey
4978
+ )
4979
+ );
4980
+ }
4981
+ retrieve(params) {
4982
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4983
+ return this.paymentSession(this.post(endpoint2, params));
4984
+ }
4985
+ cancel(params) {
4986
+ const { idempotencyKey, ...body } = params;
4987
+ assertCommerceIdempotencyKey(idempotencyKey);
4988
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4989
+ return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
4990
+ }
4991
+ confirm(params) {
4992
+ const { idempotencyKey, ...body } = params;
4993
+ assertCommerceIdempotencyKey(idempotencyKey);
4994
+ return this.paymentSession(
4995
+ this.post(
4996
+ COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
4997
+ body,
4998
+ idempotencyKey
4999
+ )
5000
+ );
5001
+ }
5002
+ };
5003
+ var CustomPaymentSessionApi = class extends BaseApi {
5004
+ constructor(options) {
5005
+ super("CustomPaymentSessionApi", options);
5006
+ }
5007
+ async create(params) {
5008
+ assertCommerceIdempotencyKey(params.idempotencyKey);
5009
+ const body = {
5010
+ provider: params.provider,
5011
+ checkoutToken: params.checkoutToken
5012
+ };
5013
+ const result = await this.requestEndpoint(
5014
+ COMMERCE_ENDPOINTS.paymentSessions.custom.create,
5015
+ body,
5016
+ { headers: { "X-Idempotency-Key": params.idempotencyKey } }
5017
+ );
5018
+ return validateCustomPaymentSession(result);
5019
+ }
5020
+ async confirm(params, options = {}) {
5021
+ const body = {
5022
+ provider: params.provider,
5023
+ providerSessionId: params.providerSessionId,
5024
+ providerPaymentId: params.providerPaymentId,
5025
+ providerEventId: params.providerEventId,
5026
+ amount: params.amount,
5027
+ currency: params.currency,
5028
+ occurredAt: params.occurredAt
5029
+ };
5030
+ const proof = await options.createProof?.(JSON.stringify(body));
5031
+ const result = await this.requestEndpoint(
5032
+ COMMERCE_ENDPOINTS.paymentSessions.custom.confirm,
5033
+ body,
5034
+ proof ? {
5035
+ headers: {
5036
+ "X-Custom-Payment-Timestamp": proof.timestamp,
5037
+ "X-Custom-Payment-Signature": proof.signature
5038
+ }
5039
+ } : void 0
5040
+ );
5041
+ return validateConfirmCustomPaymentSessionResponse(
5042
+ result
5043
+ );
3225
5044
  }
3226
5045
  };
3227
5046
 
3228
5047
  // src/core/preview/server-preview-client.ts
3229
- var ServerPreviewClient = class extends BaseApi {
5048
+ var ServerPreviewClient = class extends RawBaseApi {
3230
5049
  constructor(options) {
3231
5050
  super("ServerPreviewClient", options);
3232
5051
  }
@@ -3282,6 +5101,7 @@ var PreviewProductApi = class extends ProductApi {
3282
5101
  };
3283
5102
  var ServerCommerceClient = class {
3284
5103
  constructor(options) {
5104
+ this.market = options.market;
3285
5105
  const publishableKey = requirePublishableKeyForSecret(
3286
5106
  "ServerCommerceClient",
3287
5107
  options.publishableKey,
@@ -3298,33 +5118,34 @@ var ServerCommerceClient = class {
3298
5118
  const discountApi = new DiscountApi(serverOptions);
3299
5119
  const shippingApi = new ShippingApi(serverOptions);
3300
5120
  const orderApi = new OrderApi(serverOptions);
5121
+ const checkoutApi = new CheckoutApi(serverOptions);
5122
+ const paymentSessionApi = new PaymentSessionApi(serverOptions);
5123
+ const customPaymentSessionApi = new CustomPaymentSessionApi(serverOptions);
3301
5124
  this.product = {
3302
5125
  stockCheck: productApi.stockCheck.bind(productApi),
3303
- listingGroups: productApi.listingGroups.bind(productApi),
3304
- listingPage: productApi.listingPage.bind(productApi),
3305
- detail: productApi.detail.bind(productApi),
5126
+ listingGroups: (params) => productApi.listingGroups(this.withMarket(params)),
5127
+ listingPage: ((params = {}) => productApi.listingPage(
5128
+ this.withMarket(params)
5129
+ )),
5130
+ detail: (params) => productApi.detail(this.withMarket(params)),
5131
+ detailCatalog: (params) => productApi.detailCatalog(this.withMarket(params)),
3306
5132
  previewDetail: productApi.previewDetail.bind(productApi),
3307
5133
  upsert: productApi.upsert.bind(productApi)
3308
5134
  };
3309
- this.cart = {
3310
- create: cartApi.createCart.bind(cartApi),
3311
- get: cartApi.getCart.bind(cartApi),
5135
+ this.carts = {
5136
+ create: (params) => cartApi.create(this.withMarket(params ?? {})),
5137
+ retrieve: cartApi.retrieve.bind(cartApi),
3312
5138
  addItem: cartApi.addItem.bind(cartApi),
3313
5139
  updateItem: cartApi.updateItem.bind(cartApi),
3314
5140
  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)
5141
+ updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
5142
+ updateAttributes: cartApi.updateAttributes.bind(cartApi),
5143
+ clear: cartApi.clear.bind(cartApi),
5144
+ merge: (params) => cartApi.merge(params),
5145
+ mine: (params) => cartApi.mine(params)
3320
5146
  };
3321
5147
  this.orders = {
3322
- checkout: orderApi.checkout.bind(orderApi),
3323
- create: orderApi.createOrder.bind(orderApi),
3324
5148
  update: orderApi.updateOrder.bind(orderApi),
3325
- updateTransaction: orderApi.updateTransaction.bind(orderApi),
3326
- confirmPayment: orderApi.confirmPayment.bind(orderApi),
3327
- confirmPaymentReturningOrder: orderApi.confirmPaymentReturningOrder.bind(orderApi),
3328
5149
  getByPaymentId: orderApi.getByPaymentId.bind(orderApi),
3329
5150
  cancelOrder: orderApi.cancelOrder.bind(orderApi),
3330
5151
  resolveCancelRefund: orderApi.resolveCancelRefund.bind(orderApi),
@@ -3336,6 +5157,21 @@ var ServerCommerceClient = class {
3336
5157
  updateReturn: orderApi.updateReturn.bind(orderApi),
3337
5158
  returnWithRefund: orderApi.returnWithRefund.bind(orderApi)
3338
5159
  };
5160
+ this.checkouts = {
5161
+ create: checkoutApi.createServer.bind(checkoutApi),
5162
+ retrieve: checkoutApi.retrieveServer.bind(checkoutApi),
5163
+ query: checkoutApi.query.bind(checkoutApi)
5164
+ };
5165
+ this.paymentSessions = {
5166
+ create: paymentSessionApi.create.bind(paymentSessionApi),
5167
+ retrieve: (params) => paymentSessionApi.retrieve(params),
5168
+ cancel: (params) => paymentSessionApi.cancel(params),
5169
+ confirm: paymentSessionApi.confirm.bind(paymentSessionApi),
5170
+ custom: {
5171
+ create: customPaymentSessionApi.create.bind(customPaymentSessionApi),
5172
+ confirm: customPaymentSessionApi.confirm.bind(customPaymentSessionApi)
5173
+ }
5174
+ };
3339
5175
  this.discounts = {
3340
5176
  validate: discountApi.validate.bind(discountApi)
3341
5177
  };
@@ -3343,6 +5179,14 @@ var ServerCommerceClient = class {
3343
5179
  calculate: shippingApi.calculate.bind(shippingApi)
3344
5180
  };
3345
5181
  }
5182
+ getDefaultMarket() {
5183
+ return this.market;
5184
+ }
5185
+ withMarket(params) {
5186
+ const defaultMarket = this.market?.trim();
5187
+ if (!defaultMarket || params.market?.trim()) return params;
5188
+ return { ...params, market: defaultMarket };
5189
+ }
3346
5190
  };
3347
5191
 
3348
5192
  // src/core/events/events-client.ts
@@ -3362,7 +5206,17 @@ var EventsClient = class {
3362
5206
  getRange(params) {
3363
5207
  return this.execute(
3364
5208
  buildRangeEndpoint(params),
3365
- "GET",
5209
+ resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
5210
+ void 0,
5211
+ { useCustomerAuth: false }
5212
+ );
5213
+ }
5214
+ getAdmissionAvailability(params) {
5215
+ return this.execute(
5216
+ buildAdmissionAvailabilityEndpoint(params),
5217
+ resolveOperationMethod(
5218
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
5219
+ ),
3366
5220
  void 0,
3367
5221
  { useCustomerAuth: false }
3368
5222
  );
@@ -3391,11 +5245,11 @@ var EventsClient = class {
3391
5245
  { useCustomerAuth: false }
3392
5246
  );
3393
5247
  }
3394
- async execute(endpoint, method, body, options = {}) {
5248
+ async execute(endpoint2, method, body, options = {}) {
3395
5249
  const useCustomerAuth = options.useCustomerAuth === true;
3396
5250
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
3397
5251
  try {
3398
- const response = await httpFetch(endpoint, {
5252
+ const response = await httpFetch(endpoint2, {
3399
5253
  method,
3400
5254
  apiUrl: this.apiUrl,
3401
5255
  publishableKey: this.publishableKey,
@@ -3404,7 +5258,7 @@ var EventsClient = class {
3404
5258
  ...body !== void 0 && { body: JSON.stringify(body) }
3405
5259
  });
3406
5260
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
3407
- return parseApiResponse(response, endpoint);
5261
+ return parseApiResponse(response, endpoint2);
3408
5262
  } catch (err) {
3409
5263
  const id = err instanceof SDKError ? err.requestId ?? null : null;
3410
5264
  this.onRequestId?.(id);
@@ -3443,7 +5297,17 @@ function buildRangeEndpoint(params) {
3443
5297
  appendValues(urlParams, "categorySlug", params.categorySlug);
3444
5298
  appendValues(urlParams, "tag", params.tag);
3445
5299
  appendValues(urlParams, "tagSlug", params.tagSlug);
3446
- return `/api/event-occurrences/range?${urlParams.toString()}`;
5300
+ return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
5301
+ query: urlParams
5302
+ });
5303
+ }
5304
+ function buildAdmissionAvailabilityEndpoint(params) {
5305
+ const urlParams = new URLSearchParams();
5306
+ urlParams.set("occurrence", params.occurrence);
5307
+ return resolveOperationPath(
5308
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
5309
+ { query: urlParams }
5310
+ );
3447
5311
  }
3448
5312
  function formatDateParam(value) {
3449
5313
  return value instanceof Date ? value.toISOString() : value;
@@ -3456,11 +5320,56 @@ function appendValues(params, key, value) {
3456
5320
  }
3457
5321
  }
3458
5322
 
5323
+ // src/core/market/market-discovery.ts
5324
+ function toMarketDTO(row) {
5325
+ return {
5326
+ id: row.id,
5327
+ handle: row.handle,
5328
+ name: row.name,
5329
+ countryCode: row.countryCode,
5330
+ targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
5331
+ currency: row.currency,
5332
+ isPrimary: row.isPrimary === true,
5333
+ isActive: row.isActive === true
5334
+ };
5335
+ }
5336
+ var MarketDiscovery = class {
5337
+ constructor(read) {
5338
+ this.read = read;
5339
+ }
5340
+ async list() {
5341
+ const res = await this.read({
5342
+ where: { isActive: { equals: true } },
5343
+ limit: 100
5344
+ });
5345
+ if (res.hasNextPage) {
5346
+ console.warn(
5347
+ "[markets.list] more than 100 active markets; results truncated to 100."
5348
+ );
5349
+ }
5350
+ return res.docs.map(toMarketDTO);
5351
+ }
5352
+ async default() {
5353
+ const res = await this.read({
5354
+ where: { isPrimary: { equals: true }, isActive: { equals: true } },
5355
+ limit: 1
5356
+ });
5357
+ const row = res.docs[0];
5358
+ return row ? toMarketDTO(row) : null;
5359
+ }
5360
+ };
5361
+
3459
5362
  // src/core/api/tenant-introspection-api.ts
3460
- var TenantIntrospectionApi = class extends BaseApi {
5363
+ var TenantIntrospectionApi = class extends RawBaseApi {
3461
5364
  constructor(options) {
3462
5365
  super("TenantIntrospectionApi", options);
3463
5366
  }
5367
+ context(params = {}) {
5368
+ const endpoint2 = params.includeCounts ? "/api/tenants/context?counts=true" : "/api/tenants/context";
5369
+ return this.request(endpoint2, void 0, {
5370
+ method: "GET"
5371
+ });
5372
+ }
3464
5373
  collectionSchema(collection) {
3465
5374
  return this.request(
3466
5375
  `/api/tenants/schema/${encodeURIComponent(collection)}`,
@@ -3494,40 +5403,30 @@ var MembershipApi = class extends BaseApi {
3494
5403
  */
3495
5404
  subscribe(params) {
3496
5405
  const { subscribeIntentKey, ...body } = params;
3497
- return this.request(
3498
- MEMBERSHIP_ENDPOINTS.subscribe,
5406
+ return this.requestEndpoint(
5407
+ MEMBERSHIP_ENDPOINT_OPERATIONS.subscribe,
3499
5408
  body,
3500
5409
  idempotencyRequestOptions(subscribeIntentKey)
3501
5410
  );
3502
5411
  }
3503
5412
  /**
3504
5413
  * 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.
5414
+ * By default this sets `cancelAtPeriodEnd`, keeps benefits until
5415
+ * `currentPeriodEnd`, and stops renewal. Pass `immediate=true` to cancel
5416
+ * immediately and revoke membership groups now.
3508
5417
  */
3509
5418
  cancel(params) {
3510
5419
  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" }
5420
+ return this.requestEndpoint(
5421
+ MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
5422
+ immediate !== void 0 ? { immediate } : {},
5423
+ { pathParams: { id } }
3525
5424
  );
3526
5425
  }
3527
5426
  };
3528
5427
 
3529
5428
  // src/core/client/client.server.ts
3530
- var ServerClient = class {
5429
+ var ServerClient = class _ServerClient {
3531
5430
  constructor(options) {
3532
5431
  this.lastRequestId = null;
3533
5432
  if (typeof window !== "undefined") {
@@ -3556,17 +5455,18 @@ var ServerClient = class {
3556
5455
  publishableKey: this.config.publishableKey,
3557
5456
  secretKey: this.config.secretKey,
3558
5457
  apiUrl: this.config.apiUrl,
5458
+ market: this.config.market,
3559
5459
  onRequestId
3560
5460
  };
3561
5461
  this.commerce = new ServerCommerceClient(serverOptions);
3562
5462
  const membershipApi = new MembershipApi(serverOptions);
3563
5463
  this.memberships = {
3564
5464
  subscribe: membershipApi.subscribe.bind(membershipApi),
3565
- cancel: membershipApi.cancel.bind(membershipApi),
3566
- me: membershipApi.me.bind(membershipApi)
5465
+ cancel: membershipApi.cancel.bind(membershipApi)
3567
5466
  };
3568
5467
  const tenantIntrospectionApi = new TenantIntrospectionApi(serverOptions);
3569
5468
  this.tenant = {
5469
+ context: tenantIntrospectionApi.context.bind(tenantIntrospectionApi),
3570
5470
  collectionSchema: tenantIntrospectionApi.collectionSchema.bind(
3571
5471
  tenantIntrospectionApi
3572
5472
  ),
@@ -3594,6 +5494,9 @@ var ServerClient = class {
3594
5494
  onRequestId,
3595
5495
  this.config.apiUrl
3596
5496
  );
5497
+ this.markets = new MarketDiscovery(
5498
+ (options2) => this.collections.from("markets").find(options2)
5499
+ );
3597
5500
  }
3598
5501
  get events() {
3599
5502
  if (!this._events) {
@@ -3615,6 +5518,9 @@ var ServerClient = class {
3615
5518
  getState() {
3616
5519
  return { ...this.state };
3617
5520
  }
5521
+ withMarket(market) {
5522
+ return new _ServerClient({ ...this.config, market });
5523
+ }
3618
5524
  getConfig() {
3619
5525
  const { secretKey: _, ...safeConfig } = this.config;
3620
5526
  return safeConfig;