@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.js CHANGED
@@ -28,10 +28,136 @@ var SDKError = class extends Error {
28
28
  details: this.details,
29
29
  userMessage: this.userMessage,
30
30
  suggestion: this.suggestion,
31
- ...this.requestId !== void 0 && { requestId: this.requestId }
31
+ ...this.requestId !== void 0 && { requestId: this.requestId },
32
+ ...this.kind !== void 0 && { kind: this.kind },
33
+ ...this.reason !== void 0 && { reason: this.reason },
34
+ ...this.rawReason !== void 0 && { rawReason: this.rawReason },
35
+ ...this.retryable !== void 0 && { retryable: this.retryable },
36
+ ...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
32
37
  };
33
38
  }
34
39
  };
40
+ var COMMERCE_ERROR_CODES = [
41
+ "validation_failed",
42
+ "unauthorized",
43
+ "forbidden",
44
+ "token_expired",
45
+ "origin_not_allowed",
46
+ "server_credentials_required",
47
+ "not_found",
48
+ "conflict",
49
+ "cart_revision_conflict",
50
+ "rate_limit_exceeded",
51
+ "usage_limit_exceeded",
52
+ "service_unavailable",
53
+ "idempotency_conflict",
54
+ "idempotency_in_progress",
55
+ "cart_not_active",
56
+ "cart_locked",
57
+ "cart_empty",
58
+ "cart_market_unavailable",
59
+ "cart_market_mismatch",
60
+ "checkout_not_open",
61
+ "payment_slot_held",
62
+ "reservation_expired",
63
+ "payment_session_not_cancelable",
64
+ "provider_identity_mismatch",
65
+ "provider_unavailable",
66
+ "lock_timeout",
67
+ "price_changed",
68
+ "pricing_fact_in_use",
69
+ "insufficient_stock",
70
+ "market_not_found",
71
+ "market_shipping_currency_unsupported",
72
+ "missing_market_rate",
73
+ "missing_shipping_amount",
74
+ "no_enabled_payment_provider",
75
+ "product_market_unavailable",
76
+ "unsupported_currency",
77
+ "missing_price_row",
78
+ "payment_provider_currency_unsupported",
79
+ "discount_code_not_found",
80
+ "discount_not_started",
81
+ "discount_expired",
82
+ "discount_usage_limit",
83
+ "discount_per_customer_limit",
84
+ "discount_customer_required",
85
+ "discount_first_order_only",
86
+ "discount_customer_not_eligible",
87
+ "discount_customer_excluded",
88
+ "discount_items_required",
89
+ "discount_product_not_eligible",
90
+ "discount_product_excluded",
91
+ "discount_min_order_amount",
92
+ "discount_currency_scope_required",
93
+ "discount_allocation_method_unsupported",
94
+ "currency_mismatch"
95
+ ];
96
+ var COMMERCE_ERROR_CODE_SET = new Set(
97
+ COMMERCE_ERROR_CODES
98
+ );
99
+ var COMMERCE_ERROR_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
100
+ "error",
101
+ "reason",
102
+ "requestId",
103
+ "retryable",
104
+ "details"
105
+ ]);
106
+ function isPlainRecord(value) {
107
+ return typeof value === "object" && value !== null && !Array.isArray(value);
108
+ }
109
+ function commerceProtocolError(issue, trustedRequestId) {
110
+ return createApiError(
111
+ "Invalid canonical commerce error response.",
112
+ 502,
113
+ { protocol: "commerce-error-envelope", issue },
114
+ "The server returned an incompatible commerce error response.",
115
+ "Verify that the Console commerce contract is deployed before using this SDK version.",
116
+ trustedRequestId
117
+ );
118
+ }
119
+ function parseCommerceErrorEnvelope(body, headerRequestId) {
120
+ if (!isPlainRecord(body)) {
121
+ throw commerceProtocolError("expected_object", headerRequestId);
122
+ }
123
+ if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {
124
+ throw commerceProtocolError("unexpected_field", headerRequestId);
125
+ }
126
+ 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)) {
127
+ throw commerceProtocolError("invalid_field", headerRequestId);
128
+ }
129
+ if (headerRequestId && headerRequestId !== body.requestId) {
130
+ throw commerceProtocolError("request_id_mismatch", headerRequestId);
131
+ }
132
+ return {
133
+ error: body.error,
134
+ reason: body.reason,
135
+ requestId: body.requestId,
136
+ retryable: body.retryable === true,
137
+ ...body.details === void 0 ? {} : { details: body.details }
138
+ };
139
+ }
140
+ function enhanceCommerceError(error, body, headerRequestId) {
141
+ const envelope = parseCommerceErrorEnvelope(body, headerRequestId);
142
+ const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason);
143
+ Object.assign(error, {
144
+ code: envelope.reason,
145
+ kind: "commerce",
146
+ reason: known ? envelope.reason : "unknown_commerce_error",
147
+ ...known ? {} : { rawReason: envelope.reason },
148
+ requestId: envelope.requestId,
149
+ retryable: envelope.retryable,
150
+ details: envelope.details
151
+ });
152
+ return error;
153
+ }
154
+ function isCommerceSDKError(error) {
155
+ if (!(error instanceof SDKError) || error.kind !== "commerce") return false;
156
+ if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
157
+ return false;
158
+ }
159
+ return error.reason === "unknown_commerce_error" ? typeof error.rawReason === "string" : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === void 0;
160
+ }
35
161
  var NetworkError = class extends SDKError {
36
162
  constructor(message, status, details, userMessage, suggestion) {
37
163
  super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
@@ -225,6 +351,7 @@ var NON_RETRYABLE_STATUSES = [400, 401, 403, 404, 409, 422];
225
351
  var SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
226
352
  var DEFAULT_MAX_RETRIES = 3;
227
353
  var STOREFRONT_BROWSER_MAX_RETRIES = 1;
354
+ var MAX_AUTOMATIC_RETRY_AFTER_SECONDS = 5 * 60;
228
355
  function debugLog(debug, type, message, data) {
229
356
  if (!debug) return;
230
357
  const shouldLog = debug === true || type === "request" && debug.logRequests || type === "response" && debug.logResponses || type === "error" && debug.logErrors;
@@ -248,6 +375,11 @@ function redactSensitiveHeaders(headers) {
248
375
  redacted["x-preview-token"]
249
376
  );
250
377
  }
378
+ if (redacted["x-custom-payment-signature"]) {
379
+ redacted["x-custom-payment-signature"] = redactSensitiveHeader(
380
+ redacted["x-custom-payment-signature"]
381
+ );
382
+ }
251
383
  return redacted;
252
384
  }
253
385
  function getErrorSuggestion(status) {
@@ -339,116 +471,129 @@ function attachRequestId(err, id) {
339
471
  }
340
472
  function parseRetryAfter(response) {
341
473
  const raw = response.headers.get("Retry-After");
342
- if (!raw) return void 0;
343
- return parseInt(raw, 10) || void 0;
474
+ if (!raw) return { permitsAutomaticRetry: true };
475
+ const trimmed = raw.trim();
476
+ let seconds;
477
+ if (/^\d+$/.test(trimmed)) {
478
+ seconds = Number(trimmed);
479
+ if (!Number.isSafeInteger(seconds)) {
480
+ return { permitsAutomaticRetry: false };
481
+ }
482
+ } else {
483
+ const retryAt = Date.parse(trimmed);
484
+ if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
485
+ seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
486
+ }
487
+ return {
488
+ seconds,
489
+ permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
490
+ };
344
491
  }
345
- function mapResponseToError(status, parsed, details, requestId, retryAfter) {
492
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
346
493
  const errorDetails = {
347
494
  ...details,
348
495
  ...parsed.errors && { errors: parsed.errors },
349
- ...parsed.body && { body: parsed.body }
496
+ ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
350
497
  };
351
498
  const suggestion = getParsedErrorSuggestion(status, parsed);
499
+ const finalize = (error) => {
500
+ const withRequestId = attachRequestId(error, requestId);
501
+ if (retryAfter !== void 0) {
502
+ Object.assign(withRequestId, { retryAfter });
503
+ }
504
+ return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
505
+ };
352
506
  if (status === 400 || status === 422) {
353
- return attachRequestId(
507
+ return finalize(
354
508
  createValidationError(
355
509
  parsed.errorMessage,
356
510
  errorDetails,
357
511
  parsed.userMessage,
358
512
  suggestion,
359
513
  status
360
- ),
361
- requestId
514
+ )
362
515
  );
363
516
  }
364
517
  if (status === 401) {
365
- return attachRequestId(
518
+ return finalize(
366
519
  createAuthError(
367
520
  parsed.errorMessage,
368
521
  errorDetails,
369
522
  parsed.userMessage,
370
523
  suggestion
371
- ),
372
- requestId
524
+ )
373
525
  );
374
526
  }
375
527
  if (status === 403) {
376
- return attachRequestId(
528
+ return finalize(
377
529
  createPermissionError(
378
530
  parsed.errorMessage,
379
531
  errorDetails,
380
532
  parsed.userMessage,
381
533
  suggestion
382
- ),
383
- requestId
534
+ )
384
535
  );
385
536
  }
386
537
  if (status === 404) {
387
- return attachRequestId(
538
+ return finalize(
388
539
  createNotFoundError(
389
540
  parsed.errorMessage,
390
541
  errorDetails,
391
542
  parsed.userMessage,
392
543
  suggestion
393
- ),
394
- requestId
544
+ )
395
545
  );
396
546
  }
397
547
  if (status === 409) {
398
- return attachRequestId(
548
+ return finalize(
399
549
  createConflictError(
400
550
  parsed.errorMessage,
401
551
  errorDetails,
402
552
  parsed.userMessage,
403
553
  suggestion
404
- ),
405
- requestId
554
+ )
406
555
  );
407
556
  }
408
557
  if (status === 410) {
409
- return attachRequestId(
558
+ return finalize(
410
559
  createGoneError(
411
560
  parsed.errorMessage,
412
561
  errorDetails,
413
562
  parsed.userMessage,
414
563
  suggestion
415
- ),
416
- requestId
564
+ )
417
565
  );
418
566
  }
419
567
  if (status === 429) {
420
- return attachRequestId(
568
+ return finalize(
421
569
  createRateLimitError(
422
570
  parsed.errorMessage,
423
571
  retryAfter,
424
572
  errorDetails,
425
573
  parsed.userMessage,
426
574
  suggestion
427
- ),
428
- requestId
575
+ )
429
576
  );
430
577
  }
431
578
  if (status === 503) {
432
- return attachRequestId(
579
+ return finalize(
433
580
  createServiceUnavailableError(
434
581
  parsed.errorMessage,
435
582
  retryAfter,
436
583
  errorDetails,
437
584
  parsed.userMessage,
438
585
  suggestion
439
- ),
440
- requestId
586
+ )
441
587
  );
442
588
  }
443
- return attachRequestId(
589
+ return finalize(
444
590
  createNetworkError(
445
591
  parsed.errorMessage,
446
592
  status,
447
593
  errorDetails,
448
594
  parsed.userMessage,
449
595
  suggestion
450
- ),
451
- requestId
596
+ )
452
597
  );
453
598
  }
454
599
  async function httpFetch(url, options) {
@@ -461,6 +606,7 @@ async function httpFetch(url, options) {
461
606
  debug,
462
607
  retry,
463
608
  onUnauthorized,
609
+ errorFamily,
464
610
  ...requestInit
465
611
  } = options || {};
466
612
  const baseUrl = resolveApiUrl(apiUrl);
@@ -513,6 +659,8 @@ async function httpFetch(url, options) {
513
659
  headers: redactSensitiveHeaders(response.headers)
514
660
  });
515
661
  if (!response.ok) {
662
+ const parsed = await parseErrorBody(response);
663
+ const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
516
664
  if (isUsageLimitExceededResponse(response)) {
517
665
  const limit = parseInt(
518
666
  response.headers.get("X-Usage-Limit") || "0",
@@ -526,7 +674,7 @@ async function httpFetch(url, options) {
526
674
  response.headers.get("X-Usage-Remaining") || "0",
527
675
  10
528
676
  );
529
- throw attachRequestId(
677
+ const usageError = attachRequestId(
530
678
  createUsageLimitError(
531
679
  `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
532
680
  { limit, current, remaining },
@@ -540,9 +688,9 @@ async function httpFetch(url, options) {
540
688
  ),
541
689
  requestId
542
690
  );
691
+ throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
543
692
  }
544
- const parsed = await parseErrorBody(response);
545
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
693
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
546
694
  hasRetried401 = true;
547
695
  try {
548
696
  const newToken = await onUnauthorized();
@@ -564,13 +712,18 @@ async function httpFetch(url, options) {
564
712
  parsed,
565
713
  details,
566
714
  requestId,
567
- retryAfter
715
+ retryAfter.seconds,
716
+ errorFamily
568
717
  );
569
718
  const method2 = (requestInit.method || "GET").toUpperCase();
570
719
  const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
571
- if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
720
+ const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
721
+ if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
572
722
  lastError = error;
573
- const retryDelay = retryConfig.retryDelay(attempt);
723
+ const retryDelay = Math.max(
724
+ retryConfig.retryDelay(attempt),
725
+ (retryAfter.seconds ?? 0) * 1e3
726
+ );
574
727
  debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
575
728
  await delay(retryDelay);
576
729
  continue;
@@ -640,90 +793,45 @@ async function httpFetch(url, options) {
640
793
  throw lastError ?? new NetworkError("Request failed after retries");
641
794
  }
642
795
 
643
- // src/core/api/endpoints.ts
644
- var COMMERCE_ENDPOINTS = {
645
- orders: {
646
- create: "/api/orders/create",
647
- update: "/api/orders/update",
648
- confirmPayment: "/api/orders/confirm-payment",
649
- byPayment: "/api/orders/by-payment",
650
- cancel: "/api/orders/cancel",
651
- resolveCancelRefund: "/api/orders/resolve-cancel-refund",
652
- checkout: "/api/orders/checkout",
653
- createFulfillment: "/api/orders/create-fulfillment",
654
- updateFulfillment: "/api/orders/update-fulfillment"
655
- },
656
- transactions: {
657
- update: "/api/transactions/update"
658
- },
659
- returns: {
660
- create: "/api/returns/create",
661
- update: "/api/returns/update",
662
- returnRefund: "/api/returns/return-refund"
663
- },
664
- fulfillmentOrders: {
665
- prepare: "/api/fulfillment-orders/prepare-fulfillment-order"
666
- },
667
- fulfillments: {
668
- bulkImport: "/api/fulfillments/bulk-import"
669
- },
670
- carts: {
671
- mine: "/api/carts/mine",
672
- merge: "/api/carts/merge",
673
- addItem: "/api/carts/add-item",
674
- updateItem: "/api/carts/update-item",
675
- removeItem: "/api/carts/remove-item",
676
- applyDiscount: "/api/carts/apply-discount",
677
- removeDiscount: "/api/carts/remove-discount",
678
- clear: "/api/carts/clear"
679
- },
680
- products: {
681
- stockCheck: "/api/products/stock-check",
682
- stockSnapshot: "/api/products/stock",
683
- listingGroups: "/api/products/listing-groups",
684
- listingGroupsCatalog: "/api/products/listing-groups/catalog",
685
- listingGroupsQuery: "/api/products/listing-groups/query",
686
- listingGroupsQueryCatalog: "/api/products/listing-groups/query/catalog",
687
- detail: "/api/products/detail",
688
- detailCatalog: "/api/products/detail/catalog",
689
- upsert: "/api/products/upsert"
690
- }
691
- };
692
- var COMMERCE_ENDPOINT_PATHS = Object.values(
693
- COMMERCE_ENDPOINTS
694
- ).flatMap((group) => Object.values(group));
695
- var MEMBERSHIP_ENDPOINTS = {
696
- subscribe: "/api/memberships/subscribe",
697
- cancel: (id) => `/api/memberships/${id}/cancel`,
698
- me: "/api/memberships/me"
699
- };
700
-
701
796
  // src/core/internal/utils/query-string.ts
702
- function productDetailQuery(params) {
703
- const search = new URLSearchParams();
704
- if ("slug" in params) {
705
- search.set("slug", params.slug);
706
- } else {
707
- search.set("id", params.id);
797
+ function normalizedMarket(value) {
798
+ const market = value?.trim();
799
+ return market || void 0;
800
+ }
801
+ function appendProductLocaleSearchParams(search, options) {
802
+ if (options?.locale) search.set("locale", options.locale);
803
+ if (options?.fallbackLocale !== void 0) {
804
+ search.set(
805
+ "fallbackLocale",
806
+ options.fallbackLocale === false ? "none" : options.fallbackLocale
807
+ );
708
808
  }
709
- return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
710
809
  }
711
- function productDetailCatalogQuery(params) {
810
+ function productDetailSearchParams(params) {
712
811
  const search = new URLSearchParams();
713
812
  if ("slug" in params) {
714
813
  search.set("slug", params.slug);
715
814
  } else {
716
815
  search.set("id", params.id);
717
816
  }
718
- return `${COMMERCE_ENDPOINTS.products.detailCatalog}?${search}`;
719
- }
720
- function listingGroupsQuery(params) {
721
- return `${COMMERCE_ENDPOINTS.products.listingGroups}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
817
+ const market = normalizedMarket(params.market);
818
+ if (market) search.set("market", market);
819
+ appendProductLocaleSearchParams(search, params);
820
+ return search.toString();
722
821
  }
723
- function listingGroupsCatalogQuery(params) {
724
- return `${COMMERCE_ENDPOINTS.products.listingGroupsCatalog}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
822
+ function listingGroupsSearchParams(params) {
823
+ const ids = params.productIds.map(encodeURIComponent).join(",");
824
+ const search = new URLSearchParams();
825
+ const market = normalizedMarket(params.market);
826
+ if (market) search.set("market", market);
827
+ appendProductLocaleSearchParams(search, params);
828
+ const query = search.toString();
829
+ return `ids=${ids}${query ? `&${query}` : ""}`;
725
830
  }
726
831
  function appendListingGroupsQuerySearchParams(search, options) {
832
+ const market = normalizedMarket(options?.market);
833
+ if (market) search.set("market", market);
834
+ appendProductLocaleSearchParams(search, options);
727
835
  if (options?.page != null) search.set("page", String(options.page));
728
836
  if (options?.limit != null) search.set("limit", String(options.limit));
729
837
  if (options?.sort != null) {
@@ -734,20 +842,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
734
842
  search.set("whereJson", JSON.stringify(options.where));
735
843
  }
736
844
  }
737
- function listingGroupsQueryUrl(options) {
845
+ function listingPageSearchParams(options) {
738
846
  const search = new URLSearchParams();
739
847
  appendListingGroupsQuerySearchParams(search, options);
740
- const query = search.toString();
741
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
848
+ return search.toString();
742
849
  }
743
- function listingGroupsQueryCatalogUrl(options) {
744
- const search = new URLSearchParams();
745
- appendListingGroupsQuerySearchParams(search, options);
746
- const query = search.toString();
747
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQueryCatalog}${query ? `?${query}` : ""}`;
748
- }
749
- function stockSnapshotQuery(params) {
750
- return `${COMMERCE_ENDPOINTS.products.stockSnapshot}?variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
850
+ function stockSnapshotSearchParams(params) {
851
+ return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
751
852
  }
752
853
 
753
854
  // src/core/collection/http-client.ts
@@ -790,10 +891,15 @@ var HttpClient = class {
790
891
  throw err;
791
892
  }
792
893
  }
793
- buildUrl(endpoint, options) {
794
- if (!options) return endpoint;
795
- const queryString = stringify(options, { addQueryPrefix: true });
796
- return queryString ? `${endpoint}${queryString}` : endpoint;
894
+ buildUrl(endpoint2, options) {
895
+ if (!options) return endpoint2;
896
+ const { fallbackLocale, ...rest } = options;
897
+ const queryOptions = fallbackLocale === void 0 ? rest : {
898
+ ...rest,
899
+ "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
900
+ };
901
+ const queryString = stringify(queryOptions, { addQueryPrefix: true });
902
+ return queryString ? `${endpoint2}${queryString}` : endpoint2;
797
903
  }
798
904
  assertJsonResponse(response) {
799
905
  const contentType = response.headers.get("content-type");
@@ -984,16 +1090,16 @@ var CollectionQueryBuilder = class {
984
1090
  * @returns Payload CMS mutation response with doc and message
985
1091
  */
986
1092
  async create(data, options) {
987
- const endpoint = `/api/${String(this.collection)}`;
1093
+ const endpoint2 = `/api/${String(this.collection)}`;
988
1094
  if (options?.file) {
989
1095
  return this.api.requestCreateWithFile(
990
- endpoint,
1096
+ endpoint2,
991
1097
  data,
992
1098
  options.file,
993
1099
  options.filename
994
1100
  );
995
1101
  }
996
- return this.api.requestCreate(endpoint, data);
1102
+ return this.api.requestCreate(endpoint2, data);
997
1103
  }
998
1104
  /**
999
1105
  * Update a document by ID
@@ -1001,16 +1107,16 @@ var CollectionQueryBuilder = class {
1001
1107
  * @returns Payload CMS mutation response with doc and message
1002
1108
  */
1003
1109
  async update(id, data, options) {
1004
- const endpoint = `/api/${String(this.collection)}/${String(id)}`;
1110
+ const endpoint2 = `/api/${String(this.collection)}/${String(id)}`;
1005
1111
  if (options?.file) {
1006
1112
  return this.api.requestUpdateWithFile(
1007
- endpoint,
1113
+ endpoint2,
1008
1114
  data,
1009
1115
  options.file,
1010
1116
  options.filename
1011
1117
  );
1012
1118
  }
1013
- return this.api.requestUpdate(endpoint, data);
1119
+ return this.api.requestUpdate(endpoint2, data);
1014
1120
  }
1015
1121
  /**
1016
1122
  * Count documents
@@ -1106,8 +1212,8 @@ var CollectionClient = class extends HttpClient {
1106
1212
  * Find documents (list query)
1107
1213
  * GET /api/{collection}
1108
1214
  */
1109
- async requestFind(endpoint, options) {
1110
- const url = this.buildUrl(endpoint, options);
1215
+ async requestFind(endpoint2, options) {
1216
+ const url = this.buildUrl(endpoint2, options);
1111
1217
  const response = await this.fetchWithTracking(url, {
1112
1218
  ...this.defaultOptions,
1113
1219
  method: "GET"
@@ -1118,8 +1224,8 @@ var CollectionClient = class extends HttpClient {
1118
1224
  * Find-like response from a custom endpoint
1119
1225
  * POST /api/...custom-endpoint
1120
1226
  */
1121
- async requestFindEndpoint(endpoint, data) {
1122
- const response = await this.fetchWithTracking(endpoint, {
1227
+ async requestFindEndpoint(endpoint2, data) {
1228
+ const response = await this.fetchWithTracking(endpoint2, {
1123
1229
  ...this.defaultOptions,
1124
1230
  method: "POST",
1125
1231
  body: data ? JSON.stringify(data) : void 0
@@ -1129,8 +1235,8 @@ var CollectionClient = class extends HttpClient {
1129
1235
  /**
1130
1236
  * Find-like response from a cacheable GET custom endpoint.
1131
1237
  */
1132
- async requestFindEndpointGet(endpoint) {
1133
- const response = await this.fetchWithTracking(endpoint, {
1238
+ async requestFindEndpointGet(endpoint2) {
1239
+ const response = await this.fetchWithTracking(endpoint2, {
1134
1240
  ...this.defaultOptions,
1135
1241
  method: "GET"
1136
1242
  });
@@ -1140,8 +1246,8 @@ var CollectionClient = class extends HttpClient {
1140
1246
  * Find document by ID
1141
1247
  * GET /api/{collection}/{id}
1142
1248
  */
1143
- async requestFindById(endpoint, options) {
1144
- const url = this.buildUrl(endpoint, options);
1249
+ async requestFindById(endpoint2, options) {
1250
+ const url = this.buildUrl(endpoint2, options);
1145
1251
  const response = await this.fetchWithTracking(url, {
1146
1252
  ...this.defaultOptions,
1147
1253
  method: "GET"
@@ -1152,8 +1258,8 @@ var CollectionClient = class extends HttpClient {
1152
1258
  * Create document
1153
1259
  * POST /api/{collection}
1154
1260
  */
1155
- async requestCreate(endpoint, data) {
1156
- const response = await this.fetchWithTracking(endpoint, {
1261
+ async requestCreate(endpoint2, data) {
1262
+ const response = await this.fetchWithTracking(endpoint2, {
1157
1263
  ...this.defaultOptions,
1158
1264
  method: "POST",
1159
1265
  body: data ? JSON.stringify(data) : void 0
@@ -1164,8 +1270,8 @@ var CollectionClient = class extends HttpClient {
1164
1270
  * Update document
1165
1271
  * PATCH /api/{collection}/{id}
1166
1272
  */
1167
- async requestUpdate(endpoint, data) {
1168
- const response = await this.fetchWithTracking(endpoint, {
1273
+ async requestUpdate(endpoint2, data) {
1274
+ const response = await this.fetchWithTracking(endpoint2, {
1169
1275
  ...this.defaultOptions,
1170
1276
  method: "PATCH",
1171
1277
  body: data ? JSON.stringify(data) : void 0
@@ -1176,8 +1282,8 @@ var CollectionClient = class extends HttpClient {
1176
1282
  * Count documents
1177
1283
  * GET /api/{collection}/count
1178
1284
  */
1179
- async requestCount(endpoint, options) {
1180
- const url = this.buildUrl(endpoint, options);
1285
+ async requestCount(endpoint2, options) {
1286
+ const url = this.buildUrl(endpoint2, options);
1181
1287
  const response = await this.fetchWithTracking(url, {
1182
1288
  ...this.defaultOptions,
1183
1289
  method: "GET"
@@ -1188,8 +1294,8 @@ var CollectionClient = class extends HttpClient {
1188
1294
  * Update multiple documents (bulk update)
1189
1295
  * PATCH /api/{collection}
1190
1296
  */
1191
- async requestUpdateMany(endpoint, data) {
1192
- const response = await this.fetchWithTracking(endpoint, {
1297
+ async requestUpdateMany(endpoint2, data) {
1298
+ const response = await this.fetchWithTracking(endpoint2, {
1193
1299
  ...this.defaultOptions,
1194
1300
  method: "PATCH",
1195
1301
  body: JSON.stringify(data)
@@ -1200,8 +1306,8 @@ var CollectionClient = class extends HttpClient {
1200
1306
  * Delete document
1201
1307
  * DELETE /api/{collection}/{id}
1202
1308
  */
1203
- async requestDelete(endpoint, options) {
1204
- const url = this.buildUrl(endpoint, options);
1309
+ async requestDelete(endpoint2, options) {
1310
+ const url = this.buildUrl(endpoint2, options);
1205
1311
  const response = await this.fetchWithTracking(url, {
1206
1312
  ...this.defaultOptions,
1207
1313
  method: "DELETE"
@@ -1212,8 +1318,8 @@ var CollectionClient = class extends HttpClient {
1212
1318
  * Delete multiple documents (bulk delete)
1213
1319
  * DELETE /api/{collection}
1214
1320
  */
1215
- async requestDeleteMany(endpoint, data) {
1216
- const response = await this.fetchWithTracking(endpoint, {
1321
+ async requestDeleteMany(endpoint2, data) {
1322
+ const response = await this.fetchWithTracking(endpoint2, {
1217
1323
  ...this.defaultOptions,
1218
1324
  method: "DELETE",
1219
1325
  body: JSON.stringify(data)
@@ -1224,8 +1330,8 @@ var CollectionClient = class extends HttpClient {
1224
1330
  * Create document with file upload
1225
1331
  * POST /api/{collection} (multipart/form-data)
1226
1332
  */
1227
- async requestCreateWithFile(endpoint, data, file, filename) {
1228
- const response = await this.fetchWithTracking(endpoint, {
1333
+ async requestCreateWithFile(endpoint2, data, file, filename) {
1334
+ const response = await this.fetchWithTracking(endpoint2, {
1229
1335
  ...this.defaultOptions,
1230
1336
  method: "POST",
1231
1337
  body: buildPayloadFormData(data, file, filename)
@@ -1236,8 +1342,8 @@ var CollectionClient = class extends HttpClient {
1236
1342
  * Update document with file upload
1237
1343
  * PATCH /api/{collection}/{id} (multipart/form-data)
1238
1344
  */
1239
- async requestUpdateWithFile(endpoint, data, file, filename) {
1240
- const response = await this.fetchWithTracking(endpoint, {
1345
+ async requestUpdateWithFile(endpoint2, data, file, filename) {
1346
+ const response = await this.fetchWithTracking(endpoint2, {
1241
1347
  ...this.defaultOptions,
1242
1348
  method: "PATCH",
1243
1349
  body: buildPayloadFormData(data, file, filename)
@@ -1252,53 +1358,347 @@ var ServerCollectionClient = class extends CollectionClient {
1252
1358
  };
1253
1359
 
1254
1360
  // src/core/api/parse-response.ts
1255
- async function parseApiResponse(response, endpoint) {
1256
- let data;
1361
+ async function parseApiResponse(response, endpoint2, options = {}) {
1362
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
1363
+ return void 0;
1364
+ }
1365
+ let parsed;
1257
1366
  try {
1258
- data = await response.json();
1367
+ parsed = await response.json();
1259
1368
  } catch {
1260
1369
  throw createApiError(
1261
- `Invalid JSON response from ${endpoint}`,
1370
+ `Invalid JSON response from ${endpoint2}`,
1262
1371
  response.status,
1263
1372
  void 0,
1264
1373
  "Server returned an invalid response.",
1265
1374
  "Check if the API endpoint is available."
1266
1375
  );
1267
1376
  }
1377
+ if (parsed === null || typeof parsed !== "object") {
1378
+ return parsed;
1379
+ }
1380
+ const data = parsed;
1268
1381
  if (data.error) {
1269
1382
  const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1270
1383
  const reason = typeof data.reason === "string" ? data.reason : void 0;
1271
1384
  const requestId = response.headers.get("x-request-id") ?? void 0;
1272
- const retryAfterRaw = response.headers.get("Retry-After");
1273
- const retryAfter = retryAfterRaw ? parseInt(retryAfterRaw, 10) || void 0 : void 0;
1385
+ const retryAfter = parseRetryAfter(response).seconds;
1386
+ let error;
1274
1387
  if (reason === "validation_failed") {
1275
- throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
1276
- }
1277
- if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1278
- throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
1388
+ error = createValidationError(errorMessage, data, errorMessage);
1389
+ } else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1390
+ error = createAuthError(errorMessage, data, errorMessage);
1391
+ } else if (reason === "forbidden") {
1392
+ error = createPermissionError(errorMessage, data, errorMessage);
1393
+ } else if (reason === "rate_limit_exceeded") {
1394
+ error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
1395
+ } else if (reason === "not_found") {
1396
+ error = createNotFoundError(errorMessage, data, errorMessage);
1397
+ } else if (reason === "conflict") {
1398
+ error = createConflictError(errorMessage, data, errorMessage);
1399
+ } else {
1400
+ error = createApiError(
1401
+ errorMessage,
1402
+ response.status,
1403
+ data,
1404
+ errorMessage,
1405
+ "An error occurred while processing the request."
1406
+ );
1279
1407
  }
1280
- if (reason === "forbidden") {
1281
- throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1408
+ const withRequestId = attachRequestId(error, requestId);
1409
+ if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
1410
+ throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
1411
+ }
1412
+ return data;
1413
+ }
1414
+
1415
+ // ../../internal/http-contracts/src/index.ts
1416
+ var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1417
+ var operation = (collection, method, path) => Object.freeze({
1418
+ [operationBrand]: true,
1419
+ collection,
1420
+ method,
1421
+ path
1422
+ });
1423
+ var COMMERCE_ENDPOINT_OPERATIONS = {
1424
+ products: {
1425
+ detail: operation("products", "get", "/detail"),
1426
+ detailCatalog: operation("products", "get", "/detail/catalog"),
1427
+ listingGroups: operation("products", "get", "/listing-groups"),
1428
+ listingGroupsCatalog: operation(
1429
+ "products",
1430
+ "get",
1431
+ "/listing-groups/catalog"
1432
+ ),
1433
+ listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
1434
+ listingGroupsQueryGet: operation(
1435
+ "products",
1436
+ "get",
1437
+ "/listing-groups/query"
1438
+ ),
1439
+ listingGroupsQueryCatalog: operation(
1440
+ "products",
1441
+ "get",
1442
+ "/listing-groups/query/catalog"
1443
+ ),
1444
+ stockCheck: operation("products", "post", "/stock-check"),
1445
+ stockSnapshot: operation("products", "get", "/stock"),
1446
+ upsert: operation("products", "post", "/upsert")
1447
+ },
1448
+ orders: {
1449
+ create: operation("orders", "post", "/create"),
1450
+ update: operation("orders", "post", "/update"),
1451
+ confirmPayment: operation("orders", "post", "/confirm-payment"),
1452
+ byPayment: operation("orders", "get", "/by-payment"),
1453
+ cancel: operation("orders", "post", "/cancel"),
1454
+ resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1455
+ checkout: operation("orders", "post", "/checkout"),
1456
+ createFulfillment: operation("orders", "post", "/create-fulfillment"),
1457
+ updateFulfillment: operation("orders", "post", "/update-fulfillment")
1458
+ },
1459
+ checkouts: {
1460
+ detail: operation("checkouts", "post", "/detail"),
1461
+ query: operation("checkouts", "post", "/query")
1462
+ },
1463
+ transactions: {
1464
+ update: operation("transactions", "post", "/update")
1465
+ },
1466
+ returns: {
1467
+ create: operation("returns", "post", "/create"),
1468
+ update: operation("returns", "post", "/update"),
1469
+ returnRefund: operation("returns", "post", "/return-refund")
1470
+ },
1471
+ fulfillmentOrders: {
1472
+ prepare: operation(
1473
+ "fulfillment-orders",
1474
+ "post",
1475
+ "/prepare-fulfillment-order"
1476
+ )
1477
+ },
1478
+ fulfillments: {
1479
+ bulkImport: operation("fulfillments", "post", "/bulk-import")
1480
+ },
1481
+ carts: {
1482
+ create: operation("carts", "post", "/create"),
1483
+ retrieve: operation("carts", "post", "/retrieve"),
1484
+ mine: operation("carts", "post", "/mine"),
1485
+ merge: operation("carts", "post", "/merge"),
1486
+ addItem: operation("carts", "post", "/add-item"),
1487
+ updateItem: operation("carts", "post", "/update-item"),
1488
+ removeItem: operation("carts", "post", "/remove-item"),
1489
+ updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
1490
+ updateAttributes: operation("carts", "post", "/update-attributes"),
1491
+ clear: operation("carts", "post", "/clear")
1492
+ },
1493
+ paymentSessions: {
1494
+ create: operation("payment-sessions", "post", "/create"),
1495
+ retrieve: operation("payment-sessions", "post", "/retrieve"),
1496
+ cancel: operation("payment-sessions", "post", "/cancel"),
1497
+ server: {
1498
+ create: operation("payment-sessions", "post", "/server/create"),
1499
+ retrieve: operation("payment-sessions", "post", "/server/retrieve"),
1500
+ cancel: operation("payment-sessions", "post", "/server/cancel"),
1501
+ confirm: operation("payment-sessions", "post", "/server/confirm")
1502
+ },
1503
+ custom: {
1504
+ create: operation("orders", "post", "/custom-payment-sessions"),
1505
+ confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
1282
1506
  }
1283
- if (reason === "rate_limit_exceeded") {
1284
- throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1507
+ },
1508
+ shippingPolicies: {
1509
+ calculate: operation("shipping-policies", "post", "/calculate")
1510
+ },
1511
+ discounts: {
1512
+ validate: operation("discounts", "post", "/validate")
1513
+ }
1514
+ };
1515
+ var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1516
+ subscribe: operation(null, "post", "/memberships/subscribe"),
1517
+ cancel: operation(null, "post", "/memberships/:id/cancel"),
1518
+ me: operation(null, "get", "/memberships/me")
1519
+ };
1520
+ var EVENTS_ENDPOINT_OPERATIONS = {
1521
+ occurrences: {
1522
+ range: operation("event-occurrences", "get", "/range"),
1523
+ admissionAvailability: operation(
1524
+ "event-occurrences",
1525
+ "get",
1526
+ "/admission-availability"
1527
+ )
1528
+ }
1529
+ };
1530
+ function resolveOperationTemplate(descriptor) {
1531
+ return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
1532
+ }
1533
+ function resolveOperationPath(descriptor, options) {
1534
+ const path = resolveOperationTemplate(descriptor).replace(
1535
+ /:([A-Za-z][A-Za-z0-9_]*)/g,
1536
+ (_, key) => {
1537
+ const value = options?.pathParams?.[key];
1538
+ if (value === void 0) {
1539
+ throw new TypeError(`Missing path parameter: ${key}`);
1540
+ }
1541
+ return encodeURIComponent(value);
1285
1542
  }
1286
- if (reason === "not_found") {
1287
- throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1543
+ );
1544
+ const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
1545
+ if (unresolved) {
1546
+ throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
1547
+ }
1548
+ const query = options?.query?.toString().replace(/^\?/, "");
1549
+ return query ? `${path}?${query}` : path;
1550
+ }
1551
+ function resolveOperationMethod(descriptor) {
1552
+ return descriptor.method.toUpperCase();
1553
+ }
1554
+
1555
+ // src/core/api/endpoints.ts
1556
+ var endpoint = (method, path) => ({ method, path });
1557
+ var sharedEndpoint = (descriptor) => descriptor;
1558
+ function resolveOperationMethod2(descriptor) {
1559
+ return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1560
+ }
1561
+ function resolveOperationPath2(descriptor, options) {
1562
+ if ("collection" in descriptor) {
1563
+ return resolveOperationPath(descriptor, options);
1564
+ }
1565
+ const query = options?.query?.toString().replace(/^\?/, "");
1566
+ return query ? `${descriptor.path}?${query}` : descriptor.path;
1567
+ }
1568
+ var COMMERCE_ENDPOINTS = {
1569
+ products: {
1570
+ detail: endpoint("GET", "/api/products/detail"),
1571
+ detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1572
+ listingGroups: endpoint("GET", "/api/products/listing-groups"),
1573
+ listingGroupsCatalog: endpoint(
1574
+ "GET",
1575
+ "/api/products/listing-groups/catalog"
1576
+ ),
1577
+ listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1578
+ listingGroupsQueryCatalog: endpoint(
1579
+ "GET",
1580
+ "/api/products/listing-groups/query/catalog"
1581
+ ),
1582
+ stockCheck: endpoint("POST", "/api/products/stock-check"),
1583
+ stockSnapshot: endpoint("GET", "/api/products/stock"),
1584
+ upsert: endpoint("POST", "/api/products/upsert")
1585
+ },
1586
+ orders: {
1587
+ update: endpoint("POST", "/api/orders/update"),
1588
+ byPayment: endpoint("GET", "/api/orders/by-payment"),
1589
+ cancel: endpoint("POST", "/api/orders/cancel"),
1590
+ resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1591
+ createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1592
+ updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1593
+ },
1594
+ checkouts: {
1595
+ create: endpoint("POST", "/api/orders/checkout"),
1596
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1597
+ server: {
1598
+ create: endpoint("POST", "/api/orders/checkout"),
1599
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1600
+ query: endpoint("POST", "/api/checkouts/query")
1288
1601
  }
1289
- if (reason === "conflict") {
1290
- throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1602
+ },
1603
+ returns: {
1604
+ create: endpoint("POST", "/api/returns/create"),
1605
+ update: endpoint("POST", "/api/returns/update"),
1606
+ returnRefund: endpoint("POST", "/api/returns/return-refund")
1607
+ },
1608
+ fulfillmentOrders: {
1609
+ prepare: endpoint(
1610
+ "POST",
1611
+ "/api/fulfillment-orders/prepare-fulfillment-order"
1612
+ )
1613
+ },
1614
+ fulfillments: {
1615
+ bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1616
+ },
1617
+ carts: {
1618
+ create: endpoint("POST", "/api/carts/create"),
1619
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1620
+ mine: endpoint("POST", "/api/carts/mine"),
1621
+ merge: endpoint("POST", "/api/carts/merge"),
1622
+ server: {
1623
+ // Server credentials are an authorization lane, not a second Cart
1624
+ // transport. These must stay bound to the registered shared operations.
1625
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
1626
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1627
+ mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
1628
+ merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
1629
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1630
+ updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
1631
+ removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
1632
+ updateDiscountCodes: sharedEndpoint(
1633
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
1634
+ ),
1635
+ updateAttributes: sharedEndpoint(
1636
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
1637
+ ),
1638
+ clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
1639
+ },
1640
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1641
+ updateItem: endpoint("POST", "/api/carts/update-item"),
1642
+ removeItem: endpoint("POST", "/api/carts/remove-item"),
1643
+ updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
1644
+ updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
1645
+ clear: endpoint("POST", "/api/carts/clear")
1646
+ },
1647
+ paymentSessions: {
1648
+ create: endpoint("POST", "/api/payment-sessions/create"),
1649
+ retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
1650
+ cancel: endpoint("POST", "/api/payment-sessions/cancel"),
1651
+ custom: {
1652
+ create: sharedEndpoint(
1653
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.create
1654
+ ),
1655
+ confirm: sharedEndpoint(
1656
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.confirm
1657
+ )
1658
+ },
1659
+ server: {
1660
+ create: endpoint("POST", "/api/payment-sessions/server/create"),
1661
+ retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
1662
+ cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
1663
+ confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
1291
1664
  }
1292
- throw attachRequestId(
1293
- createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1294
- requestId
1295
- );
1665
+ },
1666
+ shippingPolicies: {
1667
+ calculate: endpoint("POST", "/api/shipping-policies/calculate")
1296
1668
  }
1297
- return data;
1669
+ };
1670
+ function isCommerceEndpointDescriptor(value) {
1671
+ if (!value || typeof value !== "object") return false;
1672
+ const candidate = value;
1673
+ return typeof candidate.method === "string" && typeof candidate.path === "string";
1674
+ }
1675
+ function flattenEndpointPaths(value) {
1676
+ if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1677
+ if (!value || typeof value !== "object") return [];
1678
+ return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1298
1679
  }
1680
+ function flattenEndpointDescriptors(value) {
1681
+ if (isCommerceEndpointDescriptor(value)) return [value];
1682
+ if (!value || typeof value !== "object") return [];
1683
+ return Object.values(value).flatMap(
1684
+ (entry) => flattenEndpointDescriptors(entry)
1685
+ );
1686
+ }
1687
+ var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1688
+ var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1689
+ var MEMBERSHIP_ENDPOINTS = {
1690
+ subscribe: "/api/memberships/subscribe",
1691
+ cancel: (id) => `/api/memberships/${id}/cancel`,
1692
+ me: "/api/memberships/me"
1693
+ };
1694
+ var MEMBERSHIP_ENDPOINT_PATHS = [
1695
+ MEMBERSHIP_ENDPOINTS.subscribe,
1696
+ MEMBERSHIP_ENDPOINTS.cancel(":id"),
1697
+ MEMBERSHIP_ENDPOINTS.me
1698
+ ];
1299
1699
 
1300
1700
  // src/core/api/customer-scoped-api.ts
1301
- var CustomerScopedApi = class {
1701
+ var CustomerScopedTransport = class {
1302
1702
  constructor(apiName, options) {
1303
1703
  if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
1304
1704
  throw createConfigError(
@@ -1316,10 +1716,10 @@ var CustomerScopedApi = class {
1316
1716
  this.onUnauthorized = options.onUnauthorized;
1317
1717
  this.onRequestId = options.onRequestId;
1318
1718
  }
1319
- async request(endpoint, options) {
1719
+ async request(endpoint2, options) {
1320
1720
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1321
1721
  try {
1322
- const response = await httpFetch(endpoint, {
1722
+ const response = await httpFetch(endpoint2, {
1323
1723
  method: options.method,
1324
1724
  apiUrl: this.apiUrl,
1325
1725
  publishableKey: this.publishableKey,
@@ -1329,10 +1729,13 @@ var CustomerScopedApi = class {
1329
1729
  ...options.body !== void 0 && {
1330
1730
  body: JSON.stringify(options.body)
1331
1731
  },
1332
- ...options.headers && { headers: options.headers }
1732
+ ...options.headers && { headers: options.headers },
1733
+ ...options.errorFamily && { errorFamily: options.errorFamily }
1333
1734
  });
1334
1735
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1335
- return parseApiResponse(response, endpoint);
1736
+ return parseApiResponse(response, endpoint2, {
1737
+ errorFamily: options.errorFamily
1738
+ });
1336
1739
  } catch (err) {
1337
1740
  const id = err instanceof SDKError ? err.requestId ?? null : null;
1338
1741
  this.onRequestId?.(id);
@@ -1340,6 +1743,26 @@ var CustomerScopedApi = class {
1340
1743
  }
1341
1744
  }
1342
1745
  };
1746
+ var CustomerScopedApi = class {
1747
+ constructor(apiName, options) {
1748
+ this.transport = new CustomerScopedTransport(apiName, options);
1749
+ }
1750
+ requestEndpoint(endpoint2, body, options) {
1751
+ return this.transport.request(resolveOperationPath2(endpoint2, options), {
1752
+ method: resolveOperationMethod2(endpoint2),
1753
+ body,
1754
+ headers: options?.headers
1755
+ });
1756
+ }
1757
+ };
1758
+ var RawCustomerScopedApi = class {
1759
+ constructor(apiName, options) {
1760
+ this.transport = new CustomerScopedTransport(apiName, options);
1761
+ }
1762
+ request(endpoint2, options) {
1763
+ return this.transport.request(endpoint2, options);
1764
+ }
1765
+ };
1343
1766
 
1344
1767
  // src/core/community/community-client.ts
1345
1768
  var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
@@ -1350,7 +1773,7 @@ function unwrapPayloadDoc(value) {
1350
1773
  }
1351
1774
  return value;
1352
1775
  }
1353
- var CommunityClient = class extends CustomerScopedApi {
1776
+ var CommunityClient = class extends RawCustomerScopedApi {
1354
1777
  constructor(options) {
1355
1778
  super("CommunityClient", { ...options, requiresCredential: false });
1356
1779
  }
@@ -1394,11 +1817,11 @@ var CommunityClient = class extends CustomerScopedApi {
1394
1817
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1395
1818
  return `/api/comments/public?${urlParams.toString()}`;
1396
1819
  }
1397
- async execute(endpoint, method, body) {
1398
- return this.request(endpoint, { method, body });
1820
+ async execute(endpoint2, method, body) {
1821
+ return this.request(endpoint2, { method, body });
1399
1822
  }
1400
- async executeDoc(endpoint, method, body) {
1401
- const response = await this.execute(endpoint, method, body);
1823
+ async executeDoc(endpoint2, method, body) {
1824
+ const response = await this.execute(endpoint2, method, body);
1402
1825
  return unwrapPayloadDoc(response);
1403
1826
  }
1404
1827
  createPost(params) {
@@ -1637,140 +2060,1399 @@ var CommunityClient = class extends CustomerScopedApi {
1637
2060
  };
1638
2061
 
1639
2062
  // src/core/api/base-api.ts
1640
- var BaseApi = class {
2063
+ var ServerApiTransport = class {
1641
2064
  constructor(apiName, options) {
1642
2065
  if (!options.secretKey) {
1643
2066
  throw createConfigError(`secretKey is required for ${apiName}.`);
1644
2067
  }
1645
- this.publishableKey = requirePublishableKeyForSecret(
1646
- apiName,
1647
- options.publishableKey,
1648
- options.secretKey
2068
+ this.publishableKey = requirePublishableKeyForSecret(
2069
+ apiName,
2070
+ options.publishableKey,
2071
+ options.secretKey
2072
+ );
2073
+ this.secretKey = options.secretKey;
2074
+ this.apiUrl = options.apiUrl;
2075
+ this.onRequestId = options.onRequestId;
2076
+ }
2077
+ async request(endpoint2, body, options) {
2078
+ const method = options?.method ?? "POST";
2079
+ try {
2080
+ const response = await httpFetch(endpoint2, {
2081
+ method,
2082
+ apiUrl: this.apiUrl,
2083
+ publishableKey: this.publishableKey,
2084
+ secretKey: this.secretKey,
2085
+ ...body !== void 0 && { body: JSON.stringify(body) },
2086
+ ...options?.headers && { headers: options.headers },
2087
+ ...options?.errorFamily && { errorFamily: options.errorFamily }
2088
+ });
2089
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
2090
+ return parseApiResponse(response, endpoint2, {
2091
+ errorFamily: options?.errorFamily
2092
+ });
2093
+ } catch (err) {
2094
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
2095
+ this.onRequestId?.(id);
2096
+ throw err;
2097
+ }
2098
+ }
2099
+ };
2100
+ var BaseApi = class {
2101
+ constructor(apiName, options) {
2102
+ this.transport = new ServerApiTransport(apiName, options);
2103
+ }
2104
+ requestEndpoint(endpoint2, body, options) {
2105
+ return this.transport.request(
2106
+ resolveOperationPath2(endpoint2, options),
2107
+ body,
2108
+ {
2109
+ method: resolveOperationMethod2(endpoint2),
2110
+ headers: options?.headers
2111
+ }
2112
+ );
2113
+ }
2114
+ };
2115
+ var RawBaseApi = class {
2116
+ constructor(apiName, options) {
2117
+ this.transport = new ServerApiTransport(apiName, options);
2118
+ this.publishableKey = requirePublishableKeyForSecret(
2119
+ apiName,
2120
+ options.publishableKey,
2121
+ options.secretKey
2122
+ );
2123
+ this.secretKey = options.secretKey;
2124
+ this.apiUrl = options.apiUrl;
2125
+ this.onRequestId = options.onRequestId;
2126
+ }
2127
+ request(endpoint2, body, options) {
2128
+ return this.transport.request(endpoint2, body, options);
2129
+ }
2130
+ };
2131
+
2132
+ // src/core/community/moderation-api.ts
2133
+ var ModerationApi = class extends RawBaseApi {
2134
+ constructor(options) {
2135
+ super("ModerationApi", options);
2136
+ }
2137
+ banCustomer(params) {
2138
+ return this.request(
2139
+ "/api/community-bans/ban-bearer",
2140
+ params,
2141
+ { method: "POST" }
2142
+ );
2143
+ }
2144
+ unbanCustomer(params) {
2145
+ return this.request(
2146
+ "/api/community-bans/unban-bearer",
2147
+ params,
2148
+ { method: "POST" }
2149
+ );
2150
+ }
2151
+ };
2152
+
2153
+ // src/core/api/canonical-response.ts
2154
+ var CART_STATUSES = ["active", "completed", "abandoned"];
2155
+ var MAX_CART_LINE_QUANTITY = 99;
2156
+ var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
2157
+ var MAX_COMMERCE_ADDRESS_LENGTH = 500;
2158
+ var MAX_COMMERCE_EMAIL_LENGTH = 254;
2159
+ var MAX_COMMERCE_PHONE_LENGTH = 32;
2160
+ var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
2161
+ var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
2162
+ var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
2163
+ var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
2164
+ var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
2165
+ var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
2166
+ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2167
+ var PAYMENT_PROVIDERS = ["toss"];
2168
+ var PAYMENT_PROVIDER_STATUSES = [
2169
+ "requires_payment_method",
2170
+ "requires_action",
2171
+ "requires_confirmation",
2172
+ "initializing",
2173
+ "processing",
2174
+ "authorized",
2175
+ "canceling",
2176
+ "unknown",
2177
+ "captured",
2178
+ "failed",
2179
+ "canceled"
2180
+ ];
2181
+ var PAYMENT_FAILURE_REASONS = [
2182
+ "payment_declined",
2183
+ "authentication_failed",
2184
+ "authorization_expired",
2185
+ "payment_method_unavailable",
2186
+ "provider_terminal_failure",
2187
+ "unknown_provider_terminal_failure"
2188
+ ];
2189
+ var CART_WARNING_CODES = [
2190
+ "DISCOUNT_CODE_NOT_HONOURED",
2191
+ "DISCOUNT_CURRENTLY_INACTIVE",
2192
+ "DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
2193
+ "DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
2194
+ "DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
2195
+ "DISCOUNT_NO_ENTITLED_LINE_ITEMS",
2196
+ "DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
2197
+ "DISCOUNT_NOT_FOUND",
2198
+ "DISCOUNT_PURCHASE_NOT_IN_RANGE",
2199
+ "DISCOUNT_USAGE_LIMIT_REACHED",
2200
+ "MERCHANDISE_NOT_ENOUGH_STOCK",
2201
+ "MERCHANDISE_OUT_OF_STOCK"
2202
+ ];
2203
+ function invalidCanonicalResponse(resource, details) {
2204
+ throw createApiError(
2205
+ `Invalid canonical ${resource} response.`,
2206
+ 502,
2207
+ { resource, ...details },
2208
+ `The server returned an incompatible ${resource} response.`,
2209
+ "Verify that the Console commerce contract is deployed before using this SDK version."
2210
+ );
2211
+ }
2212
+ function fail(resource, path, expected) {
2213
+ invalidCanonicalResponse(resource, { path, expected });
2214
+ }
2215
+ function record(value, resource, path) {
2216
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2217
+ fail(resource, path, "object");
2218
+ }
2219
+ return value;
2220
+ }
2221
+ function exact(value, required, optional, resource, path) {
2222
+ for (const key of required) {
2223
+ if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
2224
+ }
2225
+ const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
2226
+ const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2227
+ if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2228
+ }
2229
+ function string(value, resource, path) {
2230
+ if (typeof value !== "string" || value.length === 0) {
2231
+ fail(resource, path, "non-empty string");
2232
+ }
2233
+ return value;
2234
+ }
2235
+ function boundedString(value, maxLength, resource, path, allowEmpty = false) {
2236
+ if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
2237
+ fail(
2238
+ resource,
2239
+ path,
2240
+ `${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
2241
+ );
2242
+ }
2243
+ return value;
2244
+ }
2245
+ function nullableString(value, resource, path) {
2246
+ if (value !== null && typeof value !== "string") {
2247
+ fail(resource, path, "string or null");
2248
+ }
2249
+ }
2250
+ function cartLineQuantity(value, resource, path) {
2251
+ const quantity = positiveInteger(value, resource, path);
2252
+ if (quantity > MAX_CART_LINE_QUANTITY) {
2253
+ fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
2254
+ }
2255
+ return quantity;
2256
+ }
2257
+ function boolean(value, resource, path) {
2258
+ if (typeof value !== "boolean") fail(resource, path, "boolean");
2259
+ }
2260
+ function safeMinor(value, resource, path) {
2261
+ if (!Number.isSafeInteger(value) || value < 0) {
2262
+ fail(resource, path, "non-negative safe integer");
2263
+ }
2264
+ return value;
2265
+ }
2266
+ function positiveInteger(value, resource, path) {
2267
+ if (!Number.isSafeInteger(value) || value <= 0) {
2268
+ fail(resource, path, "positive safe integer");
2269
+ }
2270
+ return value;
2271
+ }
2272
+ function enumValue(value, values, resource, path) {
2273
+ if (typeof value !== "string" || !values.includes(value)) {
2274
+ fail(resource, path, values.join(" | "));
2275
+ }
2276
+ return value;
2277
+ }
2278
+ function timestamp(value, resource, path) {
2279
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
2280
+ fail(resource, path, "ISO 8601 timestamp with offset");
2281
+ }
2282
+ }
2283
+ function currency(value, resource, path) {
2284
+ if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
2285
+ fail(resource, path, "three-letter uppercase currency code");
2286
+ }
2287
+ }
2288
+ function array(value, resource, path) {
2289
+ if (!Array.isArray(value)) fail(resource, path, "array");
2290
+ return value;
2291
+ }
2292
+ function optionalNullableNumber(value, resource, path) {
2293
+ if (value !== void 0 && value !== null && typeof value !== "number") {
2294
+ fail(resource, path, "number or null");
2295
+ }
2296
+ }
2297
+ function validateMediaSize(value, resource, path) {
2298
+ const item = record(value, resource, path);
2299
+ exact(
2300
+ item,
2301
+ [],
2302
+ ["width", "height", "mimeType", "filename", "url"],
2303
+ resource,
2304
+ path
2305
+ );
2306
+ optionalNullableNumber(item.width, resource, `${path}.width`);
2307
+ optionalNullableNumber(item.height, resource, `${path}.height`);
2308
+ for (const key of ["mimeType", "filename", "url"]) {
2309
+ if (item[key] !== void 0)
2310
+ nullableString(item[key], resource, `${path}.${key}`);
2311
+ }
2312
+ }
2313
+ function validateMedia(value, resource, path) {
2314
+ if (typeof value === "string") return;
2315
+ const media = record(value, resource, path);
2316
+ exact(
2317
+ media,
2318
+ [],
2319
+ ["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
2320
+ resource,
2321
+ path
2322
+ );
2323
+ if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
2324
+ fail(resource, `${path}.id`, "string, number, or null");
2325
+ }
2326
+ for (const key of ["alt", "mimeType", "filename", "url"]) {
2327
+ if (media[key] !== void 0)
2328
+ nullableString(media[key], resource, `${path}.${key}`);
2329
+ }
2330
+ optionalNullableNumber(media.width, resource, `${path}.width`);
2331
+ optionalNullableNumber(media.height, resource, `${path}.height`);
2332
+ if (media.sizes !== void 0) {
2333
+ const sizes = record(media.sizes, resource, `${path}.sizes`);
2334
+ Object.entries(sizes).forEach(
2335
+ ([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
2336
+ );
2337
+ }
2338
+ }
2339
+ function validateReference(value, resource, path) {
2340
+ const ref = record(value, resource, path);
2341
+ exact(ref, ["id", "title", "handle", "image"], [], resource, path);
2342
+ string(ref.id, resource, `${path}.id`);
2343
+ string(ref.title, resource, `${path}.title`);
2344
+ if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
2345
+ if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
2346
+ }
2347
+ function validateAdmission(value, resource, path) {
2348
+ const admission = record(value, resource, path);
2349
+ exact(
2350
+ admission,
2351
+ ["eventId", "occurrenceId", "admissionTypeId"],
2352
+ [],
2353
+ resource,
2354
+ path
2355
+ );
2356
+ string(admission.eventId, resource, `${path}.eventId`);
2357
+ string(admission.occurrenceId, resource, `${path}.occurrenceId`);
2358
+ string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
2359
+ }
2360
+ function compareAdmissions(left, right) {
2361
+ for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
2362
+ if (left[field] < right[field]) return -1;
2363
+ if (left[field] > right[field]) return 1;
2364
+ }
2365
+ return 0;
2366
+ }
2367
+ function validateAdmissions(value, resource, path) {
2368
+ const admissions = array(value, resource, path);
2369
+ if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
2370
+ let prior;
2371
+ admissions.forEach((admission, index) => {
2372
+ validateAdmission(admission, resource, `${path}[${index}]`);
2373
+ const item = admission;
2374
+ const comparison = prior ? compareAdmissions(item, prior) : void 0;
2375
+ if (comparison !== void 0 && comparison <= 0) {
2376
+ fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
2377
+ }
2378
+ prior = item;
2379
+ });
2380
+ }
2381
+ function validateAttributes(value, resource, path) {
2382
+ const attributes = array(value, resource, path);
2383
+ if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
2384
+ const keys = /* @__PURE__ */ new Set();
2385
+ attributes.forEach((value2, index) => {
2386
+ const itemPath = `${path}[${index}]`;
2387
+ const attribute = record(value2, resource, itemPath);
2388
+ exact(attribute, ["key", "value"], [], resource, itemPath);
2389
+ const key = string(attribute.key, resource, `${itemPath}.key`);
2390
+ if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
2391
+ fail(
2392
+ resource,
2393
+ `${itemPath}.key`,
2394
+ "unique, non-reserved key of at most 40 characters"
2395
+ );
2396
+ }
2397
+ keys.add(key);
2398
+ if (typeof attribute.value !== "string" || attribute.value.length > 500) {
2399
+ fail(resource, `${itemPath}.value`, "string of at most 500 characters");
2400
+ }
2401
+ });
2402
+ }
2403
+ function validateCustomer(value, resource, path) {
2404
+ const customer = record(value, resource, path);
2405
+ exact(customer, ["email"], ["name", "phone"], resource, path);
2406
+ const email = boundedString(
2407
+ customer.email,
2408
+ MAX_COMMERCE_EMAIL_LENGTH,
2409
+ resource,
2410
+ `${path}.email`
2411
+ );
2412
+ if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
2413
+ email
2414
+ )) {
2415
+ fail(resource, `${path}.email`, "email address");
2416
+ }
2417
+ if (customer.name !== void 0)
2418
+ boundedString(
2419
+ customer.name,
2420
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2421
+ resource,
2422
+ `${path}.name`
2423
+ );
2424
+ if (customer.phone !== void 0)
2425
+ boundedString(
2426
+ customer.phone,
2427
+ MAX_COMMERCE_PHONE_LENGTH,
2428
+ resource,
2429
+ `${path}.phone`
2430
+ );
2431
+ }
2432
+ function validateShippingAddress(value, resource, path) {
2433
+ const address = record(value, resource, path);
2434
+ exact(
2435
+ address,
2436
+ ["recipientName", "phone", "postalCode", "address", "detailAddress"],
2437
+ ["countryCode", "regionCode", "deliveryMessage"],
2438
+ resource,
2439
+ path
2440
+ );
2441
+ boundedString(
2442
+ address.recipientName,
2443
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2444
+ resource,
2445
+ `${path}.recipientName`
2446
+ );
2447
+ boundedString(
2448
+ address.phone,
2449
+ MAX_COMMERCE_PHONE_LENGTH,
2450
+ resource,
2451
+ `${path}.phone`
2452
+ );
2453
+ boundedString(
2454
+ address.postalCode,
2455
+ MAX_COMMERCE_POSTAL_CODE_LENGTH,
2456
+ resource,
2457
+ `${path}.postalCode`
2458
+ );
2459
+ for (const key of ["address", "detailAddress"]) {
2460
+ boundedString(
2461
+ address[key],
2462
+ MAX_COMMERCE_ADDRESS_LENGTH,
2463
+ resource,
2464
+ `${path}.${key}`
2465
+ );
2466
+ }
2467
+ if (address.countryCode !== void 0) {
2468
+ if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
2469
+ fail(resource, `${path}.countryCode`, "two-letter country code");
2470
+ }
2471
+ }
2472
+ if (address.regionCode !== void 0) {
2473
+ if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
2474
+ fail(
2475
+ resource,
2476
+ `${path}.regionCode`,
2477
+ "trimmed string of at most 64 characters"
2478
+ );
2479
+ }
2480
+ }
2481
+ if (address.deliveryMessage !== void 0) {
2482
+ boundedString(
2483
+ address.deliveryMessage,
2484
+ MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
2485
+ resource,
2486
+ `${path}.deliveryMessage`,
2487
+ true
2488
+ );
2489
+ }
2490
+ }
2491
+ function validateOrderReference(value, resource, path) {
2492
+ const order = record(value, resource, path);
2493
+ exact(order, ["id", "orderNumber"], [], resource, path);
2494
+ string(order.id, resource, `${path}.id`);
2495
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2496
+ }
2497
+ function validateIntegrationMetadata(value, resource, path) {
2498
+ const metadata = record(value, resource, path);
2499
+ if (Object.keys(metadata).length > 50)
2500
+ fail(resource, path, "at most 50 entries");
2501
+ Object.entries(metadata).forEach(([key, entry]) => {
2502
+ if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
2503
+ fail(resource, `${path}.${key}`, "valid metadata key");
2504
+ }
2505
+ if (typeof entry !== "string" || entry.length > 500) {
2506
+ fail(resource, `${path}.${key}`, "string of at most 500 characters");
2507
+ }
2508
+ });
2509
+ }
2510
+ function validateCartItem(value, resource, path) {
2511
+ const item = record(value, resource, path);
2512
+ exact(
2513
+ item,
2514
+ [
2515
+ "id",
2516
+ "product",
2517
+ "variant",
2518
+ "admissions",
2519
+ "quantity",
2520
+ "unitPriceMinor",
2521
+ "discountMinor",
2522
+ "estimatedLineTotalMinor",
2523
+ "requiresShipping"
2524
+ ],
2525
+ [],
2526
+ resource,
2527
+ path
2528
+ );
2529
+ string(item.id, resource, `${path}.id`);
2530
+ validateReference(item.product, resource, `${path}.product`);
2531
+ validateReference(item.variant, resource, `${path}.variant`);
2532
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2533
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2534
+ const unitPrice = safeMinor(
2535
+ item.unitPriceMinor,
2536
+ resource,
2537
+ `${path}.unitPriceMinor`
2538
+ );
2539
+ const discount = safeMinor(
2540
+ item.discountMinor,
2541
+ resource,
2542
+ `${path}.discountMinor`
2543
+ );
2544
+ const estimatedLineTotal = safeMinor(
2545
+ item.estimatedLineTotalMinor,
2546
+ resource,
2547
+ `${path}.estimatedLineTotalMinor`
2548
+ );
2549
+ const quantity = item.quantity;
2550
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2551
+ if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
2552
+ fail(
2553
+ resource,
2554
+ `${path}.estimatedLineTotalMinor`,
2555
+ "unitPriceMinor * quantity - discountMinor"
2556
+ );
2557
+ }
2558
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2559
+ }
2560
+ function validatePublicCart(value, resource = "Cart") {
2561
+ const cart = record(value, resource, "$");
2562
+ exact(
2563
+ cart,
2564
+ [
2565
+ "id",
2566
+ "status",
2567
+ "revision",
2568
+ "currency",
2569
+ "market",
2570
+ "subtotalMinor",
2571
+ "discountMinor",
2572
+ "estimatedTotalMinor",
2573
+ "discountCodes",
2574
+ "attributes",
2575
+ "items",
2576
+ "expiresAt",
2577
+ "createdAt",
2578
+ "updatedAt"
2579
+ ],
2580
+ [],
2581
+ resource,
2582
+ "$"
2583
+ );
2584
+ string(cart.id, resource, "$.id");
2585
+ enumValue(cart.status, CART_STATUSES, resource, "$.status");
2586
+ safeMinor(cart.revision, resource, "$.revision");
2587
+ currency(cart.currency, resource, "$.currency");
2588
+ const market = record(cart.market, resource, "$.market");
2589
+ exact(market, ["id", "handle", "name"], [], resource, "$.market");
2590
+ for (const key of ["id", "handle", "name"])
2591
+ string(market[key], resource, `$.market.${key}`);
2592
+ const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
2593
+ const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
2594
+ const estimatedTotal = safeMinor(
2595
+ cart.estimatedTotalMinor,
2596
+ resource,
2597
+ "$.estimatedTotalMinor"
2598
+ );
2599
+ array(cart.discountCodes, resource, "$.discountCodes").forEach(
2600
+ (value2, index) => {
2601
+ const itemPath = `$.discountCodes[${index}]`;
2602
+ const code = record(value2, resource, itemPath);
2603
+ exact(code, ["code", "applicable"], [], resource, itemPath);
2604
+ boundedString(
2605
+ code.code,
2606
+ MAX_CART_DISCOUNT_CODE_LENGTH,
2607
+ resource,
2608
+ `${itemPath}.code`
2609
+ );
2610
+ boolean(code.applicable, resource, `${itemPath}.applicable`);
2611
+ }
2612
+ );
2613
+ validateAttributes(cart.attributes, resource, "$.attributes");
2614
+ const items = array(cart.items, resource, "$.items");
2615
+ items.forEach(
2616
+ (item, index) => validateCartItem(item, resource, `$.items[${index}]`)
2617
+ );
2618
+ const expectedSubtotal = items.reduce((total, value2) => {
2619
+ const item = value2;
2620
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2621
+ }, 0n);
2622
+ const expectedDiscount = items.reduce((total, value2) => {
2623
+ const item = value2;
2624
+ return total + BigInt(item.discountMinor);
2625
+ }, 0n);
2626
+ if (BigInt(subtotal) !== expectedSubtotal) {
2627
+ fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
2628
+ }
2629
+ if (BigInt(discount) !== expectedDiscount) {
2630
+ fail(resource, "$.discountMinor", "sum of cart line discounts");
2631
+ }
2632
+ if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
2633
+ fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
2634
+ }
2635
+ timestamp(cart.expiresAt, resource, "$.expiresAt");
2636
+ timestamp(cart.createdAt, resource, "$.createdAt");
2637
+ timestamp(cart.updatedAt, resource, "$.updatedAt");
2638
+ return value;
2639
+ }
2640
+ function validateWarnings(value, resource, path) {
2641
+ array(value, resource, path).forEach((value2, index) => {
2642
+ const itemPath = `${path}[${index}]`;
2643
+ const warning = record(value2, resource, itemPath);
2644
+ exact(warning, ["code", "message", "target"], [], resource, itemPath);
2645
+ enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
2646
+ string(warning.message, resource, `${itemPath}.message`);
2647
+ string(warning.target, resource, `${itemPath}.target`);
2648
+ });
2649
+ }
2650
+ function validateCartMutationResult(value) {
2651
+ const result = record(value, "Cart mutation result", "$");
2652
+ exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
2653
+ validatePublicCart(result.cart);
2654
+ validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
2655
+ return value;
2656
+ }
2657
+ function validateCreateCartResult(value) {
2658
+ const result = record(value, "Cart create result", "$");
2659
+ exact(
2660
+ result,
2661
+ ["cart", "warnings", "cartToken"],
2662
+ [],
2663
+ "Cart create result",
2664
+ "$"
2665
+ );
2666
+ const cart = record(result.cart, "Cart create result", "$.cart");
2667
+ validatePublicCart(cart);
2668
+ if (cart.revision !== 0) {
2669
+ fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
2670
+ }
2671
+ validateWarnings(result.warnings, "Cart create result", "$.warnings");
2672
+ boundedString(
2673
+ result.cartToken,
2674
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2675
+ "Cart create result",
2676
+ "$.cartToken"
2677
+ );
2678
+ return value;
2679
+ }
2680
+ function validateCartMineResult(value) {
2681
+ const result = record(value, "Cart mine result", "$");
2682
+ exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
2683
+ if (result.cart === null || result.cartToken === null) {
2684
+ if (result.cart !== null || result.cartToken !== null) {
2685
+ fail("Cart mine result", "$", "cart and cartToken must both be null");
2686
+ }
2687
+ } else {
2688
+ validatePublicCart(result.cart);
2689
+ boundedString(
2690
+ result.cartToken,
2691
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2692
+ "Cart mine result",
2693
+ "$.cartToken"
2694
+ );
2695
+ }
2696
+ return value;
2697
+ }
2698
+ function validateCartMergeResult(value) {
2699
+ const result = record(value, "Cart merge result", "$");
2700
+ exact(
2701
+ result,
2702
+ ["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
2703
+ [],
2704
+ "Cart merge result",
2705
+ "$"
2706
+ );
2707
+ validatePublicCart(result.cart);
2708
+ validateWarnings(result.warnings, "Cart merge result", "$.warnings");
2709
+ boundedString(
2710
+ result.cartToken,
2711
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2712
+ "Cart merge result",
2713
+ "$.cartToken"
2714
+ );
2715
+ const resolution = enumValue(
2716
+ result.resolution,
2717
+ ["unchanged", "claimed", "merged"],
2718
+ "Cart merge result",
2719
+ "$.resolution"
2720
+ );
2721
+ boolean(result.merged, "Cart merge result", "$.merged");
2722
+ boolean(result.claimed, "Cart merge result", "$.claimed");
2723
+ const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
2724
+ if (result.merged !== expected[0] || result.claimed !== expected[1]) {
2725
+ fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
2726
+ }
2727
+ return value;
2728
+ }
2729
+ function validateCheckoutItem(value, resource, path) {
2730
+ const item = record(value, resource, path);
2731
+ exact(
2732
+ item,
2733
+ [
2734
+ "id",
2735
+ "product",
2736
+ "variant",
2737
+ "productTitle",
2738
+ "variantTitle",
2739
+ "sku",
2740
+ "admissions",
2741
+ "quantity",
2742
+ "unitPriceMinor",
2743
+ "discountMinor",
2744
+ "lineTotalMinor",
2745
+ "requiresShipping"
2746
+ ],
2747
+ [],
2748
+ resource,
2749
+ path
2750
+ );
2751
+ string(item.id, resource, `${path}.id`);
2752
+ validateReference(item.product, resource, `${path}.product`);
2753
+ validateReference(item.variant, resource, `${path}.variant`);
2754
+ string(item.productTitle, resource, `${path}.productTitle`);
2755
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2756
+ nullableString(item.sku, resource, `${path}.sku`);
2757
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2758
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2759
+ const unitPrice = safeMinor(
2760
+ item.unitPriceMinor,
2761
+ resource,
2762
+ `${path}.unitPriceMinor`
2763
+ );
2764
+ const discount = safeMinor(
2765
+ item.discountMinor,
2766
+ resource,
2767
+ `${path}.discountMinor`
2768
+ );
2769
+ const lineTotal = safeMinor(
2770
+ item.lineTotalMinor,
2771
+ resource,
2772
+ `${path}.lineTotalMinor`
2773
+ );
2774
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
2775
+ if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
2776
+ fail(
2777
+ resource,
2778
+ `${path}.lineTotalMinor`,
2779
+ "unitPriceMinor * quantity - discountMinor"
2780
+ );
2781
+ }
2782
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2783
+ }
2784
+ function validateCheckoutAmounts(value, resource, path) {
2785
+ const amounts = record(value, resource, path);
2786
+ exact(
2787
+ amounts,
2788
+ [
2789
+ "currency",
2790
+ "subtotalMinor",
2791
+ "shippingMinor",
2792
+ "discountMinor",
2793
+ "totalMinor"
2794
+ ],
2795
+ [],
2796
+ resource,
2797
+ path
2798
+ );
2799
+ currency(amounts.currency, resource, `${path}.currency`);
2800
+ const subtotal = safeMinor(
2801
+ amounts.subtotalMinor,
2802
+ resource,
2803
+ `${path}.subtotalMinor`
2804
+ );
2805
+ const shipping = safeMinor(
2806
+ amounts.shippingMinor,
2807
+ resource,
2808
+ `${path}.shippingMinor`
2809
+ );
2810
+ const discount = safeMinor(
2811
+ amounts.discountMinor,
2812
+ resource,
2813
+ `${path}.discountMinor`
2814
+ );
2815
+ const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
2816
+ if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
2817
+ fail(
2818
+ resource,
2819
+ `${path}.totalMinor`,
2820
+ "subtotalMinor + shippingMinor - discountMinor"
2821
+ );
2822
+ }
2823
+ }
2824
+ function validatePaymentSessionReference(value, resource, path) {
2825
+ const session = record(value, resource, path);
2826
+ exact(session, ["id", "provider", "providerStatus"], [], resource, path);
2827
+ string(session.id, resource, `${path}.id`);
2828
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
2829
+ enumValue(
2830
+ session.providerStatus,
2831
+ PAYMENT_PROVIDER_STATUSES,
2832
+ resource,
2833
+ `${path}.providerStatus`
2834
+ );
2835
+ }
2836
+ function checkoutVariantKeys(status, placedVia) {
2837
+ const base = [
2838
+ "id",
2839
+ "amounts",
2840
+ "items",
2841
+ "customerSnapshot",
2842
+ "shippingAddress",
2843
+ "attributes",
2844
+ "expiresAt",
2845
+ "createdAt",
2846
+ "updatedAt",
2847
+ "status",
2848
+ "paymentState",
2849
+ "order"
2850
+ ];
2851
+ if (status === "open") return { required: base, optional: [] };
2852
+ if (status === "abandoned") {
2853
+ return {
2854
+ required: [...base, "abandonedAt", "abandonedReason"],
2855
+ optional: []
2856
+ };
2857
+ }
2858
+ return placedVia === "late_capture" ? {
2859
+ required: [
2860
+ ...base,
2861
+ "placedAt",
2862
+ "placedVia",
2863
+ "abandonedAt",
2864
+ "abandonedReason"
2865
+ ],
2866
+ optional: []
2867
+ } : { required: [...base, "placedAt"], optional: [] };
2868
+ }
2869
+ function validateCheckoutCore(value, resource, list, server) {
2870
+ const checkout = record(value, resource, "$");
2871
+ const status = enumValue(
2872
+ checkout.status,
2873
+ CHECKOUT_STATUSES,
2874
+ resource,
2875
+ "$.status"
2876
+ );
2877
+ const keys = checkoutVariantKeys(status, checkout.placedVia);
2878
+ if (list) {
2879
+ keys.required = keys.required.filter(
2880
+ (key) => !["items", "shippingAddress", "attributes"].includes(key)
2881
+ );
2882
+ keys.required.push("clientReferenceId");
2883
+ } else if (server) {
2884
+ keys.required.push("clientReferenceId", "integrationMetadata");
2885
+ }
2886
+ exact(checkout, keys.required, keys.optional, resource, "$");
2887
+ string(checkout.id, resource, "$.id");
2888
+ validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
2889
+ if (!list) {
2890
+ const items = array(checkout.items, resource, "$.items");
2891
+ if (items.length === 0) fail(resource, "$.items", "non-empty array");
2892
+ items.forEach(
2893
+ (item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
2894
+ );
2895
+ const expectedSubtotal = items.reduce((total, value2) => {
2896
+ const item = value2;
2897
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2898
+ }, 0n);
2899
+ const expectedDiscount = items.reduce((total, value2) => {
2900
+ const item = value2;
2901
+ return total + BigInt(item.discountMinor);
2902
+ }, 0n);
2903
+ const amounts = checkout.amounts;
2904
+ if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
2905
+ fail(
2906
+ resource,
2907
+ "$.amounts.subtotalMinor",
2908
+ "sum of undiscounted checkout line totals"
2909
+ );
2910
+ }
2911
+ if (BigInt(amounts.discountMinor) !== expectedDiscount) {
2912
+ fail(
2913
+ resource,
2914
+ "$.amounts.discountMinor",
2915
+ "sum of checkout line discounts"
2916
+ );
2917
+ }
2918
+ if (checkout.shippingAddress !== null) {
2919
+ validateShippingAddress(
2920
+ checkout.shippingAddress,
2921
+ resource,
2922
+ "$.shippingAddress"
2923
+ );
2924
+ }
2925
+ validateAttributes(checkout.attributes, resource, "$.attributes");
2926
+ }
2927
+ validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
2928
+ timestamp(checkout.expiresAt, resource, "$.expiresAt");
2929
+ timestamp(checkout.createdAt, resource, "$.createdAt");
2930
+ timestamp(checkout.updatedAt, resource, "$.updatedAt");
2931
+ const paymentState = record(checkout.paymentState, resource, "$.paymentState");
2932
+ exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
2933
+ if (status === "open") {
2934
+ if (paymentState.activePaymentSession !== null) {
2935
+ validatePaymentSessionReference(
2936
+ paymentState.activePaymentSession,
2937
+ resource,
2938
+ "$.paymentState.activePaymentSession"
2939
+ );
2940
+ }
2941
+ if (checkout.order !== null)
2942
+ fail(resource, "$.order", "null for open Checkout");
2943
+ } else {
2944
+ if (paymentState.activePaymentSession !== null) {
2945
+ fail(
2946
+ resource,
2947
+ "$.paymentState.activePaymentSession",
2948
+ "null for spent Checkout"
2949
+ );
2950
+ }
2951
+ if (status === "placed") {
2952
+ timestamp(checkout.placedAt, resource, "$.placedAt");
2953
+ validateOrderReference(checkout.order, resource, "$.order");
2954
+ if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
2955
+ fail(resource, "$.placedVia", "late_capture");
2956
+ }
2957
+ if (checkout.placedVia === "late_capture") {
2958
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2959
+ enumValue(
2960
+ checkout.abandonedReason,
2961
+ ABANDONED_REASONS,
2962
+ resource,
2963
+ "$.abandonedReason"
2964
+ );
2965
+ }
2966
+ } else {
2967
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2968
+ enumValue(
2969
+ checkout.abandonedReason,
2970
+ ABANDONED_REASONS,
2971
+ resource,
2972
+ "$.abandonedReason"
2973
+ );
2974
+ if (checkout.order !== null)
2975
+ fail(resource, "$.order", "null for abandoned Checkout");
2976
+ }
2977
+ }
2978
+ if (list || server) {
2979
+ if (checkout.clientReferenceId !== null) {
2980
+ boundedString(
2981
+ checkout.clientReferenceId,
2982
+ MAX_COMMERCE_RESOURCE_ID_LENGTH,
2983
+ resource,
2984
+ "$.clientReferenceId"
2985
+ );
2986
+ }
2987
+ }
2988
+ if (server)
2989
+ validateIntegrationMetadata(
2990
+ checkout.integrationMetadata,
2991
+ resource,
2992
+ "$.integrationMetadata"
2993
+ );
2994
+ }
2995
+ function validatePublicCheckout(value) {
2996
+ validateCheckoutCore(value, "Checkout", false, false);
2997
+ return value;
2998
+ }
2999
+ function validateServerCheckout(value) {
3000
+ validateCheckoutCore(value, "Server Checkout", false, true);
3001
+ return value;
3002
+ }
3003
+ function validateCreateCheckoutResult(value, server) {
3004
+ const resource = server ? "Server Checkout create result" : "Checkout create result";
3005
+ const result = record(value, resource, "$");
3006
+ exact(result, ["checkout", "checkoutToken"], [], resource, "$");
3007
+ if (server) validateServerCheckout(result.checkout);
3008
+ else validatePublicCheckout(result.checkout);
3009
+ boundedString(
3010
+ result.checkoutToken,
3011
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3012
+ resource,
3013
+ "$.checkoutToken"
3014
+ );
3015
+ return value;
3016
+ }
3017
+ function validateCheckoutQueryResult(value) {
3018
+ const result = record(value, "Checkout query result", "$");
3019
+ exact(
3020
+ result,
3021
+ ["data", "hasMore", "nextCursor"],
3022
+ [],
3023
+ "Checkout query result",
3024
+ "$"
3025
+ );
3026
+ array(result.data, "Checkout query result", "$.data").forEach(
3027
+ (item) => validateCheckoutCore(item, "Checkout list item", true, false)
3028
+ );
3029
+ boolean(result.hasMore, "Checkout query result", "$.hasMore");
3030
+ if (result.nextCursor !== null)
3031
+ boundedString(
3032
+ result.nextCursor,
3033
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3034
+ "Checkout query result",
3035
+ "$.nextCursor"
3036
+ );
3037
+ if (result.hasMore === true && result.nextCursor === null) {
3038
+ fail(
3039
+ "Checkout query result",
3040
+ "$.nextCursor",
3041
+ "non-null when hasMore is true"
3042
+ );
3043
+ }
3044
+ return value;
3045
+ }
3046
+ function validateMoney(value, resource, path) {
3047
+ const money = record(value, resource, path);
3048
+ exact(money, ["amountMinor", "currency"], [], resource, path);
3049
+ safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3050
+ currency(money.currency, resource, `${path}.currency`);
3051
+ }
3052
+ function validateCustomPaymentSession(value) {
3053
+ const resource = "custom PaymentSession";
3054
+ const session = record(value, resource, "$");
3055
+ exact(
3056
+ session,
3057
+ ["id", "provider", "providerSessionId", "money"],
3058
+ [],
3059
+ resource,
3060
+ "$"
3061
+ );
3062
+ string(session.id, resource, "$.id");
3063
+ const provider = string(session.provider, resource, "$.provider");
3064
+ if (!/^[a-z0-9][a-z0-9_-]{0,63}$/i.test(provider)) {
3065
+ fail(resource, "$.provider", "provider slug");
3066
+ }
3067
+ string(session.providerSessionId, resource, "$.providerSessionId");
3068
+ validateMoney(session.money, resource, "$.money");
3069
+ return value;
3070
+ }
3071
+ function validateConfirmCustomPaymentSessionResponse(value) {
3072
+ const resource = "custom PaymentSession confirmation";
3073
+ const result = record(value, resource, "$");
3074
+ exact(
3075
+ result,
3076
+ ["orderId", "transactionId", "status"],
3077
+ ["alreadyConfirmed"],
3078
+ resource,
3079
+ "$"
3080
+ );
3081
+ string(result.orderId, resource, "$.orderId");
3082
+ string(result.transactionId, resource, "$.transactionId");
3083
+ if (result.status !== "paid") fail(resource, "$.status", "paid");
3084
+ if (result.alreadyConfirmed !== void 0) {
3085
+ boolean(result.alreadyConfirmed, resource, "$.alreadyConfirmed");
3086
+ }
3087
+ return value;
3088
+ }
3089
+ function validateCaptureEvidence(value, resource, path) {
3090
+ const evidence = record(value, resource, path);
3091
+ exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
3092
+ safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
3093
+ currency(evidence.currency, resource, `${path}.currency`);
3094
+ timestamp(evidence.observedAt, resource, `${path}.observedAt`);
3095
+ }
3096
+ function validateNoReconciliation(value, resource, path) {
3097
+ const reconciliation = record(value, resource, path);
3098
+ exact(reconciliation, ["status"], [], resource, path);
3099
+ if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
3100
+ }
3101
+ function validateRequiredReconciliation(value, allowed, resource, path) {
3102
+ const reconciliation = record(value, resource, path);
3103
+ exact(reconciliation, ["status", "reasons"], [], resource, path);
3104
+ if (reconciliation.status !== "required")
3105
+ fail(resource, `${path}.status`, "required");
3106
+ const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
3107
+ if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
3108
+ let previous = -1;
3109
+ reasons.forEach((reason, index) => {
3110
+ const current = allowed.indexOf(reason);
3111
+ if (current < 0 || current <= previous) {
3112
+ fail(
3113
+ resource,
3114
+ `${path}.reasons[${index}]`,
3115
+ "unique canonical-sorted reconciliation reason"
3116
+ );
3117
+ }
3118
+ previous = current;
3119
+ });
3120
+ }
3121
+ function validateNextAction(value, resource, path) {
3122
+ const action = record(value, resource, path);
3123
+ exact(
3124
+ action,
3125
+ [
3126
+ "type",
3127
+ "clientKey",
3128
+ "paymentMethodVariantKey",
3129
+ "agreementVariantKey",
3130
+ "providerOrderId",
3131
+ "providerCustomerKey",
3132
+ "orderName"
3133
+ ],
3134
+ ["customerName", "customerEmail"],
3135
+ resource,
3136
+ path
3137
+ );
3138
+ if (action.type !== "toss_widget")
3139
+ fail(resource, `${path}.type`, "toss_widget");
3140
+ for (const key of [
3141
+ "clientKey",
3142
+ "paymentMethodVariantKey",
3143
+ "agreementVariantKey"
3144
+ ]) {
3145
+ boundedString(action[key], 255, resource, `${path}.${key}`);
3146
+ }
3147
+ string(action.providerOrderId, resource, `${path}.providerOrderId`);
3148
+ string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
3149
+ boundedString(
3150
+ action.orderName,
3151
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3152
+ resource,
3153
+ `${path}.orderName`
3154
+ );
3155
+ if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
3156
+ fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
3157
+ }
3158
+ 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(
3159
+ action.providerCustomerKey
3160
+ )) {
3161
+ fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
3162
+ }
3163
+ if (action.customerName !== void 0)
3164
+ boundedString(
3165
+ action.customerName,
3166
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3167
+ resource,
3168
+ `${path}.customerName`
3169
+ );
3170
+ if (action.customerEmail !== void 0)
3171
+ validateCustomer({ email: action.customerEmail }, resource, path);
3172
+ }
3173
+ function validatePublicPaymentSession(value) {
3174
+ const resource = "PaymentSession";
3175
+ const session = record(value, resource, "$");
3176
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
3177
+ const status = enumValue(
3178
+ session.providerStatus,
3179
+ PAYMENT_PROVIDER_STATUSES,
3180
+ resource,
3181
+ "$.providerStatus"
3182
+ );
3183
+ const common = [
3184
+ "id",
3185
+ "money",
3186
+ "expiresAt",
3187
+ "sessionRole",
3188
+ "provider",
3189
+ "providerStatus",
3190
+ "presentationStatus",
3191
+ "finalizationStatus",
3192
+ "reconciliation",
3193
+ "order"
3194
+ ];
3195
+ const optional = [];
3196
+ if (status === "requires_payment_method" || status === "requires_action")
3197
+ optional.push("nextAction");
3198
+ else if (status === "captured") common.push("providerEvidence");
3199
+ else if (status === "failed") common.push("failure");
3200
+ else if (status === "canceled") common.push("cancellationReason");
3201
+ exact(session, common, optional, resource, "$");
3202
+ string(session.id, resource, "$.id");
3203
+ validateMoney(session.money, resource, "$.money");
3204
+ if (session.expiresAt !== null)
3205
+ timestamp(session.expiresAt, resource, "$.expiresAt");
3206
+ if (status === "requires_payment_method" || status === "requires_action") {
3207
+ if (session.sessionRole === "active") {
3208
+ if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
3209
+ fail(resource, "$", "actionable active not-ready state");
3210
+ }
3211
+ if (!("nextAction" in session))
3212
+ fail(resource, "$.nextAction", "required field");
3213
+ validateNextAction(session.nextAction, resource, "$.nextAction");
3214
+ } else if (session.sessionRole === "residual") {
3215
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3216
+ fail(resource, "$", "suppressed residual not-ready state");
3217
+ }
3218
+ if ("nextAction" in session)
3219
+ fail(resource, "$.nextAction", "absent for suppressed state");
3220
+ } else fail(resource, "$.sessionRole", "active | residual");
3221
+ validateNoReconciliation(
3222
+ session.reconciliation,
3223
+ resource,
3224
+ "$.reconciliation"
3225
+ );
3226
+ if (session.order !== null) fail(resource, "$.order", "null");
3227
+ } else if ([
3228
+ "requires_confirmation",
3229
+ "initializing",
3230
+ "processing",
3231
+ "authorized",
3232
+ "canceling"
3233
+ ].includes(status)) {
3234
+ enumValue(
3235
+ session.sessionRole,
3236
+ ["active", "residual"],
3237
+ resource,
3238
+ "$.sessionRole"
3239
+ );
3240
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3241
+ fail(resource, "$", "suppressed not-ready state");
3242
+ }
3243
+ validateNoReconciliation(
3244
+ session.reconciliation,
3245
+ resource,
3246
+ "$.reconciliation"
3247
+ );
3248
+ if (session.order !== null) fail(resource, "$.order", "null");
3249
+ } else if (status === "unknown") {
3250
+ enumValue(
3251
+ session.sessionRole,
3252
+ ["active", "residual"],
3253
+ resource,
3254
+ "$.sessionRole"
3255
+ );
3256
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3257
+ fail(resource, "$", "suppressed not-ready state");
3258
+ }
3259
+ validateRequiredReconciliation(
3260
+ session.reconciliation,
3261
+ ["provider_outcome_unknown"],
3262
+ resource,
3263
+ "$.reconciliation"
3264
+ );
3265
+ if (session.order !== null) fail(resource, "$.order", "null");
3266
+ } else if (status === "captured") {
3267
+ validateCaptureEvidence(
3268
+ session.providerEvidence,
3269
+ resource,
3270
+ "$.providerEvidence"
3271
+ );
3272
+ if (session.presentationStatus !== "suppressed")
3273
+ fail(resource, "$.presentationStatus", "suppressed");
3274
+ if (session.finalizationStatus === "pending") {
3275
+ enumValue(
3276
+ session.sessionRole,
3277
+ ["canonical_candidate", "residual"],
3278
+ resource,
3279
+ "$.sessionRole"
3280
+ );
3281
+ if (session.order !== null)
3282
+ fail(resource, "$.order", "null for pending finalization");
3283
+ const reconciliation = record(
3284
+ session.reconciliation,
3285
+ resource,
3286
+ "$.reconciliation"
3287
+ );
3288
+ if (reconciliation.status === "none")
3289
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3290
+ else
3291
+ validateRequiredReconciliation(
3292
+ reconciliation,
3293
+ [
3294
+ "local_commit_ambiguous",
3295
+ "amount_mismatch",
3296
+ "currency_mismatch",
3297
+ "excess_capture_pending_order"
3298
+ ],
3299
+ resource,
3300
+ "$.reconciliation"
3301
+ );
3302
+ } else if (session.finalizationStatus === "committed") {
3303
+ validateOrderReference(session.order, resource, "$.order");
3304
+ const reconciliation = record(
3305
+ session.reconciliation,
3306
+ resource,
3307
+ "$.reconciliation"
3308
+ );
3309
+ if (reconciliation.status === "none") {
3310
+ enumValue(
3311
+ session.sessionRole,
3312
+ ["canonical", "historical"],
3313
+ resource,
3314
+ "$.sessionRole"
3315
+ );
3316
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3317
+ } else {
3318
+ enumValue(
3319
+ session.sessionRole,
3320
+ ["canonical", "residual"],
3321
+ resource,
3322
+ "$.sessionRole"
3323
+ );
3324
+ validateRequiredReconciliation(
3325
+ reconciliation,
3326
+ [
3327
+ "inventory_unavailable",
3328
+ "admission_unavailable",
3329
+ "amount_mismatch",
3330
+ "currency_mismatch",
3331
+ "excess_capture",
3332
+ "late_capture",
3333
+ "cross_checkout_duplicate"
3334
+ ],
3335
+ resource,
3336
+ "$.reconciliation"
3337
+ );
3338
+ }
3339
+ } else fail(resource, "$.finalizationStatus", "pending | committed");
3340
+ } else if (status === "failed") {
3341
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3342
+ fail(resource, "$", "historical suppressed failed state");
3343
+ }
3344
+ validateNoReconciliation(
3345
+ session.reconciliation,
3346
+ resource,
3347
+ "$.reconciliation"
1649
3348
  );
1650
- this.secretKey = options.secretKey;
1651
- this.apiUrl = options.apiUrl;
1652
- this.onRequestId = options.onRequestId;
1653
- }
1654
- async request(endpoint, body, options) {
1655
- const method = options?.method ?? "POST";
1656
- try {
1657
- const response = await httpFetch(endpoint, {
1658
- method,
1659
- apiUrl: this.apiUrl,
1660
- publishableKey: this.publishableKey,
1661
- secretKey: this.secretKey,
1662
- ...body !== void 0 && { body: JSON.stringify(body) },
1663
- ...options?.headers && { headers: options.headers }
1664
- });
1665
- this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1666
- return parseApiResponse(response, endpoint);
1667
- } catch (err) {
1668
- const id = err instanceof SDKError ? err.requestId ?? null : null;
1669
- this.onRequestId?.(id);
1670
- throw err;
3349
+ const failure = record(session.failure, resource, "$.failure");
3350
+ exact(failure, ["reason"], ["message"], resource, "$.failure");
3351
+ enumValue(
3352
+ failure.reason,
3353
+ PAYMENT_FAILURE_REASONS,
3354
+ resource,
3355
+ "$.failure.reason"
3356
+ );
3357
+ if (failure.message !== void 0)
3358
+ string(failure.message, resource, "$.failure.message");
3359
+ } else {
3360
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3361
+ fail(resource, "$", "historical suppressed canceled state");
1671
3362
  }
1672
- }
1673
- };
1674
-
1675
- // src/core/community/moderation-api.ts
1676
- var ModerationApi = class extends BaseApi {
1677
- constructor(options) {
1678
- super("ModerationApi", options);
1679
- }
1680
- banCustomer(params) {
1681
- return this.request(
1682
- "/api/community-bans/ban-bearer",
1683
- params,
1684
- { method: "POST" }
3363
+ validateNoReconciliation(
3364
+ session.reconciliation,
3365
+ resource,
3366
+ "$.reconciliation"
1685
3367
  );
1686
- }
1687
- unbanCustomer(params) {
1688
- return this.request(
1689
- "/api/community-bans/unban-bearer",
1690
- params,
1691
- { method: "POST" }
3368
+ enumValue(
3369
+ session.cancellationReason,
3370
+ ["expired", "customer", "operator", "provider"],
3371
+ resource,
3372
+ "$.cancellationReason"
1692
3373
  );
1693
3374
  }
1694
- };
3375
+ return value;
3376
+ }
3377
+
3378
+ // src/core/api/commerce-idempotency.ts
3379
+ 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;
3380
+ var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
3381
+ function isCommerceIdempotencyKey(value) {
3382
+ return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
3383
+ }
3384
+ function assertCommerceIdempotencyKey(value) {
3385
+ if (isCommerceIdempotencyKey(value)) return;
3386
+ throw createValidationError(
3387
+ "idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
3388
+ { field: "idempotencyKey" }
3389
+ );
3390
+ }
1695
3391
 
1696
3392
  // src/core/api/cart-api.ts
1697
3393
  var CartApi = class extends CustomerScopedApi {
1698
3394
  constructor(options) {
1699
3395
  super("CartApi", { ...options, requiresCredential: false });
3396
+ this.serverTransport = Boolean(options.secretKey);
1700
3397
  }
1701
- async execute(endpoint, method, body) {
1702
- return this.request(endpoint, { method, body });
3398
+ endpoint(key) {
3399
+ return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
1703
3400
  }
1704
- /**
1705
- * Create a cart and receive its `cartToken`. Store the token and pass it to
1706
- * every subsequent cart operation.
1707
- */
1708
- createCart(params = {}) {
1709
- return this.execute("/api/carts/create", "POST", params);
3401
+ execute(endpoint2, body, idempotencyKey) {
3402
+ return this.requestEndpoint(endpoint2, body, {
3403
+ ...idempotencyKey && {
3404
+ headers: { "X-Idempotency-Key": idempotencyKey }
3405
+ }
3406
+ });
1710
3407
  }
1711
- getCart(cartToken) {
1712
- return this.execute("/api/carts/get", "POST", { cartToken });
3408
+ create(params = {}) {
3409
+ return this.execute(this.endpoint("create"), params).then(
3410
+ (value) => validateCreateCartResult(value)
3411
+ );
1713
3412
  }
1714
- merge(params) {
1715
- return this.execute(
1716
- COMMERCE_ENDPOINTS.carts.merge,
1717
- "POST",
1718
- params
3413
+ retrieve(params) {
3414
+ return this.execute(this.endpoint("retrieve"), params).then(
3415
+ (value) => validatePublicCart(value)
1719
3416
  );
1720
3417
  }
1721
- /**
1722
- * Resolve the authenticated customer's active cart by JWT (no `cartToken`
1723
- * required). Returns the cart and its capability handle, or both `null` when
1724
- * the customer has no active cart. Requires a customer token.
1725
- */
1726
- mine() {
1727
- return this.execute(
1728
- COMMERCE_ENDPOINTS.carts.mine,
1729
- "POST",
1730
- {}
3418
+ mine(params = {}) {
3419
+ const endpoint2 = this.endpoint("mine");
3420
+ return this.execute(endpoint2, params).then(
3421
+ (value) => validateCartMineResult(value)
3422
+ );
3423
+ }
3424
+ merge(params) {
3425
+ const { idempotencyKey, ...body } = params;
3426
+ assertCommerceIdempotencyKey(idempotencyKey);
3427
+ const endpoint2 = this.endpoint("merge");
3428
+ return this.execute(endpoint2, body, idempotencyKey).then(
3429
+ (value) => validateCartMergeResult(value)
1731
3430
  );
1732
3431
  }
1733
3432
  addItem(params) {
1734
- return this.execute(
1735
- COMMERCE_ENDPOINTS.carts.addItem,
1736
- "POST",
1737
- params
3433
+ return this.mutate(this.endpoint("addItem"), params);
3434
+ }
3435
+ mutate(endpoint2, params) {
3436
+ const { idempotencyKey, ...body } = params;
3437
+ assertCommerceIdempotencyKey(idempotencyKey);
3438
+ return this.execute(endpoint2, body, idempotencyKey).then(
3439
+ (value) => validateCartMutationResult(value)
1738
3440
  );
1739
3441
  }
1740
3442
  updateItem(params) {
1741
- return this.execute(
1742
- COMMERCE_ENDPOINTS.carts.updateItem,
1743
- "POST",
1744
- params
1745
- );
3443
+ return this.mutate(this.endpoint("updateItem"), params);
1746
3444
  }
1747
3445
  removeItem(params) {
1748
- return this.execute(
1749
- COMMERCE_ENDPOINTS.carts.removeItem,
1750
- "POST",
1751
- params
1752
- );
3446
+ return this.mutate(this.endpoint("removeItem"), params);
1753
3447
  }
1754
- applyDiscount(params) {
1755
- return this.execute(
1756
- COMMERCE_ENDPOINTS.carts.applyDiscount,
1757
- "POST",
1758
- params
1759
- );
3448
+ clear(params) {
3449
+ return this.mutate(this.endpoint("clear"), params);
1760
3450
  }
1761
- removeDiscount(params) {
1762
- return this.execute(
1763
- COMMERCE_ENDPOINTS.carts.removeDiscount,
1764
- "POST",
1765
- params
1766
- );
3451
+ updateDiscountCodes(params) {
3452
+ return this.mutate(this.endpoint("updateDiscountCodes"), params);
1767
3453
  }
1768
- clearCart(params) {
1769
- return this.execute(
1770
- COMMERCE_ENDPOINTS.carts.clear,
1771
- "POST",
1772
- params
1773
- );
3454
+ updateAttributes(params) {
3455
+ return this.mutate(this.endpoint("updateAttributes"), params);
1774
3456
  }
1775
3457
  };
1776
3458
 
@@ -2577,6 +4259,9 @@ function compareVariantOrder(a, b) {
2577
4259
  }
2578
4260
  function getVariantAvailableForSale(variant) {
2579
4261
  if (variant.isActive === false) return false;
4262
+ if (typeof variant.availableForSale === "boolean") {
4263
+ return variant.availableForSale;
4264
+ }
2580
4265
  if (variant.isUnlimited) return true;
2581
4266
  if (variant.inventoryPolicy === "continue") return true;
2582
4267
  return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
@@ -2686,7 +4371,7 @@ function buildProductListingCard(item, options = {}) {
2686
4371
  { listing: { selectionHintVariant } },
2687
4372
  options
2688
4373
  ),
2689
- title: product.title,
4374
+ title: product.title ?? "",
2690
4375
  representativeVariant,
2691
4376
  primaryImage: listingPrimaryMedia,
2692
4377
  priceRange,
@@ -2814,6 +4499,11 @@ function productDetailResultFromError(error) {
2814
4499
  if (!reason) return void 0;
2815
4500
  return { found: false, reason };
2816
4501
  }
4502
+ var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
4503
+ var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
4504
+ "priceRange.minVariantPrice.amount",
4505
+ "priceRange.maxVariantPrice.amount"
4506
+ ]);
2817
4507
  function nonEmpty(values) {
2818
4508
  return values?.length ? values : void 0;
2819
4509
  }
@@ -2861,14 +4551,34 @@ function buildProductListingPageWhere(params) {
2861
4551
  if (clauses.length === 1) return clauses[0];
2862
4552
  return { and: clauses };
2863
4553
  }
2864
- function buildProductListingPageUrl(params) {
4554
+ function productListingPageUsesBasePriceSort(sort) {
4555
+ const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
4556
+ return values.some(
4557
+ (value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
4558
+ );
4559
+ }
4560
+ function assertMarketListingPageQuerySupported(params) {
4561
+ if (!params.market?.trim()) return;
4562
+ const priceFilter = params.filters?.price;
4563
+ if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
4564
+ throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
4565
+ }
4566
+ }
4567
+ function buildProductListingPageRequest(params) {
4568
+ assertMarketListingPageQuerySupported(params);
2865
4569
  const options = {
4570
+ market: params.market,
4571
+ locale: params.locale,
4572
+ fallbackLocale: params.fallbackLocale,
2866
4573
  page: params.page,
2867
4574
  limit: params.limit,
2868
4575
  sort: params.sort,
2869
4576
  where: buildProductListingPageWhere(params)
2870
4577
  };
2871
- return params.mode === "full" ? listingGroupsQueryUrl(options) : listingGroupsQueryCatalogUrl(options);
4578
+ return {
4579
+ operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
4580
+ query: listingPageSearchParams(options)
4581
+ };
2872
4582
  }
2873
4583
  function withProductListingCards(response, options) {
2874
4584
  return {
@@ -2917,38 +4627,40 @@ var ProductApi = class extends BaseApi {
2917
4627
  * to remain available by the time an order is placed.
2918
4628
  */
2919
4629
  stockCheck(params) {
2920
- return this.request(
2921
- COMMERCE_ENDPOINTS.products.stockCheck,
4630
+ return this.requestEndpoint(
4631
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
2922
4632
  params
2923
4633
  );
2924
4634
  }
2925
4635
  stockSnapshot(params) {
2926
- return this.request(
2927
- stockSnapshotQuery(params),
4636
+ return this.requestEndpoint(
4637
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
2928
4638
  void 0,
2929
- { method: "GET" }
4639
+ { query: stockSnapshotSearchParams(params) }
2930
4640
  );
2931
4641
  }
2932
4642
  listingGroups(params) {
2933
- return this.request(
2934
- listingGroupsQuery(params),
4643
+ return this.requestEndpoint(
4644
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups,
2935
4645
  void 0,
2936
- { method: "GET" }
4646
+ { query: listingGroupsSearchParams(params) }
2937
4647
  );
2938
4648
  }
2939
4649
  listingGroupsCatalog(params) {
2940
- return this.request(
2941
- listingGroupsCatalogQuery(params),
4650
+ return this.requestEndpoint(
4651
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
2942
4652
  void 0,
2943
- { method: "GET" }
4653
+ { query: listingGroupsSearchParams(params) }
2944
4654
  );
2945
4655
  }
2946
4656
  async listingPage(params = {}) {
2947
4657
  if (params.mode === "full") {
2948
- const response2 = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4658
+ const request2 = buildProductListingPageRequest(params);
4659
+ const response2 = await this.requestEndpoint(request2.operation, void 0, { query: request2.query });
2949
4660
  return withProductListingCards(response2, params);
2950
4661
  }
2951
- const response = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4662
+ const request = buildProductListingPageRequest(params);
4663
+ const response = await this.requestEndpoint(request.operation, void 0, { query: request.query });
2952
4664
  return withProductListingCards(response, params);
2953
4665
  }
2954
4666
  /**
@@ -2963,10 +4675,10 @@ var ProductApi = class extends BaseApi {
2963
4675
  */
2964
4676
  async detail(params) {
2965
4677
  try {
2966
- const product = await this.request(
2967
- productDetailQuery(params),
4678
+ const product = await this.requestEndpoint(
4679
+ COMMERCE_ENDPOINT_OPERATIONS.products.detail,
2968
4680
  void 0,
2969
- { method: "GET" }
4681
+ { query: productDetailSearchParams(params) }
2970
4682
  );
2971
4683
  return { found: true, product };
2972
4684
  } catch (err) {
@@ -2977,10 +4689,10 @@ var ProductApi = class extends BaseApi {
2977
4689
  }
2978
4690
  async detailCatalog(params) {
2979
4691
  try {
2980
- const product = await this.request(
2981
- productDetailCatalogQuery(params),
4692
+ const product = await this.requestEndpoint(
4693
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
2982
4694
  void 0,
2983
- { method: "GET" }
4695
+ { query: productDetailSearchParams(params) }
2984
4696
  );
2985
4697
  return { found: true, product };
2986
4698
  } catch (err) {
@@ -2996,8 +4708,8 @@ var ProductApi = class extends BaseApi {
2996
4708
  * `product-upsert` tool.
2997
4709
  */
2998
4710
  upsert(params) {
2999
- return this.request(
3000
- COMMERCE_ENDPOINTS.products.upsert,
4711
+ return this.requestEndpoint(
4712
+ COMMERCE_ENDPOINT_OPERATIONS.products.upsert,
3001
4713
  normalizeProductUpsertParams(params)
3002
4714
  );
3003
4715
  }
@@ -3009,7 +4721,10 @@ var DiscountApi = class extends BaseApi {
3009
4721
  super("DiscountApi", options);
3010
4722
  }
3011
4723
  validate(params) {
3012
- return this.request("/api/discounts/validate", params);
4724
+ return this.requestEndpoint(
4725
+ COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
4726
+ params
4727
+ );
3013
4728
  }
3014
4729
  };
3015
4730
 
@@ -3019,7 +4734,10 @@ var ShippingApi = class extends BaseApi {
3019
4734
  super("ShippingApi", options);
3020
4735
  }
3021
4736
  calculate(params) {
3022
- return this.request("/api/shipping-policies/calculate", params);
4737
+ return this.requestEndpoint(
4738
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
4739
+ params
4740
+ );
3023
4741
  }
3024
4742
  };
3025
4743
 
@@ -3031,44 +4749,12 @@ function splitIdempotencyKey(params) {
3031
4749
  const { idempotencyKey, ...body } = params;
3032
4750
  return { body, idempotencyKey };
3033
4751
  }
3034
- function normalizeCreateOrderBody(params) {
3035
- if (params.items !== void 0) {
3036
- const { idempotencyKey: _idempotencyKey2, items, ...rest } = params;
3037
- return { ...rest, orderItems: items };
3038
- }
3039
- const { idempotencyKey: _idempotencyKey, ...body } = params;
3040
- return body;
3041
- }
3042
4752
  var OrderApi = class extends BaseApi {
3043
4753
  constructor(options) {
3044
4754
  super("OrderApi", options);
3045
4755
  }
3046
- createOrder(params) {
3047
- const { idempotencyKey } = params;
3048
- const normalizedBody = normalizeCreateOrderBody(params);
3049
- return this.request(
3050
- COMMERCE_ENDPOINTS.orders.create,
3051
- normalizedBody,
3052
- idempotencyRequestOptions(idempotencyKey)
3053
- );
3054
- }
3055
4756
  updateOrder(params) {
3056
- return this.request(COMMERCE_ENDPOINTS.orders.update, params);
3057
- }
3058
- updateTransaction(params) {
3059
- return this.request(
3060
- COMMERCE_ENDPOINTS.transactions.update,
3061
- params
3062
- );
3063
- }
3064
- confirmPayment(params) {
3065
- const { body, idempotencyKey } = splitIdempotencyKey(params);
3066
- const headerKey = idempotencyKey ?? params.providerEventId;
3067
- return this.request(
3068
- COMMERCE_ENDPOINTS.orders.confirmPayment,
3069
- body,
3070
- idempotencyRequestOptions(headerKey)
3071
- );
4757
+ return this.requestEndpoint(COMMERCE_ENDPOINTS.orders.update, params);
3072
4758
  }
3073
4759
  /**
3074
4760
  * Resolve an order + its payment transaction by PG payment id. Replaces raw
@@ -3080,28 +4766,12 @@ var OrderApi = class extends BaseApi {
3080
4766
  pgProvider: params.pgProvider,
3081
4767
  pgPaymentId: params.pgPaymentId
3082
4768
  }).toString();
3083
- return this.request(
3084
- `${COMMERCE_ENDPOINTS.orders.byPayment}?${query}`,
4769
+ return this.requestEndpoint(
4770
+ COMMERCE_ENDPOINTS.orders.byPayment,
3085
4771
  void 0,
3086
- { method: "GET" }
4772
+ { query }
3087
4773
  );
3088
4774
  }
3089
- /**
3090
- * Composed facade: confirm a provider payment, then resolve the
3091
- * depth-populated order/transaction by the same payment id. `confirmPayment`'s
3092
- * wire response carries only IDs (its contract is `.strict()`); this returns
3093
- * the populated `Order` so storefronts stop reconstructing order state
3094
- * locally. Two round trips by design — the alternative (widening the strict
3095
- * confirm-payment wire contract to embed a full Order) is rejected.
3096
- */
3097
- async confirmPaymentReturningOrder(params) {
3098
- const confirmation = await this.confirmPayment(params);
3099
- const { order, transaction } = await this.getByPaymentId({
3100
- pgProvider: params.pgProvider,
3101
- pgPaymentId: params.pgPaymentId
3102
- });
3103
- return { ...confirmation, order, transaction };
3104
- }
3105
4775
  cancelOrder(params) {
3106
4776
  const { idempotencyKey } = params;
3107
4777
  const body = {
@@ -3109,14 +4779,14 @@ var OrderApi = class extends BaseApi {
3109
4779
  reasonCode: params.reasonCode,
3110
4780
  reasonDetail: params.reasonDetail
3111
4781
  };
3112
- return this.request(
4782
+ return this.requestEndpoint(
3113
4783
  COMMERCE_ENDPOINTS.orders.cancel,
3114
4784
  body,
3115
4785
  idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0
3116
4786
  );
3117
4787
  }
3118
4788
  resolveCancelRefund(params) {
3119
- return this.request(
4789
+ return this.requestEndpoint(
3120
4790
  COMMERCE_ENDPOINTS.orders.resolveCancelRefund,
3121
4791
  {
3122
4792
  orderNumber: params.orderNumber,
@@ -3129,49 +4799,35 @@ var OrderApi = class extends BaseApi {
3129
4799
  idempotencyRequestOptions(params.idempotencyKey)
3130
4800
  );
3131
4801
  }
3132
- /**
3133
- * Returns a `PublicOrder`-compatible shape even when the server backs the
3134
- * response with a Checkout (checkout/order separation, #1285). `orderNumber`
3135
- * stays the stable cross-window key. A breaking `PublicCheckout` split is a
3136
- * deferred follow-up (design D10 / Q3-b); do not change this return type here.
3137
- */
3138
- checkout(params) {
3139
- const { body, idempotencyKey } = splitIdempotencyKey(params);
3140
- return this.request(
3141
- COMMERCE_ENDPOINTS.orders.checkout,
3142
- body,
3143
- idempotencyRequestOptions(idempotencyKey)
3144
- );
3145
- }
3146
4802
  createFulfillment(params) {
3147
4803
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3148
- return this.request(
4804
+ return this.requestEndpoint(
3149
4805
  COMMERCE_ENDPOINTS.orders.createFulfillment,
3150
4806
  body,
3151
4807
  idempotencyRequestOptions(idempotencyKey)
3152
4808
  );
3153
4809
  }
3154
4810
  prepareFulfillmentOrder(params) {
3155
- return this.request(
4811
+ return this.requestEndpoint(
3156
4812
  COMMERCE_ENDPOINTS.fulfillmentOrders.prepare,
3157
4813
  params
3158
4814
  );
3159
4815
  }
3160
4816
  updateFulfillment(params) {
3161
- return this.request(
4817
+ return this.requestEndpoint(
3162
4818
  COMMERCE_ENDPOINTS.orders.updateFulfillment,
3163
4819
  params
3164
4820
  );
3165
4821
  }
3166
4822
  bulkImportFulfillments(params) {
3167
- return this.request(
4823
+ return this.requestEndpoint(
3168
4824
  COMMERCE_ENDPOINTS.fulfillments.bulkImport,
3169
4825
  params
3170
4826
  );
3171
4827
  }
3172
4828
  returnWithRefund(params) {
3173
4829
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3174
- return this.request(
4830
+ return this.requestEndpoint(
3175
4831
  COMMERCE_ENDPOINTS.returns.returnRefund,
3176
4832
  body,
3177
4833
  idempotencyRequestOptions(idempotencyKey)
@@ -3179,19 +4835,182 @@ var OrderApi = class extends BaseApi {
3179
4835
  }
3180
4836
  createReturn(params) {
3181
4837
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3182
- return this.request(
4838
+ return this.requestEndpoint(
3183
4839
  COMMERCE_ENDPOINTS.returns.create,
3184
4840
  body,
3185
4841
  idempotencyRequestOptions(idempotencyKey)
3186
4842
  );
3187
4843
  }
3188
4844
  updateReturn(params) {
3189
- return this.request(COMMERCE_ENDPOINTS.returns.update, params);
4845
+ return this.requestEndpoint(
4846
+ COMMERCE_ENDPOINTS.returns.update,
4847
+ params
4848
+ );
4849
+ }
4850
+ };
4851
+
4852
+ // src/core/api/checkout-api.ts
4853
+ var CheckoutApi = class extends CustomerScopedApi {
4854
+ constructor(options) {
4855
+ super("CheckoutApi", { ...options, requiresCredential: false });
4856
+ }
4857
+ post(endpoint2, body, idempotencyKey) {
4858
+ return this.requestEndpoint(endpoint2, body, {
4859
+ ...idempotencyKey && {
4860
+ headers: { "X-Idempotency-Key": idempotencyKey }
4861
+ }
4862
+ });
4863
+ }
4864
+ async publicCheckout(result) {
4865
+ return validatePublicCheckout(await result);
4866
+ }
4867
+ async serverCheckout(result) {
4868
+ return validateServerCheckout(await result);
4869
+ }
4870
+ async createResult(result) {
4871
+ return validateCreateCheckoutResult(
4872
+ await result,
4873
+ false
4874
+ );
4875
+ }
4876
+ async createServerResult(result) {
4877
+ return validateCreateCheckoutResult(
4878
+ await result,
4879
+ true
4880
+ );
4881
+ }
4882
+ create(params) {
4883
+ const { idempotencyKey, ...body } = params;
4884
+ assertCommerceIdempotencyKey(idempotencyKey);
4885
+ return this.createResult(
4886
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
4887
+ );
4888
+ }
4889
+ createServer(params) {
4890
+ const { idempotencyKey, ...body } = params;
4891
+ assertCommerceIdempotencyKey(idempotencyKey);
4892
+ return this.createServerResult(
4893
+ this.post(
4894
+ COMMERCE_ENDPOINTS.checkouts.server.create,
4895
+ body,
4896
+ idempotencyKey
4897
+ )
4898
+ );
4899
+ }
4900
+ retrieve(params) {
4901
+ return this.publicCheckout(
4902
+ this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
4903
+ );
4904
+ }
4905
+ retrieveServer(params) {
4906
+ return this.serverCheckout(
4907
+ this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
4908
+ );
4909
+ }
4910
+ async query(params = {}) {
4911
+ const result = await this.post(
4912
+ COMMERCE_ENDPOINTS.checkouts.server.query,
4913
+ params
4914
+ );
4915
+ return validateCheckoutQueryResult(result);
4916
+ }
4917
+ };
4918
+
4919
+ // src/core/api/payment-session-api.ts
4920
+ var PaymentSessionApi = class extends CustomerScopedApi {
4921
+ constructor(options) {
4922
+ super("PaymentSessionApi", { ...options, requiresCredential: false });
4923
+ this.serverTransport = Boolean(options.secretKey);
4924
+ }
4925
+ post(endpoint2, body, idempotencyKey) {
4926
+ return this.requestEndpoint(endpoint2, body, {
4927
+ ...idempotencyKey && {
4928
+ headers: { "X-Idempotency-Key": idempotencyKey }
4929
+ }
4930
+ });
4931
+ }
4932
+ async paymentSession(result) {
4933
+ return validatePublicPaymentSession(await result);
4934
+ }
4935
+ create(params) {
4936
+ const { idempotencyKey, ...body } = params;
4937
+ assertCommerceIdempotencyKey(idempotencyKey);
4938
+ return this.paymentSession(
4939
+ this.post(
4940
+ this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
4941
+ body,
4942
+ idempotencyKey
4943
+ )
4944
+ );
4945
+ }
4946
+ retrieve(params) {
4947
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4948
+ return this.paymentSession(this.post(endpoint2, params));
4949
+ }
4950
+ cancel(params) {
4951
+ const { idempotencyKey, ...body } = params;
4952
+ assertCommerceIdempotencyKey(idempotencyKey);
4953
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4954
+ return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
4955
+ }
4956
+ confirm(params) {
4957
+ const { idempotencyKey, ...body } = params;
4958
+ assertCommerceIdempotencyKey(idempotencyKey);
4959
+ return this.paymentSession(
4960
+ this.post(
4961
+ COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
4962
+ body,
4963
+ idempotencyKey
4964
+ )
4965
+ );
4966
+ }
4967
+ };
4968
+ var CustomPaymentSessionApi = class extends BaseApi {
4969
+ constructor(options) {
4970
+ super("CustomPaymentSessionApi", options);
4971
+ }
4972
+ async create(params) {
4973
+ assertCommerceIdempotencyKey(params.idempotencyKey);
4974
+ const body = {
4975
+ provider: params.provider,
4976
+ checkoutToken: params.checkoutToken
4977
+ };
4978
+ const result = await this.requestEndpoint(
4979
+ COMMERCE_ENDPOINTS.paymentSessions.custom.create,
4980
+ body,
4981
+ { headers: { "X-Idempotency-Key": params.idempotencyKey } }
4982
+ );
4983
+ return validateCustomPaymentSession(result);
4984
+ }
4985
+ async confirm(params, options = {}) {
4986
+ const body = {
4987
+ provider: params.provider,
4988
+ providerSessionId: params.providerSessionId,
4989
+ providerPaymentId: params.providerPaymentId,
4990
+ providerEventId: params.providerEventId,
4991
+ amount: params.amount,
4992
+ currency: params.currency,
4993
+ occurredAt: params.occurredAt
4994
+ };
4995
+ const proof = await options.createProof?.(JSON.stringify(body));
4996
+ const result = await this.requestEndpoint(
4997
+ COMMERCE_ENDPOINTS.paymentSessions.custom.confirm,
4998
+ body,
4999
+ proof ? {
5000
+ headers: {
5001
+ "X-Custom-Payment-Timestamp": proof.timestamp,
5002
+ "X-Custom-Payment-Signature": proof.signature
5003
+ }
5004
+ } : void 0
5005
+ );
5006
+ return validateConfirmCustomPaymentSessionResponse(
5007
+ result
5008
+ );
3190
5009
  }
3191
5010
  };
3192
5011
 
3193
5012
  // src/core/preview/server-preview-client.ts
3194
- var ServerPreviewClient = class extends BaseApi {
5013
+ var ServerPreviewClient = class extends RawBaseApi {
3195
5014
  constructor(options) {
3196
5015
  super("ServerPreviewClient", options);
3197
5016
  }
@@ -3247,6 +5066,7 @@ var PreviewProductApi = class extends ProductApi {
3247
5066
  };
3248
5067
  var ServerCommerceClient = class {
3249
5068
  constructor(options) {
5069
+ this.market = options.market;
3250
5070
  const publishableKey = requirePublishableKeyForSecret(
3251
5071
  "ServerCommerceClient",
3252
5072
  options.publishableKey,
@@ -3263,33 +5083,34 @@ var ServerCommerceClient = class {
3263
5083
  const discountApi = new DiscountApi(serverOptions);
3264
5084
  const shippingApi = new ShippingApi(serverOptions);
3265
5085
  const orderApi = new OrderApi(serverOptions);
5086
+ const checkoutApi = new CheckoutApi(serverOptions);
5087
+ const paymentSessionApi = new PaymentSessionApi(serverOptions);
5088
+ const customPaymentSessionApi = new CustomPaymentSessionApi(serverOptions);
3266
5089
  this.product = {
3267
5090
  stockCheck: productApi.stockCheck.bind(productApi),
3268
- listingGroups: productApi.listingGroups.bind(productApi),
3269
- listingPage: productApi.listingPage.bind(productApi),
3270
- detail: productApi.detail.bind(productApi),
5091
+ listingGroups: (params) => productApi.listingGroups(this.withMarket(params)),
5092
+ listingPage: ((params = {}) => productApi.listingPage(
5093
+ this.withMarket(params)
5094
+ )),
5095
+ detail: (params) => productApi.detail(this.withMarket(params)),
5096
+ detailCatalog: (params) => productApi.detailCatalog(this.withMarket(params)),
3271
5097
  previewDetail: productApi.previewDetail.bind(productApi),
3272
5098
  upsert: productApi.upsert.bind(productApi)
3273
5099
  };
3274
- this.cart = {
3275
- create: cartApi.createCart.bind(cartApi),
3276
- get: cartApi.getCart.bind(cartApi),
5100
+ this.carts = {
5101
+ create: (params) => cartApi.create(this.withMarket(params ?? {})),
5102
+ retrieve: cartApi.retrieve.bind(cartApi),
3277
5103
  addItem: cartApi.addItem.bind(cartApi),
3278
5104
  updateItem: cartApi.updateItem.bind(cartApi),
3279
5105
  removeItem: cartApi.removeItem.bind(cartApi),
3280
- applyDiscount: cartApi.applyDiscount.bind(cartApi),
3281
- removeDiscount: cartApi.removeDiscount.bind(cartApi),
3282
- clear: cartApi.clearCart.bind(cartApi),
3283
- merge: cartApi.merge.bind(cartApi),
3284
- mine: cartApi.mine.bind(cartApi)
5106
+ updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
5107
+ updateAttributes: cartApi.updateAttributes.bind(cartApi),
5108
+ clear: cartApi.clear.bind(cartApi),
5109
+ merge: (params) => cartApi.merge(params),
5110
+ mine: (params) => cartApi.mine(params)
3285
5111
  };
3286
5112
  this.orders = {
3287
- checkout: orderApi.checkout.bind(orderApi),
3288
- create: orderApi.createOrder.bind(orderApi),
3289
5113
  update: orderApi.updateOrder.bind(orderApi),
3290
- updateTransaction: orderApi.updateTransaction.bind(orderApi),
3291
- confirmPayment: orderApi.confirmPayment.bind(orderApi),
3292
- confirmPaymentReturningOrder: orderApi.confirmPaymentReturningOrder.bind(orderApi),
3293
5114
  getByPaymentId: orderApi.getByPaymentId.bind(orderApi),
3294
5115
  cancelOrder: orderApi.cancelOrder.bind(orderApi),
3295
5116
  resolveCancelRefund: orderApi.resolveCancelRefund.bind(orderApi),
@@ -3301,6 +5122,21 @@ var ServerCommerceClient = class {
3301
5122
  updateReturn: orderApi.updateReturn.bind(orderApi),
3302
5123
  returnWithRefund: orderApi.returnWithRefund.bind(orderApi)
3303
5124
  };
5125
+ this.checkouts = {
5126
+ create: checkoutApi.createServer.bind(checkoutApi),
5127
+ retrieve: checkoutApi.retrieveServer.bind(checkoutApi),
5128
+ query: checkoutApi.query.bind(checkoutApi)
5129
+ };
5130
+ this.paymentSessions = {
5131
+ create: paymentSessionApi.create.bind(paymentSessionApi),
5132
+ retrieve: (params) => paymentSessionApi.retrieve(params),
5133
+ cancel: (params) => paymentSessionApi.cancel(params),
5134
+ confirm: paymentSessionApi.confirm.bind(paymentSessionApi),
5135
+ custom: {
5136
+ create: customPaymentSessionApi.create.bind(customPaymentSessionApi),
5137
+ confirm: customPaymentSessionApi.confirm.bind(customPaymentSessionApi)
5138
+ }
5139
+ };
3304
5140
  this.discounts = {
3305
5141
  validate: discountApi.validate.bind(discountApi)
3306
5142
  };
@@ -3308,6 +5144,14 @@ var ServerCommerceClient = class {
3308
5144
  calculate: shippingApi.calculate.bind(shippingApi)
3309
5145
  };
3310
5146
  }
5147
+ getDefaultMarket() {
5148
+ return this.market;
5149
+ }
5150
+ withMarket(params) {
5151
+ const defaultMarket = this.market?.trim();
5152
+ if (!defaultMarket || params.market?.trim()) return params;
5153
+ return { ...params, market: defaultMarket };
5154
+ }
3311
5155
  };
3312
5156
 
3313
5157
  // src/core/events/events-client.ts
@@ -3327,7 +5171,17 @@ var EventsClient = class {
3327
5171
  getRange(params) {
3328
5172
  return this.execute(
3329
5173
  buildRangeEndpoint(params),
3330
- "GET",
5174
+ resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
5175
+ void 0,
5176
+ { useCustomerAuth: false }
5177
+ );
5178
+ }
5179
+ getAdmissionAvailability(params) {
5180
+ return this.execute(
5181
+ buildAdmissionAvailabilityEndpoint(params),
5182
+ resolveOperationMethod(
5183
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
5184
+ ),
3331
5185
  void 0,
3332
5186
  { useCustomerAuth: false }
3333
5187
  );
@@ -3356,11 +5210,11 @@ var EventsClient = class {
3356
5210
  { useCustomerAuth: false }
3357
5211
  );
3358
5212
  }
3359
- async execute(endpoint, method, body, options = {}) {
5213
+ async execute(endpoint2, method, body, options = {}) {
3360
5214
  const useCustomerAuth = options.useCustomerAuth === true;
3361
5215
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
3362
5216
  try {
3363
- const response = await httpFetch(endpoint, {
5217
+ const response = await httpFetch(endpoint2, {
3364
5218
  method,
3365
5219
  apiUrl: this.apiUrl,
3366
5220
  publishableKey: this.publishableKey,
@@ -3369,7 +5223,7 @@ var EventsClient = class {
3369
5223
  ...body !== void 0 && { body: JSON.stringify(body) }
3370
5224
  });
3371
5225
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
3372
- return parseApiResponse(response, endpoint);
5226
+ return parseApiResponse(response, endpoint2);
3373
5227
  } catch (err) {
3374
5228
  const id = err instanceof SDKError ? err.requestId ?? null : null;
3375
5229
  this.onRequestId?.(id);
@@ -3408,7 +5262,17 @@ function buildRangeEndpoint(params) {
3408
5262
  appendValues(urlParams, "categorySlug", params.categorySlug);
3409
5263
  appendValues(urlParams, "tag", params.tag);
3410
5264
  appendValues(urlParams, "tagSlug", params.tagSlug);
3411
- return `/api/event-occurrences/range?${urlParams.toString()}`;
5265
+ return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
5266
+ query: urlParams
5267
+ });
5268
+ }
5269
+ function buildAdmissionAvailabilityEndpoint(params) {
5270
+ const urlParams = new URLSearchParams();
5271
+ urlParams.set("occurrence", params.occurrence);
5272
+ return resolveOperationPath(
5273
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
5274
+ { query: urlParams }
5275
+ );
3412
5276
  }
3413
5277
  function formatDateParam(value) {
3414
5278
  return value instanceof Date ? value.toISOString() : value;
@@ -3421,11 +5285,56 @@ function appendValues(params, key, value) {
3421
5285
  }
3422
5286
  }
3423
5287
 
5288
+ // src/core/market/market-discovery.ts
5289
+ function toMarketDTO(row) {
5290
+ return {
5291
+ id: row.id,
5292
+ handle: row.handle,
5293
+ name: row.name,
5294
+ countryCode: row.countryCode,
5295
+ targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
5296
+ currency: row.currency,
5297
+ isPrimary: row.isPrimary === true,
5298
+ isActive: row.isActive === true
5299
+ };
5300
+ }
5301
+ var MarketDiscovery = class {
5302
+ constructor(read) {
5303
+ this.read = read;
5304
+ }
5305
+ async list() {
5306
+ const res = await this.read({
5307
+ where: { isActive: { equals: true } },
5308
+ limit: 100
5309
+ });
5310
+ if (res.hasNextPage) {
5311
+ console.warn(
5312
+ "[markets.list] more than 100 active markets; results truncated to 100."
5313
+ );
5314
+ }
5315
+ return res.docs.map(toMarketDTO);
5316
+ }
5317
+ async default() {
5318
+ const res = await this.read({
5319
+ where: { isPrimary: { equals: true }, isActive: { equals: true } },
5320
+ limit: 1
5321
+ });
5322
+ const row = res.docs[0];
5323
+ return row ? toMarketDTO(row) : null;
5324
+ }
5325
+ };
5326
+
3424
5327
  // src/core/api/tenant-introspection-api.ts
3425
- var TenantIntrospectionApi = class extends BaseApi {
5328
+ var TenantIntrospectionApi = class extends RawBaseApi {
3426
5329
  constructor(options) {
3427
5330
  super("TenantIntrospectionApi", options);
3428
5331
  }
5332
+ context(params = {}) {
5333
+ const endpoint2 = params.includeCounts ? "/api/tenants/context?counts=true" : "/api/tenants/context";
5334
+ return this.request(endpoint2, void 0, {
5335
+ method: "GET"
5336
+ });
5337
+ }
3429
5338
  collectionSchema(collection) {
3430
5339
  return this.request(
3431
5340
  `/api/tenants/schema/${encodeURIComponent(collection)}`,
@@ -3459,40 +5368,30 @@ var MembershipApi = class extends BaseApi {
3459
5368
  */
3460
5369
  subscribe(params) {
3461
5370
  const { subscribeIntentKey, ...body } = params;
3462
- return this.request(
3463
- MEMBERSHIP_ENDPOINTS.subscribe,
5371
+ return this.requestEndpoint(
5372
+ MEMBERSHIP_ENDPOINT_OPERATIONS.subscribe,
3464
5373
  body,
3465
5374
  idempotencyRequestOptions(subscribeIntentKey)
3466
5375
  );
3467
5376
  }
3468
5377
  /**
3469
5378
  * Cancel a membership by id.
3470
- * `immediate=false` (default) sets `cancelAtPeriodEnd`; the customer retains
3471
- * benefits until `currentPeriodEnd`. `immediate=true` cancels now and revokes
3472
- * membership groups immediately.
5379
+ * By default this sets `cancelAtPeriodEnd`, keeps benefits until
5380
+ * `currentPeriodEnd`, and stops renewal. Pass `immediate=true` to cancel
5381
+ * immediately and revoke membership groups now.
3473
5382
  */
3474
5383
  cancel(params) {
3475
5384
  const { id, immediate } = params;
3476
- return this.request(
3477
- MEMBERSHIP_ENDPOINTS.cancel(id),
3478
- immediate !== void 0 ? { immediate } : {}
3479
- );
3480
- }
3481
- /**
3482
- * Retrieve the authenticated customer's own membership view.
3483
- * Never returns payment tokens or internal keys.
3484
- */
3485
- me() {
3486
- return this.request(
3487
- MEMBERSHIP_ENDPOINTS.me,
3488
- void 0,
3489
- { method: "GET" }
5385
+ return this.requestEndpoint(
5386
+ MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
5387
+ immediate !== void 0 ? { immediate } : {},
5388
+ { pathParams: { id } }
3490
5389
  );
3491
5390
  }
3492
5391
  };
3493
5392
 
3494
5393
  // src/core/client/client.server.ts
3495
- var ServerClient = class {
5394
+ var ServerClient = class _ServerClient {
3496
5395
  constructor(options) {
3497
5396
  this.lastRequestId = null;
3498
5397
  if (typeof window !== "undefined") {
@@ -3521,17 +5420,18 @@ var ServerClient = class {
3521
5420
  publishableKey: this.config.publishableKey,
3522
5421
  secretKey: this.config.secretKey,
3523
5422
  apiUrl: this.config.apiUrl,
5423
+ market: this.config.market,
3524
5424
  onRequestId
3525
5425
  };
3526
5426
  this.commerce = new ServerCommerceClient(serverOptions);
3527
5427
  const membershipApi = new MembershipApi(serverOptions);
3528
5428
  this.memberships = {
3529
5429
  subscribe: membershipApi.subscribe.bind(membershipApi),
3530
- cancel: membershipApi.cancel.bind(membershipApi),
3531
- me: membershipApi.me.bind(membershipApi)
5430
+ cancel: membershipApi.cancel.bind(membershipApi)
3532
5431
  };
3533
5432
  const tenantIntrospectionApi = new TenantIntrospectionApi(serverOptions);
3534
5433
  this.tenant = {
5434
+ context: tenantIntrospectionApi.context.bind(tenantIntrospectionApi),
3535
5435
  collectionSchema: tenantIntrospectionApi.collectionSchema.bind(
3536
5436
  tenantIntrospectionApi
3537
5437
  ),
@@ -3559,6 +5459,9 @@ var ServerClient = class {
3559
5459
  onRequestId,
3560
5460
  this.config.apiUrl
3561
5461
  );
5462
+ this.markets = new MarketDiscovery(
5463
+ (options2) => this.collections.from("markets").find(options2)
5464
+ );
3562
5465
  }
3563
5466
  get events() {
3564
5467
  if (!this._events) {
@@ -3580,6 +5483,9 @@ var ServerClient = class {
3580
5483
  getState() {
3581
5484
  return { ...this.state };
3582
5485
  }
5486
+ withMarket(market) {
5487
+ return new _ServerClient({ ...this.config, market });
5488
+ }
3583
5489
  getConfig() {
3584
5490
  const { secretKey: _, ...safeConfig } = this.config;
3585
5491
  return safeConfig;