@01.software/sdk 0.44.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +358 -2
  2. package/MIGRATION.md +89 -10
  3. package/README.md +441 -98
  4. package/dist/{server-nXOezi4b.d.cts → catalog-mappers-sIshKNb3.d.cts} +14 -3
  5. package/dist/{server-nXOezi4b.d.ts → catalog-mappers-sIshKNb3.d.ts} +14 -3
  6. package/dist/client.cjs +2680 -345
  7. package/dist/client.cjs.map +1 -1
  8. package/dist/client.d.cts +10 -7
  9. package/dist/client.d.ts +10 -7
  10. package/dist/client.js +2680 -345
  11. package/dist/client.js.map +1 -1
  12. package/dist/{collection-client-Dyl-CDcj.d.cts → collection-client-BSo7VXQE.d.cts} +8 -5
  13. package/dist/{collection-client-DWooaiTr.d.ts → collection-client-Ckfusuee.d.ts} +8 -5
  14. package/dist/{const-pGDnsy0o.d.ts → const-BAG0MH0u.d.cts} +13 -10
  15. package/dist/{const-1vleZ6ov.d.cts → const-CaPq2AE4.d.ts} +13 -10
  16. package/dist/errors.cjs +74 -1
  17. package/dist/errors.cjs.map +1 -1
  18. package/dist/errors.d.cts +38 -1
  19. package/dist/errors.d.ts +38 -1
  20. package/dist/errors.js +74 -1
  21. package/dist/errors.js.map +1 -1
  22. package/dist/{index-DUNySyxV.d.ts → index-BNICJxBL.d.ts} +4 -4
  23. package/dist/{index-a6g7vqAD.d.cts → index-YGrZrxNn.d.cts} +4 -4
  24. package/dist/index.cjs +2741 -368
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +18 -19
  27. package/dist/index.d.ts +18 -19
  28. package/dist/index.js +2741 -368
  29. package/dist/index.js.map +1 -1
  30. package/dist/{payload-types-CDsuOEfM.d.cts → payload-types-CJZuXcgF.d.cts} +6671 -4001
  31. package/dist/{payload-types-CDsuOEfM.d.ts → payload-types-CJZuXcgF.d.ts} +6671 -4001
  32. package/dist/query.cjs +550 -101
  33. package/dist/query.cjs.map +1 -1
  34. package/dist/query.d.cts +43 -45
  35. package/dist/query.d.ts +43 -45
  36. package/dist/query.js +550 -101
  37. package/dist/query.js.map +1 -1
  38. package/dist/realtime.cjs.map +1 -1
  39. package/dist/realtime.d.cts +2 -2
  40. package/dist/realtime.d.ts +2 -2
  41. package/dist/realtime.js.map +1 -1
  42. package/dist/server.cjs +2252 -444
  43. package/dist/server.cjs.map +1 -1
  44. package/dist/server.d.cts +11 -10
  45. package/dist/server.d.ts +11 -10
  46. package/dist/server.js +2252 -444
  47. package/dist/server.js.map +1 -1
  48. package/dist/storefront-cache.cjs +65 -1
  49. package/dist/storefront-cache.cjs.map +1 -1
  50. package/dist/storefront-cache.js +65 -1
  51. package/dist/storefront-cache.js.map +1 -1
  52. package/dist/types-BC6rVmJa.d.ts +47 -0
  53. package/dist/{types-CDND3hzq.d.cts → types-BlOvjoTX.d.ts} +1095 -509
  54. package/dist/{types-Dt9FJisi.d.ts → types-C4WuJfw7.d.cts} +1095 -509
  55. package/dist/types-D5p7-m1l.d.cts +47 -0
  56. package/dist/ui/canvas/server.cjs +244 -2
  57. package/dist/ui/canvas/server.cjs.map +1 -1
  58. package/dist/ui/canvas/server.d.cts +27 -1
  59. package/dist/ui/canvas/server.d.ts +27 -1
  60. package/dist/ui/canvas/server.js +244 -2
  61. package/dist/ui/canvas/server.js.map +1 -1
  62. package/dist/ui/canvas.cjs +419 -103
  63. package/dist/ui/canvas.cjs.map +1 -1
  64. package/dist/ui/canvas.d.cts +19 -7
  65. package/dist/ui/canvas.d.ts +19 -7
  66. package/dist/ui/canvas.js +419 -103
  67. package/dist/ui/canvas.js.map +1 -1
  68. package/dist/ui/form.d.cts +1 -1
  69. package/dist/ui/form.d.ts +1 -1
  70. package/dist/ui/video.d.cts +1 -1
  71. package/dist/ui/video.d.ts +1 -1
  72. package/dist/webhook.cjs +2 -1
  73. package/dist/webhook.cjs.map +1 -1
  74. package/dist/webhook.d.cts +4 -4
  75. package/dist/webhook.d.ts +4 -4
  76. package/dist/webhook.js +2 -1
  77. package/dist/webhook.js.map +1 -1
  78. package/package.json +12 -11
  79. package/dist/types-SoXsbKhj.d.cts +0 -33
  80. package/dist/types-oiae_LMm.d.ts +0 -33
package/dist/server.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;
@@ -339,116 +466,129 @@ function attachRequestId(err, id) {
339
466
  }
340
467
  function parseRetryAfter(response) {
341
468
  const raw = response.headers.get("Retry-After");
342
- if (!raw) return void 0;
343
- return parseInt(raw, 10) || void 0;
469
+ if (!raw) return { permitsAutomaticRetry: true };
470
+ const trimmed = raw.trim();
471
+ let seconds;
472
+ if (/^\d+$/.test(trimmed)) {
473
+ seconds = Number(trimmed);
474
+ if (!Number.isSafeInteger(seconds)) {
475
+ return { permitsAutomaticRetry: false };
476
+ }
477
+ } else {
478
+ const retryAt = Date.parse(trimmed);
479
+ if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
480
+ seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
481
+ }
482
+ return {
483
+ seconds,
484
+ permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
485
+ };
344
486
  }
345
- function mapResponseToError(status, parsed, details, requestId, retryAfter) {
487
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
346
488
  const errorDetails = {
347
489
  ...details,
348
490
  ...parsed.errors && { errors: parsed.errors },
349
- ...parsed.body && { body: parsed.body }
491
+ ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
350
492
  };
351
493
  const suggestion = getParsedErrorSuggestion(status, parsed);
494
+ const finalize = (error) => {
495
+ const withRequestId = attachRequestId(error, requestId);
496
+ if (retryAfter !== void 0) {
497
+ Object.assign(withRequestId, { retryAfter });
498
+ }
499
+ return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
500
+ };
352
501
  if (status === 400 || status === 422) {
353
- return attachRequestId(
502
+ return finalize(
354
503
  createValidationError(
355
504
  parsed.errorMessage,
356
505
  errorDetails,
357
506
  parsed.userMessage,
358
507
  suggestion,
359
508
  status
360
- ),
361
- requestId
509
+ )
362
510
  );
363
511
  }
364
512
  if (status === 401) {
365
- return attachRequestId(
513
+ return finalize(
366
514
  createAuthError(
367
515
  parsed.errorMessage,
368
516
  errorDetails,
369
517
  parsed.userMessage,
370
518
  suggestion
371
- ),
372
- requestId
519
+ )
373
520
  );
374
521
  }
375
522
  if (status === 403) {
376
- return attachRequestId(
523
+ return finalize(
377
524
  createPermissionError(
378
525
  parsed.errorMessage,
379
526
  errorDetails,
380
527
  parsed.userMessage,
381
528
  suggestion
382
- ),
383
- requestId
529
+ )
384
530
  );
385
531
  }
386
532
  if (status === 404) {
387
- return attachRequestId(
533
+ return finalize(
388
534
  createNotFoundError(
389
535
  parsed.errorMessage,
390
536
  errorDetails,
391
537
  parsed.userMessage,
392
538
  suggestion
393
- ),
394
- requestId
539
+ )
395
540
  );
396
541
  }
397
542
  if (status === 409) {
398
- return attachRequestId(
543
+ return finalize(
399
544
  createConflictError(
400
545
  parsed.errorMessage,
401
546
  errorDetails,
402
547
  parsed.userMessage,
403
548
  suggestion
404
- ),
405
- requestId
549
+ )
406
550
  );
407
551
  }
408
552
  if (status === 410) {
409
- return attachRequestId(
553
+ return finalize(
410
554
  createGoneError(
411
555
  parsed.errorMessage,
412
556
  errorDetails,
413
557
  parsed.userMessage,
414
558
  suggestion
415
- ),
416
- requestId
559
+ )
417
560
  );
418
561
  }
419
562
  if (status === 429) {
420
- return attachRequestId(
563
+ return finalize(
421
564
  createRateLimitError(
422
565
  parsed.errorMessage,
423
566
  retryAfter,
424
567
  errorDetails,
425
568
  parsed.userMessage,
426
569
  suggestion
427
- ),
428
- requestId
570
+ )
429
571
  );
430
572
  }
431
573
  if (status === 503) {
432
- return attachRequestId(
574
+ return finalize(
433
575
  createServiceUnavailableError(
434
576
  parsed.errorMessage,
435
577
  retryAfter,
436
578
  errorDetails,
437
579
  parsed.userMessage,
438
580
  suggestion
439
- ),
440
- requestId
581
+ )
441
582
  );
442
583
  }
443
- return attachRequestId(
584
+ return finalize(
444
585
  createNetworkError(
445
586
  parsed.errorMessage,
446
587
  status,
447
588
  errorDetails,
448
589
  parsed.userMessage,
449
590
  suggestion
450
- ),
451
- requestId
591
+ )
452
592
  );
453
593
  }
454
594
  async function httpFetch(url, options) {
@@ -461,6 +601,7 @@ async function httpFetch(url, options) {
461
601
  debug,
462
602
  retry,
463
603
  onUnauthorized,
604
+ errorFamily,
464
605
  ...requestInit
465
606
  } = options || {};
466
607
  const baseUrl = resolveApiUrl(apiUrl);
@@ -513,6 +654,8 @@ async function httpFetch(url, options) {
513
654
  headers: redactSensitiveHeaders(response.headers)
514
655
  });
515
656
  if (!response.ok) {
657
+ const parsed = await parseErrorBody(response);
658
+ const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
516
659
  if (isUsageLimitExceededResponse(response)) {
517
660
  const limit = parseInt(
518
661
  response.headers.get("X-Usage-Limit") || "0",
@@ -526,7 +669,7 @@ async function httpFetch(url, options) {
526
669
  response.headers.get("X-Usage-Remaining") || "0",
527
670
  10
528
671
  );
529
- throw attachRequestId(
672
+ const usageError = attachRequestId(
530
673
  createUsageLimitError(
531
674
  `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
532
675
  { limit, current, remaining },
@@ -540,9 +683,9 @@ async function httpFetch(url, options) {
540
683
  ),
541
684
  requestId
542
685
  );
686
+ throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
543
687
  }
544
- const parsed = await parseErrorBody(response);
545
- if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
688
+ if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
546
689
  hasRetried401 = true;
547
690
  try {
548
691
  const newToken = await onUnauthorized();
@@ -564,13 +707,18 @@ async function httpFetch(url, options) {
564
707
  parsed,
565
708
  details,
566
709
  requestId,
567
- retryAfter
710
+ retryAfter.seconds,
711
+ errorFamily
568
712
  );
569
713
  const method2 = (requestInit.method || "GET").toUpperCase();
570
714
  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)) {
715
+ const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
716
+ if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
572
717
  lastError = error;
573
- const retryDelay = retryConfig.retryDelay(attempt);
718
+ const retryDelay = Math.max(
719
+ retryConfig.retryDelay(attempt),
720
+ (retryAfter.seconds ?? 0) * 1e3
721
+ );
574
722
  debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
575
723
  await delay(retryDelay);
576
724
  continue;
@@ -640,90 +788,45 @@ async function httpFetch(url, options) {
640
788
  throw lastError ?? new NetworkError("Request failed after retries");
641
789
  }
642
790
 
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
791
  // 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);
792
+ function normalizedMarket(value) {
793
+ const market = value?.trim();
794
+ return market || void 0;
795
+ }
796
+ function appendProductLocaleSearchParams(search, options) {
797
+ if (options?.locale) search.set("locale", options.locale);
798
+ if (options?.fallbackLocale !== void 0) {
799
+ search.set(
800
+ "fallbackLocale",
801
+ options.fallbackLocale === false ? "none" : options.fallbackLocale
802
+ );
708
803
  }
709
- return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
710
804
  }
711
- function productDetailCatalogQuery(params) {
805
+ function productDetailSearchParams(params) {
712
806
  const search = new URLSearchParams();
713
807
  if ("slug" in params) {
714
808
  search.set("slug", params.slug);
715
809
  } else {
716
810
  search.set("id", params.id);
717
811
  }
718
- return `${COMMERCE_ENDPOINTS.products.detailCatalog}?${search}`;
812
+ const market = normalizedMarket(params.market);
813
+ if (market) search.set("market", market);
814
+ appendProductLocaleSearchParams(search, params);
815
+ return search.toString();
719
816
  }
720
- function listingGroupsQuery(params) {
721
- return `${COMMERCE_ENDPOINTS.products.listingGroups}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
722
- }
723
- function listingGroupsCatalogQuery(params) {
724
- return `${COMMERCE_ENDPOINTS.products.listingGroupsCatalog}?ids=${params.productIds.map(encodeURIComponent).join(",")}`;
817
+ function listingGroupsSearchParams(params) {
818
+ const ids = params.productIds.map(encodeURIComponent).join(",");
819
+ const search = new URLSearchParams();
820
+ const market = normalizedMarket(params.market);
821
+ if (market) search.set("market", market);
822
+ appendProductLocaleSearchParams(search, params);
823
+ const query = search.toString();
824
+ return `ids=${ids}${query ? `&${query}` : ""}`;
725
825
  }
726
826
  function appendListingGroupsQuerySearchParams(search, options) {
827
+ const market = normalizedMarket(options?.market);
828
+ if (market) search.set("market", market);
829
+ appendProductLocaleSearchParams(search, options);
727
830
  if (options?.page != null) search.set("page", String(options.page));
728
831
  if (options?.limit != null) search.set("limit", String(options.limit));
729
832
  if (options?.sort != null) {
@@ -734,20 +837,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
734
837
  search.set("whereJson", JSON.stringify(options.where));
735
838
  }
736
839
  }
737
- function listingGroupsQueryUrl(options) {
840
+ function listingPageSearchParams(options) {
738
841
  const search = new URLSearchParams();
739
842
  appendListingGroupsQuerySearchParams(search, options);
740
- const query = search.toString();
741
- return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
843
+ return search.toString();
742
844
  }
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(",")}`;
845
+ function stockSnapshotSearchParams(params) {
846
+ return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
751
847
  }
752
848
 
753
849
  // src/core/collection/http-client.ts
@@ -790,10 +886,15 @@ var HttpClient = class {
790
886
  throw err;
791
887
  }
792
888
  }
793
- buildUrl(endpoint, options) {
794
- if (!options) return endpoint;
795
- const queryString = stringify(options, { addQueryPrefix: true });
796
- return queryString ? `${endpoint}${queryString}` : endpoint;
889
+ buildUrl(endpoint2, options) {
890
+ if (!options) return endpoint2;
891
+ const { fallbackLocale, ...rest } = options;
892
+ const queryOptions = fallbackLocale === void 0 ? rest : {
893
+ ...rest,
894
+ "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
895
+ };
896
+ const queryString = stringify(queryOptions, { addQueryPrefix: true });
897
+ return queryString ? `${endpoint2}${queryString}` : endpoint2;
797
898
  }
798
899
  assertJsonResponse(response) {
799
900
  const contentType = response.headers.get("content-type");
@@ -984,16 +1085,16 @@ var CollectionQueryBuilder = class {
984
1085
  * @returns Payload CMS mutation response with doc and message
985
1086
  */
986
1087
  async create(data, options) {
987
- const endpoint = `/api/${String(this.collection)}`;
1088
+ const endpoint2 = `/api/${String(this.collection)}`;
988
1089
  if (options?.file) {
989
1090
  return this.api.requestCreateWithFile(
990
- endpoint,
1091
+ endpoint2,
991
1092
  data,
992
1093
  options.file,
993
1094
  options.filename
994
1095
  );
995
1096
  }
996
- return this.api.requestCreate(endpoint, data);
1097
+ return this.api.requestCreate(endpoint2, data);
997
1098
  }
998
1099
  /**
999
1100
  * Update a document by ID
@@ -1001,16 +1102,16 @@ var CollectionQueryBuilder = class {
1001
1102
  * @returns Payload CMS mutation response with doc and message
1002
1103
  */
1003
1104
  async update(id, data, options) {
1004
- const endpoint = `/api/${String(this.collection)}/${String(id)}`;
1105
+ const endpoint2 = `/api/${String(this.collection)}/${String(id)}`;
1005
1106
  if (options?.file) {
1006
1107
  return this.api.requestUpdateWithFile(
1007
- endpoint,
1108
+ endpoint2,
1008
1109
  data,
1009
1110
  options.file,
1010
1111
  options.filename
1011
1112
  );
1012
1113
  }
1013
- return this.api.requestUpdate(endpoint, data);
1114
+ return this.api.requestUpdate(endpoint2, data);
1014
1115
  }
1015
1116
  /**
1016
1117
  * Count documents
@@ -1106,8 +1207,8 @@ var CollectionClient = class extends HttpClient {
1106
1207
  * Find documents (list query)
1107
1208
  * GET /api/{collection}
1108
1209
  */
1109
- async requestFind(endpoint, options) {
1110
- const url = this.buildUrl(endpoint, options);
1210
+ async requestFind(endpoint2, options) {
1211
+ const url = this.buildUrl(endpoint2, options);
1111
1212
  const response = await this.fetchWithTracking(url, {
1112
1213
  ...this.defaultOptions,
1113
1214
  method: "GET"
@@ -1118,8 +1219,8 @@ var CollectionClient = class extends HttpClient {
1118
1219
  * Find-like response from a custom endpoint
1119
1220
  * POST /api/...custom-endpoint
1120
1221
  */
1121
- async requestFindEndpoint(endpoint, data) {
1122
- const response = await this.fetchWithTracking(endpoint, {
1222
+ async requestFindEndpoint(endpoint2, data) {
1223
+ const response = await this.fetchWithTracking(endpoint2, {
1123
1224
  ...this.defaultOptions,
1124
1225
  method: "POST",
1125
1226
  body: data ? JSON.stringify(data) : void 0
@@ -1129,8 +1230,8 @@ var CollectionClient = class extends HttpClient {
1129
1230
  /**
1130
1231
  * Find-like response from a cacheable GET custom endpoint.
1131
1232
  */
1132
- async requestFindEndpointGet(endpoint) {
1133
- const response = await this.fetchWithTracking(endpoint, {
1233
+ async requestFindEndpointGet(endpoint2) {
1234
+ const response = await this.fetchWithTracking(endpoint2, {
1134
1235
  ...this.defaultOptions,
1135
1236
  method: "GET"
1136
1237
  });
@@ -1140,8 +1241,8 @@ var CollectionClient = class extends HttpClient {
1140
1241
  * Find document by ID
1141
1242
  * GET /api/{collection}/{id}
1142
1243
  */
1143
- async requestFindById(endpoint, options) {
1144
- const url = this.buildUrl(endpoint, options);
1244
+ async requestFindById(endpoint2, options) {
1245
+ const url = this.buildUrl(endpoint2, options);
1145
1246
  const response = await this.fetchWithTracking(url, {
1146
1247
  ...this.defaultOptions,
1147
1248
  method: "GET"
@@ -1152,8 +1253,8 @@ var CollectionClient = class extends HttpClient {
1152
1253
  * Create document
1153
1254
  * POST /api/{collection}
1154
1255
  */
1155
- async requestCreate(endpoint, data) {
1156
- const response = await this.fetchWithTracking(endpoint, {
1256
+ async requestCreate(endpoint2, data) {
1257
+ const response = await this.fetchWithTracking(endpoint2, {
1157
1258
  ...this.defaultOptions,
1158
1259
  method: "POST",
1159
1260
  body: data ? JSON.stringify(data) : void 0
@@ -1164,8 +1265,8 @@ var CollectionClient = class extends HttpClient {
1164
1265
  * Update document
1165
1266
  * PATCH /api/{collection}/{id}
1166
1267
  */
1167
- async requestUpdate(endpoint, data) {
1168
- const response = await this.fetchWithTracking(endpoint, {
1268
+ async requestUpdate(endpoint2, data) {
1269
+ const response = await this.fetchWithTracking(endpoint2, {
1169
1270
  ...this.defaultOptions,
1170
1271
  method: "PATCH",
1171
1272
  body: data ? JSON.stringify(data) : void 0
@@ -1176,8 +1277,8 @@ var CollectionClient = class extends HttpClient {
1176
1277
  * Count documents
1177
1278
  * GET /api/{collection}/count
1178
1279
  */
1179
- async requestCount(endpoint, options) {
1180
- const url = this.buildUrl(endpoint, options);
1280
+ async requestCount(endpoint2, options) {
1281
+ const url = this.buildUrl(endpoint2, options);
1181
1282
  const response = await this.fetchWithTracking(url, {
1182
1283
  ...this.defaultOptions,
1183
1284
  method: "GET"
@@ -1188,8 +1289,8 @@ var CollectionClient = class extends HttpClient {
1188
1289
  * Update multiple documents (bulk update)
1189
1290
  * PATCH /api/{collection}
1190
1291
  */
1191
- async requestUpdateMany(endpoint, data) {
1192
- const response = await this.fetchWithTracking(endpoint, {
1292
+ async requestUpdateMany(endpoint2, data) {
1293
+ const response = await this.fetchWithTracking(endpoint2, {
1193
1294
  ...this.defaultOptions,
1194
1295
  method: "PATCH",
1195
1296
  body: JSON.stringify(data)
@@ -1200,8 +1301,8 @@ var CollectionClient = class extends HttpClient {
1200
1301
  * Delete document
1201
1302
  * DELETE /api/{collection}/{id}
1202
1303
  */
1203
- async requestDelete(endpoint, options) {
1204
- const url = this.buildUrl(endpoint, options);
1304
+ async requestDelete(endpoint2, options) {
1305
+ const url = this.buildUrl(endpoint2, options);
1205
1306
  const response = await this.fetchWithTracking(url, {
1206
1307
  ...this.defaultOptions,
1207
1308
  method: "DELETE"
@@ -1212,8 +1313,8 @@ var CollectionClient = class extends HttpClient {
1212
1313
  * Delete multiple documents (bulk delete)
1213
1314
  * DELETE /api/{collection}
1214
1315
  */
1215
- async requestDeleteMany(endpoint, data) {
1216
- const response = await this.fetchWithTracking(endpoint, {
1316
+ async requestDeleteMany(endpoint2, data) {
1317
+ const response = await this.fetchWithTracking(endpoint2, {
1217
1318
  ...this.defaultOptions,
1218
1319
  method: "DELETE",
1219
1320
  body: JSON.stringify(data)
@@ -1224,8 +1325,8 @@ var CollectionClient = class extends HttpClient {
1224
1325
  * Create document with file upload
1225
1326
  * POST /api/{collection} (multipart/form-data)
1226
1327
  */
1227
- async requestCreateWithFile(endpoint, data, file, filename) {
1228
- const response = await this.fetchWithTracking(endpoint, {
1328
+ async requestCreateWithFile(endpoint2, data, file, filename) {
1329
+ const response = await this.fetchWithTracking(endpoint2, {
1229
1330
  ...this.defaultOptions,
1230
1331
  method: "POST",
1231
1332
  body: buildPayloadFormData(data, file, filename)
@@ -1236,8 +1337,8 @@ var CollectionClient = class extends HttpClient {
1236
1337
  * Update document with file upload
1237
1338
  * PATCH /api/{collection}/{id} (multipart/form-data)
1238
1339
  */
1239
- async requestUpdateWithFile(endpoint, data, file, filename) {
1240
- const response = await this.fetchWithTracking(endpoint, {
1340
+ async requestUpdateWithFile(endpoint2, data, file, filename) {
1341
+ const response = await this.fetchWithTracking(endpoint2, {
1241
1342
  ...this.defaultOptions,
1242
1343
  method: "PATCH",
1243
1344
  body: buildPayloadFormData(data, file, filename)
@@ -1252,53 +1353,339 @@ var ServerCollectionClient = class extends CollectionClient {
1252
1353
  };
1253
1354
 
1254
1355
  // src/core/api/parse-response.ts
1255
- async function parseApiResponse(response, endpoint) {
1256
- let data;
1356
+ async function parseApiResponse(response, endpoint2, options = {}) {
1357
+ if (response.status === 204 || response.headers.get("content-length") === "0") {
1358
+ return void 0;
1359
+ }
1360
+ let parsed;
1257
1361
  try {
1258
- data = await response.json();
1362
+ parsed = await response.json();
1259
1363
  } catch {
1260
1364
  throw createApiError(
1261
- `Invalid JSON response from ${endpoint}`,
1365
+ `Invalid JSON response from ${endpoint2}`,
1262
1366
  response.status,
1263
1367
  void 0,
1264
1368
  "Server returned an invalid response.",
1265
1369
  "Check if the API endpoint is available."
1266
1370
  );
1267
1371
  }
1372
+ if (parsed === null || typeof parsed !== "object") {
1373
+ return parsed;
1374
+ }
1375
+ const data = parsed;
1268
1376
  if (data.error) {
1269
1377
  const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
1270
1378
  const reason = typeof data.reason === "string" ? data.reason : void 0;
1271
1379
  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;
1380
+ const retryAfter = parseRetryAfter(response).seconds;
1381
+ let error;
1274
1382
  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);
1383
+ error = createValidationError(errorMessage, data, errorMessage);
1384
+ } else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
1385
+ error = createAuthError(errorMessage, data, errorMessage);
1386
+ } else if (reason === "forbidden") {
1387
+ error = createPermissionError(errorMessage, data, errorMessage);
1388
+ } else if (reason === "rate_limit_exceeded") {
1389
+ error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
1390
+ } else if (reason === "not_found") {
1391
+ error = createNotFoundError(errorMessage, data, errorMessage);
1392
+ } else if (reason === "conflict") {
1393
+ error = createConflictError(errorMessage, data, errorMessage);
1394
+ } else {
1395
+ error = createApiError(
1396
+ errorMessage,
1397
+ response.status,
1398
+ data,
1399
+ errorMessage,
1400
+ "An error occurred while processing the request."
1401
+ );
1279
1402
  }
1280
- if (reason === "forbidden") {
1281
- throw attachRequestId(createPermissionError(errorMessage, data, errorMessage), requestId);
1403
+ const withRequestId = attachRequestId(error, requestId);
1404
+ if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
1405
+ throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
1406
+ }
1407
+ return data;
1408
+ }
1409
+
1410
+ // ../../internal/http-contracts/src/index.ts
1411
+ var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1412
+ var operation = (collection, method, path) => Object.freeze({
1413
+ [operationBrand]: true,
1414
+ collection,
1415
+ method,
1416
+ path
1417
+ });
1418
+ var COMMERCE_ENDPOINT_OPERATIONS = {
1419
+ products: {
1420
+ detail: operation("products", "get", "/detail"),
1421
+ detailCatalog: operation("products", "get", "/detail/catalog"),
1422
+ listingGroups: operation("products", "get", "/listing-groups"),
1423
+ listingGroupsCatalog: operation(
1424
+ "products",
1425
+ "get",
1426
+ "/listing-groups/catalog"
1427
+ ),
1428
+ listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
1429
+ listingGroupsQueryGet: operation(
1430
+ "products",
1431
+ "get",
1432
+ "/listing-groups/query"
1433
+ ),
1434
+ listingGroupsQueryCatalog: operation(
1435
+ "products",
1436
+ "get",
1437
+ "/listing-groups/query/catalog"
1438
+ ),
1439
+ stockCheck: operation("products", "post", "/stock-check"),
1440
+ stockSnapshot: operation("products", "get", "/stock"),
1441
+ upsert: operation("products", "post", "/upsert")
1442
+ },
1443
+ orders: {
1444
+ create: operation("orders", "post", "/create"),
1445
+ update: operation("orders", "post", "/update"),
1446
+ confirmPayment: operation("orders", "post", "/confirm-payment"),
1447
+ byPayment: operation("orders", "get", "/by-payment"),
1448
+ cancel: operation("orders", "post", "/cancel"),
1449
+ resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1450
+ checkout: operation("orders", "post", "/checkout"),
1451
+ createFulfillment: operation("orders", "post", "/create-fulfillment"),
1452
+ updateFulfillment: operation("orders", "post", "/update-fulfillment")
1453
+ },
1454
+ checkouts: {
1455
+ detail: operation("checkouts", "post", "/detail"),
1456
+ query: operation("checkouts", "post", "/query")
1457
+ },
1458
+ transactions: {
1459
+ update: operation("transactions", "post", "/update")
1460
+ },
1461
+ returns: {
1462
+ create: operation("returns", "post", "/create"),
1463
+ update: operation("returns", "post", "/update"),
1464
+ returnRefund: operation("returns", "post", "/return-refund")
1465
+ },
1466
+ fulfillmentOrders: {
1467
+ prepare: operation(
1468
+ "fulfillment-orders",
1469
+ "post",
1470
+ "/prepare-fulfillment-order"
1471
+ )
1472
+ },
1473
+ fulfillments: {
1474
+ bulkImport: operation("fulfillments", "post", "/bulk-import")
1475
+ },
1476
+ carts: {
1477
+ create: operation("carts", "post", "/create"),
1478
+ retrieve: operation("carts", "post", "/retrieve"),
1479
+ mine: operation("carts", "post", "/mine"),
1480
+ merge: operation("carts", "post", "/merge"),
1481
+ addItem: operation("carts", "post", "/add-item"),
1482
+ updateItem: operation("carts", "post", "/update-item"),
1483
+ removeItem: operation("carts", "post", "/remove-item"),
1484
+ updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
1485
+ updateAttributes: operation("carts", "post", "/update-attributes"),
1486
+ clear: operation("carts", "post", "/clear")
1487
+ },
1488
+ paymentSessions: {
1489
+ create: operation("payment-sessions", "post", "/create"),
1490
+ retrieve: operation("payment-sessions", "post", "/retrieve"),
1491
+ cancel: operation("payment-sessions", "post", "/cancel"),
1492
+ server: {
1493
+ create: operation("payment-sessions", "post", "/server/create"),
1494
+ retrieve: operation("payment-sessions", "post", "/server/retrieve"),
1495
+ cancel: operation("payment-sessions", "post", "/server/cancel"),
1496
+ confirm: operation("payment-sessions", "post", "/server/confirm")
1497
+ },
1498
+ custom: {
1499
+ create: operation("orders", "post", "/custom-payment-sessions"),
1500
+ confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
1282
1501
  }
1283
- if (reason === "rate_limit_exceeded") {
1284
- throw attachRequestId(createRateLimitError(errorMessage, retryAfter, data, errorMessage), requestId);
1502
+ },
1503
+ shippingPolicies: {
1504
+ calculate: operation("shipping-policies", "post", "/calculate")
1505
+ },
1506
+ discounts: {
1507
+ validate: operation("discounts", "post", "/validate")
1508
+ }
1509
+ };
1510
+ var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1511
+ subscribe: operation(null, "post", "/memberships/subscribe"),
1512
+ cancel: operation(null, "post", "/memberships/:id/cancel"),
1513
+ me: operation(null, "get", "/memberships/me")
1514
+ };
1515
+ var EVENTS_ENDPOINT_OPERATIONS = {
1516
+ occurrences: {
1517
+ range: operation("event-occurrences", "get", "/range"),
1518
+ admissionAvailability: operation(
1519
+ "event-occurrences",
1520
+ "get",
1521
+ "/admission-availability"
1522
+ )
1523
+ }
1524
+ };
1525
+ function resolveOperationTemplate(descriptor) {
1526
+ return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
1527
+ }
1528
+ function resolveOperationPath(descriptor, options) {
1529
+ const path = resolveOperationTemplate(descriptor).replace(
1530
+ /:([A-Za-z][A-Za-z0-9_]*)/g,
1531
+ (_, key) => {
1532
+ const value = options?.pathParams?.[key];
1533
+ if (value === void 0) {
1534
+ throw new TypeError(`Missing path parameter: ${key}`);
1535
+ }
1536
+ return encodeURIComponent(value);
1285
1537
  }
1286
- if (reason === "not_found") {
1287
- throw attachRequestId(createNotFoundError(errorMessage, data, errorMessage), requestId);
1538
+ );
1539
+ const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
1540
+ if (unresolved) {
1541
+ throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
1542
+ }
1543
+ const query = options?.query?.toString().replace(/^\?/, "");
1544
+ return query ? `${path}?${query}` : path;
1545
+ }
1546
+ function resolveOperationMethod(descriptor) {
1547
+ return descriptor.method.toUpperCase();
1548
+ }
1549
+
1550
+ // src/core/api/endpoints.ts
1551
+ var endpoint = (method, path) => ({ method, path });
1552
+ var sharedEndpoint = (descriptor) => descriptor;
1553
+ function resolveOperationMethod2(descriptor) {
1554
+ return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1555
+ }
1556
+ function resolveOperationPath2(descriptor, options) {
1557
+ if ("collection" in descriptor) {
1558
+ return resolveOperationPath(descriptor, options);
1559
+ }
1560
+ const query = options?.query?.toString().replace(/^\?/, "");
1561
+ return query ? `${descriptor.path}?${query}` : descriptor.path;
1562
+ }
1563
+ var COMMERCE_ENDPOINTS = {
1564
+ products: {
1565
+ detail: endpoint("GET", "/api/products/detail"),
1566
+ detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1567
+ listingGroups: endpoint("GET", "/api/products/listing-groups"),
1568
+ listingGroupsCatalog: endpoint(
1569
+ "GET",
1570
+ "/api/products/listing-groups/catalog"
1571
+ ),
1572
+ listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1573
+ listingGroupsQueryCatalog: endpoint(
1574
+ "GET",
1575
+ "/api/products/listing-groups/query/catalog"
1576
+ ),
1577
+ stockCheck: endpoint("POST", "/api/products/stock-check"),
1578
+ stockSnapshot: endpoint("GET", "/api/products/stock"),
1579
+ upsert: endpoint("POST", "/api/products/upsert")
1580
+ },
1581
+ orders: {
1582
+ update: endpoint("POST", "/api/orders/update"),
1583
+ byPayment: endpoint("GET", "/api/orders/by-payment"),
1584
+ cancel: endpoint("POST", "/api/orders/cancel"),
1585
+ resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1586
+ createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1587
+ updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1588
+ },
1589
+ checkouts: {
1590
+ create: endpoint("POST", "/api/orders/checkout"),
1591
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1592
+ server: {
1593
+ create: endpoint("POST", "/api/orders/checkout"),
1594
+ retrieve: endpoint("POST", "/api/checkouts/detail"),
1595
+ query: endpoint("POST", "/api/checkouts/query")
1288
1596
  }
1289
- if (reason === "conflict") {
1290
- throw attachRequestId(createConflictError(errorMessage, data, errorMessage), requestId);
1597
+ },
1598
+ returns: {
1599
+ create: endpoint("POST", "/api/returns/create"),
1600
+ update: endpoint("POST", "/api/returns/update"),
1601
+ returnRefund: endpoint("POST", "/api/returns/return-refund")
1602
+ },
1603
+ fulfillmentOrders: {
1604
+ prepare: endpoint(
1605
+ "POST",
1606
+ "/api/fulfillment-orders/prepare-fulfillment-order"
1607
+ )
1608
+ },
1609
+ fulfillments: {
1610
+ bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1611
+ },
1612
+ carts: {
1613
+ create: endpoint("POST", "/api/carts/create"),
1614
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1615
+ mine: endpoint("POST", "/api/carts/mine"),
1616
+ merge: endpoint("POST", "/api/carts/merge"),
1617
+ server: {
1618
+ // Server credentials are an authorization lane, not a second Cart
1619
+ // transport. These must stay bound to the registered shared operations.
1620
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
1621
+ retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
1622
+ mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
1623
+ merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
1624
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1625
+ updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
1626
+ removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
1627
+ updateDiscountCodes: sharedEndpoint(
1628
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
1629
+ ),
1630
+ updateAttributes: sharedEndpoint(
1631
+ COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
1632
+ ),
1633
+ clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
1634
+ },
1635
+ addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
1636
+ updateItem: endpoint("POST", "/api/carts/update-item"),
1637
+ removeItem: endpoint("POST", "/api/carts/remove-item"),
1638
+ updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
1639
+ updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
1640
+ clear: endpoint("POST", "/api/carts/clear")
1641
+ },
1642
+ paymentSessions: {
1643
+ create: endpoint("POST", "/api/payment-sessions/create"),
1644
+ retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
1645
+ cancel: endpoint("POST", "/api/payment-sessions/cancel"),
1646
+ server: {
1647
+ create: endpoint("POST", "/api/payment-sessions/server/create"),
1648
+ retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
1649
+ cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
1650
+ confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
1291
1651
  }
1292
- throw attachRequestId(
1293
- createApiError(errorMessage, response.status, data, errorMessage, "An error occurred while processing the request."),
1294
- requestId
1295
- );
1652
+ },
1653
+ shippingPolicies: {
1654
+ calculate: endpoint("POST", "/api/shipping-policies/calculate")
1296
1655
  }
1297
- return data;
1656
+ };
1657
+ function isCommerceEndpointDescriptor(value) {
1658
+ if (!value || typeof value !== "object") return false;
1659
+ const candidate = value;
1660
+ return typeof candidate.method === "string" && typeof candidate.path === "string";
1661
+ }
1662
+ function flattenEndpointPaths(value) {
1663
+ if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1664
+ if (!value || typeof value !== "object") return [];
1665
+ return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1666
+ }
1667
+ function flattenEndpointDescriptors(value) {
1668
+ if (isCommerceEndpointDescriptor(value)) return [value];
1669
+ if (!value || typeof value !== "object") return [];
1670
+ return Object.values(value).flatMap(
1671
+ (entry) => flattenEndpointDescriptors(entry)
1672
+ );
1298
1673
  }
1674
+ var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1675
+ var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1676
+ var MEMBERSHIP_ENDPOINTS = {
1677
+ subscribe: "/api/memberships/subscribe",
1678
+ cancel: (id) => `/api/memberships/${id}/cancel`,
1679
+ me: "/api/memberships/me"
1680
+ };
1681
+ var MEMBERSHIP_ENDPOINT_PATHS = [
1682
+ MEMBERSHIP_ENDPOINTS.subscribe,
1683
+ MEMBERSHIP_ENDPOINTS.cancel(":id"),
1684
+ MEMBERSHIP_ENDPOINTS.me
1685
+ ];
1299
1686
 
1300
1687
  // src/core/api/customer-scoped-api.ts
1301
- var CustomerScopedApi = class {
1688
+ var CustomerScopedTransport = class {
1302
1689
  constructor(apiName, options) {
1303
1690
  if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
1304
1691
  throw createConfigError(
@@ -1316,10 +1703,10 @@ var CustomerScopedApi = class {
1316
1703
  this.onUnauthorized = options.onUnauthorized;
1317
1704
  this.onRequestId = options.onRequestId;
1318
1705
  }
1319
- async request(endpoint, options) {
1706
+ async request(endpoint2, options) {
1320
1707
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1321
1708
  try {
1322
- const response = await httpFetch(endpoint, {
1709
+ const response = await httpFetch(endpoint2, {
1323
1710
  method: options.method,
1324
1711
  apiUrl: this.apiUrl,
1325
1712
  publishableKey: this.publishableKey,
@@ -1329,10 +1716,13 @@ var CustomerScopedApi = class {
1329
1716
  ...options.body !== void 0 && {
1330
1717
  body: JSON.stringify(options.body)
1331
1718
  },
1332
- ...options.headers && { headers: options.headers }
1719
+ ...options.headers && { headers: options.headers },
1720
+ ...options.errorFamily && { errorFamily: options.errorFamily }
1333
1721
  });
1334
1722
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1335
- return parseApiResponse(response, endpoint);
1723
+ return parseApiResponse(response, endpoint2, {
1724
+ errorFamily: options.errorFamily
1725
+ });
1336
1726
  } catch (err) {
1337
1727
  const id = err instanceof SDKError ? err.requestId ?? null : null;
1338
1728
  this.onRequestId?.(id);
@@ -1340,6 +1730,26 @@ var CustomerScopedApi = class {
1340
1730
  }
1341
1731
  }
1342
1732
  };
1733
+ var CustomerScopedApi = class {
1734
+ constructor(apiName, options) {
1735
+ this.transport = new CustomerScopedTransport(apiName, options);
1736
+ }
1737
+ requestEndpoint(endpoint2, body, options) {
1738
+ return this.transport.request(resolveOperationPath2(endpoint2, options), {
1739
+ method: resolveOperationMethod2(endpoint2),
1740
+ body,
1741
+ headers: options?.headers
1742
+ });
1743
+ }
1744
+ };
1745
+ var RawCustomerScopedApi = class {
1746
+ constructor(apiName, options) {
1747
+ this.transport = new CustomerScopedTransport(apiName, options);
1748
+ }
1749
+ request(endpoint2, options) {
1750
+ return this.transport.request(endpoint2, options);
1751
+ }
1752
+ };
1343
1753
 
1344
1754
  // src/core/community/community-client.ts
1345
1755
  var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
@@ -1350,7 +1760,7 @@ function unwrapPayloadDoc(value) {
1350
1760
  }
1351
1761
  return value;
1352
1762
  }
1353
- var CommunityClient = class extends CustomerScopedApi {
1763
+ var CommunityClient = class extends RawCustomerScopedApi {
1354
1764
  constructor(options) {
1355
1765
  super("CommunityClient", { ...options, requiresCredential: false });
1356
1766
  }
@@ -1394,11 +1804,11 @@ var CommunityClient = class extends CustomerScopedApi {
1394
1804
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1395
1805
  return `/api/comments/public?${urlParams.toString()}`;
1396
1806
  }
1397
- async execute(endpoint, method, body) {
1398
- return this.request(endpoint, { method, body });
1807
+ async execute(endpoint2, method, body) {
1808
+ return this.request(endpoint2, { method, body });
1399
1809
  }
1400
- async executeDoc(endpoint, method, body) {
1401
- const response = await this.execute(endpoint, method, body);
1810
+ async executeDoc(endpoint2, method, body) {
1811
+ const response = await this.execute(endpoint2, method, body);
1402
1812
  return unwrapPayloadDoc(response);
1403
1813
  }
1404
1814
  createPost(params) {
@@ -1633,144 +2043,1366 @@ var CommunityClient = class extends CustomerScopedApi {
1633
2043
  "PATCH",
1634
2044
  body
1635
2045
  );
1636
- }
1637
- };
1638
-
1639
- // src/core/api/base-api.ts
1640
- var BaseApi = class {
1641
- constructor(apiName, options) {
1642
- if (!options.secretKey) {
1643
- throw createConfigError(`secretKey is required for ${apiName}.`);
2046
+ }
2047
+ };
2048
+
2049
+ // src/core/api/base-api.ts
2050
+ var ServerApiTransport = class {
2051
+ constructor(apiName, options) {
2052
+ if (!options.secretKey) {
2053
+ throw createConfigError(`secretKey is required for ${apiName}.`);
2054
+ }
2055
+ this.publishableKey = requirePublishableKeyForSecret(
2056
+ apiName,
2057
+ options.publishableKey,
2058
+ options.secretKey
2059
+ );
2060
+ this.secretKey = options.secretKey;
2061
+ this.apiUrl = options.apiUrl;
2062
+ this.onRequestId = options.onRequestId;
2063
+ }
2064
+ async request(endpoint2, body, options) {
2065
+ const method = options?.method ?? "POST";
2066
+ try {
2067
+ const response = await httpFetch(endpoint2, {
2068
+ method,
2069
+ apiUrl: this.apiUrl,
2070
+ publishableKey: this.publishableKey,
2071
+ secretKey: this.secretKey,
2072
+ ...body !== void 0 && { body: JSON.stringify(body) },
2073
+ ...options?.headers && { headers: options.headers },
2074
+ ...options?.errorFamily && { errorFamily: options.errorFamily }
2075
+ });
2076
+ this.onRequestId?.(response.headers.get("x-request-id") ?? null);
2077
+ return parseApiResponse(response, endpoint2, {
2078
+ errorFamily: options?.errorFamily
2079
+ });
2080
+ } catch (err) {
2081
+ const id = err instanceof SDKError ? err.requestId ?? null : null;
2082
+ this.onRequestId?.(id);
2083
+ throw err;
2084
+ }
2085
+ }
2086
+ };
2087
+ var BaseApi = class {
2088
+ constructor(apiName, options) {
2089
+ this.transport = new ServerApiTransport(apiName, options);
2090
+ }
2091
+ requestEndpoint(endpoint2, body, options) {
2092
+ return this.transport.request(
2093
+ resolveOperationPath2(endpoint2, options),
2094
+ body,
2095
+ {
2096
+ method: resolveOperationMethod2(endpoint2),
2097
+ headers: options?.headers
2098
+ }
2099
+ );
2100
+ }
2101
+ };
2102
+ var RawBaseApi = class {
2103
+ constructor(apiName, options) {
2104
+ this.transport = new ServerApiTransport(apiName, options);
2105
+ this.publishableKey = requirePublishableKeyForSecret(
2106
+ apiName,
2107
+ options.publishableKey,
2108
+ options.secretKey
2109
+ );
2110
+ this.secretKey = options.secretKey;
2111
+ this.apiUrl = options.apiUrl;
2112
+ this.onRequestId = options.onRequestId;
2113
+ }
2114
+ request(endpoint2, body, options) {
2115
+ return this.transport.request(endpoint2, body, options);
2116
+ }
2117
+ };
2118
+
2119
+ // src/core/community/moderation-api.ts
2120
+ var ModerationApi = class extends RawBaseApi {
2121
+ constructor(options) {
2122
+ super("ModerationApi", options);
2123
+ }
2124
+ banCustomer(params) {
2125
+ return this.request(
2126
+ "/api/community-bans/ban-bearer",
2127
+ params,
2128
+ { method: "POST" }
2129
+ );
2130
+ }
2131
+ unbanCustomer(params) {
2132
+ return this.request(
2133
+ "/api/community-bans/unban-bearer",
2134
+ params,
2135
+ { method: "POST" }
2136
+ );
2137
+ }
2138
+ };
2139
+
2140
+ // src/core/api/canonical-response.ts
2141
+ var CART_STATUSES = ["active", "completed", "abandoned"];
2142
+ var MAX_CART_LINE_QUANTITY = 99;
2143
+ var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
2144
+ var MAX_COMMERCE_ADDRESS_LENGTH = 500;
2145
+ var MAX_COMMERCE_EMAIL_LENGTH = 254;
2146
+ var MAX_COMMERCE_PHONE_LENGTH = 32;
2147
+ var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
2148
+ var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
2149
+ var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
2150
+ var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
2151
+ var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
2152
+ var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
2153
+ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2154
+ var PAYMENT_PROVIDERS = ["toss"];
2155
+ var PAYMENT_PROVIDER_STATUSES = [
2156
+ "requires_payment_method",
2157
+ "requires_action",
2158
+ "requires_confirmation",
2159
+ "initializing",
2160
+ "processing",
2161
+ "authorized",
2162
+ "canceling",
2163
+ "unknown",
2164
+ "captured",
2165
+ "failed",
2166
+ "canceled"
2167
+ ];
2168
+ var PAYMENT_FAILURE_REASONS = [
2169
+ "payment_declined",
2170
+ "authentication_failed",
2171
+ "authorization_expired",
2172
+ "payment_method_unavailable",
2173
+ "provider_terminal_failure",
2174
+ "unknown_provider_terminal_failure"
2175
+ ];
2176
+ var CART_WARNING_CODES = [
2177
+ "DISCOUNT_CODE_NOT_HONOURED",
2178
+ "DISCOUNT_CURRENTLY_INACTIVE",
2179
+ "DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
2180
+ "DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
2181
+ "DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
2182
+ "DISCOUNT_NO_ENTITLED_LINE_ITEMS",
2183
+ "DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
2184
+ "DISCOUNT_NOT_FOUND",
2185
+ "DISCOUNT_PURCHASE_NOT_IN_RANGE",
2186
+ "DISCOUNT_USAGE_LIMIT_REACHED",
2187
+ "MERCHANDISE_NOT_ENOUGH_STOCK",
2188
+ "MERCHANDISE_OUT_OF_STOCK"
2189
+ ];
2190
+ function invalidCanonicalResponse(resource, details) {
2191
+ throw createApiError(
2192
+ `Invalid canonical ${resource} response.`,
2193
+ 502,
2194
+ { resource, ...details },
2195
+ `The server returned an incompatible ${resource} response.`,
2196
+ "Verify that the Console commerce contract is deployed before using this SDK version."
2197
+ );
2198
+ }
2199
+ function fail(resource, path, expected) {
2200
+ invalidCanonicalResponse(resource, { path, expected });
2201
+ }
2202
+ function record(value, resource, path) {
2203
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
2204
+ fail(resource, path, "object");
2205
+ }
2206
+ return value;
2207
+ }
2208
+ function exact(value, required, optional, resource, path) {
2209
+ for (const key of required) {
2210
+ if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
2211
+ }
2212
+ const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
2213
+ const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2214
+ if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2215
+ }
2216
+ function string(value, resource, path) {
2217
+ if (typeof value !== "string" || value.length === 0) {
2218
+ fail(resource, path, "non-empty string");
2219
+ }
2220
+ return value;
2221
+ }
2222
+ function boundedString(value, maxLength, resource, path, allowEmpty = false) {
2223
+ if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
2224
+ fail(
2225
+ resource,
2226
+ path,
2227
+ `${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
2228
+ );
2229
+ }
2230
+ return value;
2231
+ }
2232
+ function nullableString(value, resource, path) {
2233
+ if (value !== null && typeof value !== "string") {
2234
+ fail(resource, path, "string or null");
2235
+ }
2236
+ }
2237
+ function cartLineQuantity(value, resource, path) {
2238
+ const quantity = positiveInteger(value, resource, path);
2239
+ if (quantity > MAX_CART_LINE_QUANTITY) {
2240
+ fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
2241
+ }
2242
+ return quantity;
2243
+ }
2244
+ function boolean(value, resource, path) {
2245
+ if (typeof value !== "boolean") fail(resource, path, "boolean");
2246
+ }
2247
+ function safeMinor(value, resource, path) {
2248
+ if (!Number.isSafeInteger(value) || value < 0) {
2249
+ fail(resource, path, "non-negative safe integer");
2250
+ }
2251
+ return value;
2252
+ }
2253
+ function positiveInteger(value, resource, path) {
2254
+ if (!Number.isSafeInteger(value) || value <= 0) {
2255
+ fail(resource, path, "positive safe integer");
2256
+ }
2257
+ return value;
2258
+ }
2259
+ function enumValue(value, values, resource, path) {
2260
+ if (typeof value !== "string" || !values.includes(value)) {
2261
+ fail(resource, path, values.join(" | "));
2262
+ }
2263
+ return value;
2264
+ }
2265
+ function timestamp(value, resource, path) {
2266
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
2267
+ fail(resource, path, "ISO 8601 timestamp with offset");
2268
+ }
2269
+ }
2270
+ function currency(value, resource, path) {
2271
+ if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
2272
+ fail(resource, path, "three-letter uppercase currency code");
2273
+ }
2274
+ }
2275
+ function array(value, resource, path) {
2276
+ if (!Array.isArray(value)) fail(resource, path, "array");
2277
+ return value;
2278
+ }
2279
+ function optionalNullableNumber(value, resource, path) {
2280
+ if (value !== void 0 && value !== null && typeof value !== "number") {
2281
+ fail(resource, path, "number or null");
2282
+ }
2283
+ }
2284
+ function validateMediaSize(value, resource, path) {
2285
+ const item = record(value, resource, path);
2286
+ exact(
2287
+ item,
2288
+ [],
2289
+ ["width", "height", "mimeType", "filename", "url"],
2290
+ resource,
2291
+ path
2292
+ );
2293
+ optionalNullableNumber(item.width, resource, `${path}.width`);
2294
+ optionalNullableNumber(item.height, resource, `${path}.height`);
2295
+ for (const key of ["mimeType", "filename", "url"]) {
2296
+ if (item[key] !== void 0)
2297
+ nullableString(item[key], resource, `${path}.${key}`);
2298
+ }
2299
+ }
2300
+ function validateMedia(value, resource, path) {
2301
+ if (typeof value === "string") return;
2302
+ const media = record(value, resource, path);
2303
+ exact(
2304
+ media,
2305
+ [],
2306
+ ["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
2307
+ resource,
2308
+ path
2309
+ );
2310
+ if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
2311
+ fail(resource, `${path}.id`, "string, number, or null");
2312
+ }
2313
+ for (const key of ["alt", "mimeType", "filename", "url"]) {
2314
+ if (media[key] !== void 0)
2315
+ nullableString(media[key], resource, `${path}.${key}`);
2316
+ }
2317
+ optionalNullableNumber(media.width, resource, `${path}.width`);
2318
+ optionalNullableNumber(media.height, resource, `${path}.height`);
2319
+ if (media.sizes !== void 0) {
2320
+ const sizes = record(media.sizes, resource, `${path}.sizes`);
2321
+ Object.entries(sizes).forEach(
2322
+ ([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
2323
+ );
2324
+ }
2325
+ }
2326
+ function validateReference(value, resource, path) {
2327
+ const ref = record(value, resource, path);
2328
+ exact(ref, ["id", "title", "handle", "image"], [], resource, path);
2329
+ string(ref.id, resource, `${path}.id`);
2330
+ string(ref.title, resource, `${path}.title`);
2331
+ if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
2332
+ if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
2333
+ }
2334
+ function validateAdmission(value, resource, path) {
2335
+ const admission = record(value, resource, path);
2336
+ exact(
2337
+ admission,
2338
+ ["eventId", "occurrenceId", "admissionTypeId"],
2339
+ [],
2340
+ resource,
2341
+ path
2342
+ );
2343
+ string(admission.eventId, resource, `${path}.eventId`);
2344
+ string(admission.occurrenceId, resource, `${path}.occurrenceId`);
2345
+ string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
2346
+ }
2347
+ function compareAdmissions(left, right) {
2348
+ for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
2349
+ if (left[field] < right[field]) return -1;
2350
+ if (left[field] > right[field]) return 1;
2351
+ }
2352
+ return 0;
2353
+ }
2354
+ function validateAdmissions(value, resource, path) {
2355
+ const admissions = array(value, resource, path);
2356
+ if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
2357
+ let prior;
2358
+ admissions.forEach((admission, index) => {
2359
+ validateAdmission(admission, resource, `${path}[${index}]`);
2360
+ const item = admission;
2361
+ const comparison = prior ? compareAdmissions(item, prior) : void 0;
2362
+ if (comparison !== void 0 && comparison <= 0) {
2363
+ fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
2364
+ }
2365
+ prior = item;
2366
+ });
2367
+ }
2368
+ function validateAttributes(value, resource, path) {
2369
+ const attributes = array(value, resource, path);
2370
+ if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
2371
+ const keys = /* @__PURE__ */ new Set();
2372
+ attributes.forEach((value2, index) => {
2373
+ const itemPath = `${path}[${index}]`;
2374
+ const attribute = record(value2, resource, itemPath);
2375
+ exact(attribute, ["key", "value"], [], resource, itemPath);
2376
+ const key = string(attribute.key, resource, `${itemPath}.key`);
2377
+ if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
2378
+ fail(
2379
+ resource,
2380
+ `${itemPath}.key`,
2381
+ "unique, non-reserved key of at most 40 characters"
2382
+ );
2383
+ }
2384
+ keys.add(key);
2385
+ if (typeof attribute.value !== "string" || attribute.value.length > 500) {
2386
+ fail(resource, `${itemPath}.value`, "string of at most 500 characters");
2387
+ }
2388
+ });
2389
+ }
2390
+ function validateCustomer(value, resource, path) {
2391
+ const customer = record(value, resource, path);
2392
+ exact(customer, ["email"], ["name", "phone"], resource, path);
2393
+ const email = boundedString(
2394
+ customer.email,
2395
+ MAX_COMMERCE_EMAIL_LENGTH,
2396
+ resource,
2397
+ `${path}.email`
2398
+ );
2399
+ if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
2400
+ email
2401
+ )) {
2402
+ fail(resource, `${path}.email`, "email address");
2403
+ }
2404
+ if (customer.name !== void 0)
2405
+ boundedString(
2406
+ customer.name,
2407
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2408
+ resource,
2409
+ `${path}.name`
2410
+ );
2411
+ if (customer.phone !== void 0)
2412
+ boundedString(
2413
+ customer.phone,
2414
+ MAX_COMMERCE_PHONE_LENGTH,
2415
+ resource,
2416
+ `${path}.phone`
2417
+ );
2418
+ }
2419
+ function validateShippingAddress(value, resource, path) {
2420
+ const address = record(value, resource, path);
2421
+ exact(
2422
+ address,
2423
+ ["recipientName", "phone", "postalCode", "address", "detailAddress"],
2424
+ ["countryCode", "regionCode", "deliveryMessage"],
2425
+ resource,
2426
+ path
2427
+ );
2428
+ boundedString(
2429
+ address.recipientName,
2430
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
2431
+ resource,
2432
+ `${path}.recipientName`
2433
+ );
2434
+ boundedString(
2435
+ address.phone,
2436
+ MAX_COMMERCE_PHONE_LENGTH,
2437
+ resource,
2438
+ `${path}.phone`
2439
+ );
2440
+ boundedString(
2441
+ address.postalCode,
2442
+ MAX_COMMERCE_POSTAL_CODE_LENGTH,
2443
+ resource,
2444
+ `${path}.postalCode`
2445
+ );
2446
+ for (const key of ["address", "detailAddress"]) {
2447
+ boundedString(
2448
+ address[key],
2449
+ MAX_COMMERCE_ADDRESS_LENGTH,
2450
+ resource,
2451
+ `${path}.${key}`
2452
+ );
2453
+ }
2454
+ if (address.countryCode !== void 0) {
2455
+ if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
2456
+ fail(resource, `${path}.countryCode`, "two-letter country code");
2457
+ }
2458
+ }
2459
+ if (address.regionCode !== void 0) {
2460
+ if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
2461
+ fail(
2462
+ resource,
2463
+ `${path}.regionCode`,
2464
+ "trimmed string of at most 64 characters"
2465
+ );
2466
+ }
2467
+ }
2468
+ if (address.deliveryMessage !== void 0) {
2469
+ boundedString(
2470
+ address.deliveryMessage,
2471
+ MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
2472
+ resource,
2473
+ `${path}.deliveryMessage`,
2474
+ true
2475
+ );
2476
+ }
2477
+ }
2478
+ function validateOrderReference(value, resource, path) {
2479
+ const order = record(value, resource, path);
2480
+ exact(order, ["id", "orderNumber"], [], resource, path);
2481
+ string(order.id, resource, `${path}.id`);
2482
+ string(order.orderNumber, resource, `${path}.orderNumber`);
2483
+ }
2484
+ function validateIntegrationMetadata(value, resource, path) {
2485
+ const metadata = record(value, resource, path);
2486
+ if (Object.keys(metadata).length > 50)
2487
+ fail(resource, path, "at most 50 entries");
2488
+ Object.entries(metadata).forEach(([key, entry]) => {
2489
+ if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
2490
+ fail(resource, `${path}.${key}`, "valid metadata key");
2491
+ }
2492
+ if (typeof entry !== "string" || entry.length > 500) {
2493
+ fail(resource, `${path}.${key}`, "string of at most 500 characters");
2494
+ }
2495
+ });
2496
+ }
2497
+ function validateCartItem(value, resource, path) {
2498
+ const item = record(value, resource, path);
2499
+ exact(
2500
+ item,
2501
+ [
2502
+ "id",
2503
+ "product",
2504
+ "variant",
2505
+ "admissions",
2506
+ "quantity",
2507
+ "unitPriceMinor",
2508
+ "discountMinor",
2509
+ "estimatedLineTotalMinor",
2510
+ "requiresShipping"
2511
+ ],
2512
+ [],
2513
+ resource,
2514
+ path
2515
+ );
2516
+ string(item.id, resource, `${path}.id`);
2517
+ validateReference(item.product, resource, `${path}.product`);
2518
+ validateReference(item.variant, resource, `${path}.variant`);
2519
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2520
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2521
+ const unitPrice = safeMinor(
2522
+ item.unitPriceMinor,
2523
+ resource,
2524
+ `${path}.unitPriceMinor`
2525
+ );
2526
+ const discount = safeMinor(
2527
+ item.discountMinor,
2528
+ resource,
2529
+ `${path}.discountMinor`
2530
+ );
2531
+ const estimatedLineTotal = safeMinor(
2532
+ item.estimatedLineTotalMinor,
2533
+ resource,
2534
+ `${path}.estimatedLineTotalMinor`
2535
+ );
2536
+ const quantity = item.quantity;
2537
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
2538
+ if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
2539
+ fail(
2540
+ resource,
2541
+ `${path}.estimatedLineTotalMinor`,
2542
+ "unitPriceMinor * quantity - discountMinor"
2543
+ );
2544
+ }
2545
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2546
+ }
2547
+ function validatePublicCart(value, resource = "Cart") {
2548
+ const cart = record(value, resource, "$");
2549
+ exact(
2550
+ cart,
2551
+ [
2552
+ "id",
2553
+ "status",
2554
+ "revision",
2555
+ "currency",
2556
+ "market",
2557
+ "subtotalMinor",
2558
+ "discountMinor",
2559
+ "estimatedTotalMinor",
2560
+ "discountCodes",
2561
+ "attributes",
2562
+ "items",
2563
+ "expiresAt",
2564
+ "createdAt",
2565
+ "updatedAt"
2566
+ ],
2567
+ [],
2568
+ resource,
2569
+ "$"
2570
+ );
2571
+ string(cart.id, resource, "$.id");
2572
+ enumValue(cart.status, CART_STATUSES, resource, "$.status");
2573
+ safeMinor(cart.revision, resource, "$.revision");
2574
+ currency(cart.currency, resource, "$.currency");
2575
+ const market = record(cart.market, resource, "$.market");
2576
+ exact(market, ["id", "handle", "name"], [], resource, "$.market");
2577
+ for (const key of ["id", "handle", "name"])
2578
+ string(market[key], resource, `$.market.${key}`);
2579
+ const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
2580
+ const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
2581
+ const estimatedTotal = safeMinor(
2582
+ cart.estimatedTotalMinor,
2583
+ resource,
2584
+ "$.estimatedTotalMinor"
2585
+ );
2586
+ array(cart.discountCodes, resource, "$.discountCodes").forEach(
2587
+ (value2, index) => {
2588
+ const itemPath = `$.discountCodes[${index}]`;
2589
+ const code = record(value2, resource, itemPath);
2590
+ exact(code, ["code", "applicable"], [], resource, itemPath);
2591
+ boundedString(
2592
+ code.code,
2593
+ MAX_CART_DISCOUNT_CODE_LENGTH,
2594
+ resource,
2595
+ `${itemPath}.code`
2596
+ );
2597
+ boolean(code.applicable, resource, `${itemPath}.applicable`);
2598
+ }
2599
+ );
2600
+ validateAttributes(cart.attributes, resource, "$.attributes");
2601
+ const items = array(cart.items, resource, "$.items");
2602
+ items.forEach(
2603
+ (item, index) => validateCartItem(item, resource, `$.items[${index}]`)
2604
+ );
2605
+ const expectedSubtotal = items.reduce((total, value2) => {
2606
+ const item = value2;
2607
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2608
+ }, 0n);
2609
+ const expectedDiscount = items.reduce((total, value2) => {
2610
+ const item = value2;
2611
+ return total + BigInt(item.discountMinor);
2612
+ }, 0n);
2613
+ if (BigInt(subtotal) !== expectedSubtotal) {
2614
+ fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
2615
+ }
2616
+ if (BigInt(discount) !== expectedDiscount) {
2617
+ fail(resource, "$.discountMinor", "sum of cart line discounts");
2618
+ }
2619
+ if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
2620
+ fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
2621
+ }
2622
+ timestamp(cart.expiresAt, resource, "$.expiresAt");
2623
+ timestamp(cart.createdAt, resource, "$.createdAt");
2624
+ timestamp(cart.updatedAt, resource, "$.updatedAt");
2625
+ return value;
2626
+ }
2627
+ function validateWarnings(value, resource, path) {
2628
+ array(value, resource, path).forEach((value2, index) => {
2629
+ const itemPath = `${path}[${index}]`;
2630
+ const warning = record(value2, resource, itemPath);
2631
+ exact(warning, ["code", "message", "target"], [], resource, itemPath);
2632
+ enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
2633
+ string(warning.message, resource, `${itemPath}.message`);
2634
+ string(warning.target, resource, `${itemPath}.target`);
2635
+ });
2636
+ }
2637
+ function validateCartMutationResult(value) {
2638
+ const result = record(value, "Cart mutation result", "$");
2639
+ exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
2640
+ validatePublicCart(result.cart);
2641
+ validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
2642
+ return value;
2643
+ }
2644
+ function validateCreateCartResult(value) {
2645
+ const result = record(value, "Cart create result", "$");
2646
+ exact(
2647
+ result,
2648
+ ["cart", "warnings", "cartToken"],
2649
+ [],
2650
+ "Cart create result",
2651
+ "$"
2652
+ );
2653
+ const cart = record(result.cart, "Cart create result", "$.cart");
2654
+ validatePublicCart(cart);
2655
+ if (cart.revision !== 0) {
2656
+ fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
2657
+ }
2658
+ validateWarnings(result.warnings, "Cart create result", "$.warnings");
2659
+ boundedString(
2660
+ result.cartToken,
2661
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2662
+ "Cart create result",
2663
+ "$.cartToken"
2664
+ );
2665
+ return value;
2666
+ }
2667
+ function validateCartMineResult(value) {
2668
+ const result = record(value, "Cart mine result", "$");
2669
+ exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
2670
+ if (result.cart === null || result.cartToken === null) {
2671
+ if (result.cart !== null || result.cartToken !== null) {
2672
+ fail("Cart mine result", "$", "cart and cartToken must both be null");
2673
+ }
2674
+ } else {
2675
+ validatePublicCart(result.cart);
2676
+ boundedString(
2677
+ result.cartToken,
2678
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2679
+ "Cart mine result",
2680
+ "$.cartToken"
2681
+ );
2682
+ }
2683
+ return value;
2684
+ }
2685
+ function validateCartMergeResult(value) {
2686
+ const result = record(value, "Cart merge result", "$");
2687
+ exact(
2688
+ result,
2689
+ ["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
2690
+ [],
2691
+ "Cart merge result",
2692
+ "$"
2693
+ );
2694
+ validatePublicCart(result.cart);
2695
+ validateWarnings(result.warnings, "Cart merge result", "$.warnings");
2696
+ boundedString(
2697
+ result.cartToken,
2698
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2699
+ "Cart merge result",
2700
+ "$.cartToken"
2701
+ );
2702
+ const resolution = enumValue(
2703
+ result.resolution,
2704
+ ["unchanged", "claimed", "merged"],
2705
+ "Cart merge result",
2706
+ "$.resolution"
2707
+ );
2708
+ boolean(result.merged, "Cart merge result", "$.merged");
2709
+ boolean(result.claimed, "Cart merge result", "$.claimed");
2710
+ const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
2711
+ if (result.merged !== expected[0] || result.claimed !== expected[1]) {
2712
+ fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
2713
+ }
2714
+ return value;
2715
+ }
2716
+ function validateCheckoutItem(value, resource, path) {
2717
+ const item = record(value, resource, path);
2718
+ exact(
2719
+ item,
2720
+ [
2721
+ "id",
2722
+ "product",
2723
+ "variant",
2724
+ "productTitle",
2725
+ "variantTitle",
2726
+ "sku",
2727
+ "admissions",
2728
+ "quantity",
2729
+ "unitPriceMinor",
2730
+ "discountMinor",
2731
+ "lineTotalMinor",
2732
+ "requiresShipping"
2733
+ ],
2734
+ [],
2735
+ resource,
2736
+ path
2737
+ );
2738
+ string(item.id, resource, `${path}.id`);
2739
+ validateReference(item.product, resource, `${path}.product`);
2740
+ validateReference(item.variant, resource, `${path}.variant`);
2741
+ string(item.productTitle, resource, `${path}.productTitle`);
2742
+ nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2743
+ nullableString(item.sku, resource, `${path}.sku`);
2744
+ validateAdmissions(item.admissions, resource, `${path}.admissions`);
2745
+ cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2746
+ const unitPrice = safeMinor(
2747
+ item.unitPriceMinor,
2748
+ resource,
2749
+ `${path}.unitPriceMinor`
2750
+ );
2751
+ const discount = safeMinor(
2752
+ item.discountMinor,
2753
+ resource,
2754
+ `${path}.discountMinor`
2755
+ );
2756
+ const lineTotal = safeMinor(
2757
+ item.lineTotalMinor,
2758
+ resource,
2759
+ `${path}.lineTotalMinor`
2760
+ );
2761
+ const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
2762
+ if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
2763
+ fail(
2764
+ resource,
2765
+ `${path}.lineTotalMinor`,
2766
+ "unitPriceMinor * quantity - discountMinor"
2767
+ );
2768
+ }
2769
+ boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
2770
+ }
2771
+ function validateCheckoutAmounts(value, resource, path) {
2772
+ const amounts = record(value, resource, path);
2773
+ exact(
2774
+ amounts,
2775
+ [
2776
+ "currency",
2777
+ "subtotalMinor",
2778
+ "shippingMinor",
2779
+ "discountMinor",
2780
+ "totalMinor"
2781
+ ],
2782
+ [],
2783
+ resource,
2784
+ path
2785
+ );
2786
+ currency(amounts.currency, resource, `${path}.currency`);
2787
+ const subtotal = safeMinor(
2788
+ amounts.subtotalMinor,
2789
+ resource,
2790
+ `${path}.subtotalMinor`
2791
+ );
2792
+ const shipping = safeMinor(
2793
+ amounts.shippingMinor,
2794
+ resource,
2795
+ `${path}.shippingMinor`
2796
+ );
2797
+ const discount = safeMinor(
2798
+ amounts.discountMinor,
2799
+ resource,
2800
+ `${path}.discountMinor`
2801
+ );
2802
+ const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
2803
+ if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
2804
+ fail(
2805
+ resource,
2806
+ `${path}.totalMinor`,
2807
+ "subtotalMinor + shippingMinor - discountMinor"
2808
+ );
2809
+ }
2810
+ }
2811
+ function validatePaymentSessionReference(value, resource, path) {
2812
+ const session = record(value, resource, path);
2813
+ exact(session, ["id", "provider", "providerStatus"], [], resource, path);
2814
+ string(session.id, resource, `${path}.id`);
2815
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
2816
+ enumValue(
2817
+ session.providerStatus,
2818
+ PAYMENT_PROVIDER_STATUSES,
2819
+ resource,
2820
+ `${path}.providerStatus`
2821
+ );
2822
+ }
2823
+ function checkoutVariantKeys(status, placedVia) {
2824
+ const base = [
2825
+ "id",
2826
+ "amounts",
2827
+ "items",
2828
+ "customerSnapshot",
2829
+ "shippingAddress",
2830
+ "attributes",
2831
+ "expiresAt",
2832
+ "createdAt",
2833
+ "updatedAt",
2834
+ "status",
2835
+ "paymentState",
2836
+ "order"
2837
+ ];
2838
+ if (status === "open") return { required: base, optional: [] };
2839
+ if (status === "abandoned") {
2840
+ return {
2841
+ required: [...base, "abandonedAt", "abandonedReason"],
2842
+ optional: []
2843
+ };
2844
+ }
2845
+ return placedVia === "late_capture" ? {
2846
+ required: [
2847
+ ...base,
2848
+ "placedAt",
2849
+ "placedVia",
2850
+ "abandonedAt",
2851
+ "abandonedReason"
2852
+ ],
2853
+ optional: []
2854
+ } : { required: [...base, "placedAt"], optional: [] };
2855
+ }
2856
+ function validateCheckoutCore(value, resource, list, server) {
2857
+ const checkout = record(value, resource, "$");
2858
+ const status = enumValue(
2859
+ checkout.status,
2860
+ CHECKOUT_STATUSES,
2861
+ resource,
2862
+ "$.status"
2863
+ );
2864
+ const keys = checkoutVariantKeys(status, checkout.placedVia);
2865
+ if (list) {
2866
+ keys.required = keys.required.filter(
2867
+ (key) => !["items", "shippingAddress", "attributes"].includes(key)
2868
+ );
2869
+ keys.required.push("clientReferenceId");
2870
+ } else if (server) {
2871
+ keys.required.push("clientReferenceId", "integrationMetadata");
2872
+ }
2873
+ exact(checkout, keys.required, keys.optional, resource, "$");
2874
+ string(checkout.id, resource, "$.id");
2875
+ validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
2876
+ if (!list) {
2877
+ const items = array(checkout.items, resource, "$.items");
2878
+ if (items.length === 0) fail(resource, "$.items", "non-empty array");
2879
+ items.forEach(
2880
+ (item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
2881
+ );
2882
+ const expectedSubtotal = items.reduce((total, value2) => {
2883
+ const item = value2;
2884
+ return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
2885
+ }, 0n);
2886
+ const expectedDiscount = items.reduce((total, value2) => {
2887
+ const item = value2;
2888
+ return total + BigInt(item.discountMinor);
2889
+ }, 0n);
2890
+ const amounts = checkout.amounts;
2891
+ if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
2892
+ fail(
2893
+ resource,
2894
+ "$.amounts.subtotalMinor",
2895
+ "sum of undiscounted checkout line totals"
2896
+ );
2897
+ }
2898
+ if (BigInt(amounts.discountMinor) !== expectedDiscount) {
2899
+ fail(
2900
+ resource,
2901
+ "$.amounts.discountMinor",
2902
+ "sum of checkout line discounts"
2903
+ );
2904
+ }
2905
+ if (checkout.shippingAddress !== null) {
2906
+ validateShippingAddress(
2907
+ checkout.shippingAddress,
2908
+ resource,
2909
+ "$.shippingAddress"
2910
+ );
2911
+ }
2912
+ validateAttributes(checkout.attributes, resource, "$.attributes");
2913
+ }
2914
+ validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
2915
+ timestamp(checkout.expiresAt, resource, "$.expiresAt");
2916
+ timestamp(checkout.createdAt, resource, "$.createdAt");
2917
+ timestamp(checkout.updatedAt, resource, "$.updatedAt");
2918
+ const paymentState = record(checkout.paymentState, resource, "$.paymentState");
2919
+ exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
2920
+ if (status === "open") {
2921
+ if (paymentState.activePaymentSession !== null) {
2922
+ validatePaymentSessionReference(
2923
+ paymentState.activePaymentSession,
2924
+ resource,
2925
+ "$.paymentState.activePaymentSession"
2926
+ );
2927
+ }
2928
+ if (checkout.order !== null)
2929
+ fail(resource, "$.order", "null for open Checkout");
2930
+ } else {
2931
+ if (paymentState.activePaymentSession !== null) {
2932
+ fail(
2933
+ resource,
2934
+ "$.paymentState.activePaymentSession",
2935
+ "null for spent Checkout"
2936
+ );
2937
+ }
2938
+ if (status === "placed") {
2939
+ timestamp(checkout.placedAt, resource, "$.placedAt");
2940
+ validateOrderReference(checkout.order, resource, "$.order");
2941
+ if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
2942
+ fail(resource, "$.placedVia", "late_capture");
2943
+ }
2944
+ if (checkout.placedVia === "late_capture") {
2945
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2946
+ enumValue(
2947
+ checkout.abandonedReason,
2948
+ ABANDONED_REASONS,
2949
+ resource,
2950
+ "$.abandonedReason"
2951
+ );
2952
+ }
2953
+ } else {
2954
+ timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
2955
+ enumValue(
2956
+ checkout.abandonedReason,
2957
+ ABANDONED_REASONS,
2958
+ resource,
2959
+ "$.abandonedReason"
2960
+ );
2961
+ if (checkout.order !== null)
2962
+ fail(resource, "$.order", "null for abandoned Checkout");
2963
+ }
2964
+ }
2965
+ if (list || server) {
2966
+ if (checkout.clientReferenceId !== null) {
2967
+ boundedString(
2968
+ checkout.clientReferenceId,
2969
+ MAX_COMMERCE_RESOURCE_ID_LENGTH,
2970
+ resource,
2971
+ "$.clientReferenceId"
2972
+ );
2973
+ }
2974
+ }
2975
+ if (server)
2976
+ validateIntegrationMetadata(
2977
+ checkout.integrationMetadata,
2978
+ resource,
2979
+ "$.integrationMetadata"
2980
+ );
2981
+ }
2982
+ function validatePublicCheckout(value) {
2983
+ validateCheckoutCore(value, "Checkout", false, false);
2984
+ return value;
2985
+ }
2986
+ function validateServerCheckout(value) {
2987
+ validateCheckoutCore(value, "Server Checkout", false, true);
2988
+ return value;
2989
+ }
2990
+ function validateCreateCheckoutResult(value, server) {
2991
+ const resource = server ? "Server Checkout create result" : "Checkout create result";
2992
+ const result = record(value, resource, "$");
2993
+ exact(result, ["checkout", "checkoutToken"], [], resource, "$");
2994
+ if (server) validateServerCheckout(result.checkout);
2995
+ else validatePublicCheckout(result.checkout);
2996
+ boundedString(
2997
+ result.checkoutToken,
2998
+ MAX_COMMERCE_CAPABILITY_LENGTH,
2999
+ resource,
3000
+ "$.checkoutToken"
3001
+ );
3002
+ return value;
3003
+ }
3004
+ function validateCheckoutQueryResult(value) {
3005
+ const result = record(value, "Checkout query result", "$");
3006
+ exact(
3007
+ result,
3008
+ ["data", "hasMore", "nextCursor"],
3009
+ [],
3010
+ "Checkout query result",
3011
+ "$"
3012
+ );
3013
+ array(result.data, "Checkout query result", "$.data").forEach(
3014
+ (item) => validateCheckoutCore(item, "Checkout list item", true, false)
3015
+ );
3016
+ boolean(result.hasMore, "Checkout query result", "$.hasMore");
3017
+ if (result.nextCursor !== null)
3018
+ boundedString(
3019
+ result.nextCursor,
3020
+ MAX_COMMERCE_CAPABILITY_LENGTH,
3021
+ "Checkout query result",
3022
+ "$.nextCursor"
3023
+ );
3024
+ if (result.hasMore === true && result.nextCursor === null) {
3025
+ fail(
3026
+ "Checkout query result",
3027
+ "$.nextCursor",
3028
+ "non-null when hasMore is true"
3029
+ );
3030
+ }
3031
+ return value;
3032
+ }
3033
+ function validateMoney(value, resource, path) {
3034
+ const money = record(value, resource, path);
3035
+ exact(money, ["amountMinor", "currency"], [], resource, path);
3036
+ safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3037
+ currency(money.currency, resource, `${path}.currency`);
3038
+ }
3039
+ function validateCaptureEvidence(value, resource, path) {
3040
+ const evidence = record(value, resource, path);
3041
+ exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
3042
+ safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
3043
+ currency(evidence.currency, resource, `${path}.currency`);
3044
+ timestamp(evidence.observedAt, resource, `${path}.observedAt`);
3045
+ }
3046
+ function validateNoReconciliation(value, resource, path) {
3047
+ const reconciliation = record(value, resource, path);
3048
+ exact(reconciliation, ["status"], [], resource, path);
3049
+ if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
3050
+ }
3051
+ function validateRequiredReconciliation(value, allowed, resource, path) {
3052
+ const reconciliation = record(value, resource, path);
3053
+ exact(reconciliation, ["status", "reasons"], [], resource, path);
3054
+ if (reconciliation.status !== "required")
3055
+ fail(resource, `${path}.status`, "required");
3056
+ const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
3057
+ if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
3058
+ let previous = -1;
3059
+ reasons.forEach((reason, index) => {
3060
+ const current = allowed.indexOf(reason);
3061
+ if (current < 0 || current <= previous) {
3062
+ fail(
3063
+ resource,
3064
+ `${path}.reasons[${index}]`,
3065
+ "unique canonical-sorted reconciliation reason"
3066
+ );
3067
+ }
3068
+ previous = current;
3069
+ });
3070
+ }
3071
+ function validateNextAction(value, resource, path) {
3072
+ const action = record(value, resource, path);
3073
+ exact(
3074
+ action,
3075
+ [
3076
+ "type",
3077
+ "clientKey",
3078
+ "paymentMethodVariantKey",
3079
+ "agreementVariantKey",
3080
+ "providerOrderId",
3081
+ "providerCustomerKey",
3082
+ "orderName"
3083
+ ],
3084
+ ["customerName", "customerEmail"],
3085
+ resource,
3086
+ path
3087
+ );
3088
+ if (action.type !== "toss_widget")
3089
+ fail(resource, `${path}.type`, "toss_widget");
3090
+ for (const key of [
3091
+ "clientKey",
3092
+ "paymentMethodVariantKey",
3093
+ "agreementVariantKey"
3094
+ ]) {
3095
+ boundedString(action[key], 255, resource, `${path}.${key}`);
3096
+ }
3097
+ string(action.providerOrderId, resource, `${path}.providerOrderId`);
3098
+ string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
3099
+ boundedString(
3100
+ action.orderName,
3101
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3102
+ resource,
3103
+ `${path}.orderName`
3104
+ );
3105
+ if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
3106
+ fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
3107
+ }
3108
+ 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(
3109
+ action.providerCustomerKey
3110
+ )) {
3111
+ fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
3112
+ }
3113
+ if (action.customerName !== void 0)
3114
+ boundedString(
3115
+ action.customerName,
3116
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3117
+ resource,
3118
+ `${path}.customerName`
3119
+ );
3120
+ if (action.customerEmail !== void 0)
3121
+ validateCustomer({ email: action.customerEmail }, resource, path);
3122
+ }
3123
+ function validatePublicPaymentSession(value) {
3124
+ const resource = "PaymentSession";
3125
+ const session = record(value, resource, "$");
3126
+ enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
3127
+ const status = enumValue(
3128
+ session.providerStatus,
3129
+ PAYMENT_PROVIDER_STATUSES,
3130
+ resource,
3131
+ "$.providerStatus"
3132
+ );
3133
+ const common = [
3134
+ "id",
3135
+ "money",
3136
+ "expiresAt",
3137
+ "sessionRole",
3138
+ "provider",
3139
+ "providerStatus",
3140
+ "presentationStatus",
3141
+ "finalizationStatus",
3142
+ "reconciliation",
3143
+ "order"
3144
+ ];
3145
+ const optional = [];
3146
+ if (status === "requires_payment_method" || status === "requires_action")
3147
+ optional.push("nextAction");
3148
+ else if (status === "captured") common.push("providerEvidence");
3149
+ else if (status === "failed") common.push("failure");
3150
+ else if (status === "canceled") common.push("cancellationReason");
3151
+ exact(session, common, optional, resource, "$");
3152
+ string(session.id, resource, "$.id");
3153
+ validateMoney(session.money, resource, "$.money");
3154
+ if (session.expiresAt !== null)
3155
+ timestamp(session.expiresAt, resource, "$.expiresAt");
3156
+ if (status === "requires_payment_method" || status === "requires_action") {
3157
+ if (session.sessionRole === "active") {
3158
+ if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
3159
+ fail(resource, "$", "actionable active not-ready state");
3160
+ }
3161
+ if (!("nextAction" in session))
3162
+ fail(resource, "$.nextAction", "required field");
3163
+ validateNextAction(session.nextAction, resource, "$.nextAction");
3164
+ } else if (session.sessionRole === "residual") {
3165
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3166
+ fail(resource, "$", "suppressed residual not-ready state");
3167
+ }
3168
+ if ("nextAction" in session)
3169
+ fail(resource, "$.nextAction", "absent for suppressed state");
3170
+ } else fail(resource, "$.sessionRole", "active | residual");
3171
+ validateNoReconciliation(
3172
+ session.reconciliation,
3173
+ resource,
3174
+ "$.reconciliation"
3175
+ );
3176
+ if (session.order !== null) fail(resource, "$.order", "null");
3177
+ } else if ([
3178
+ "requires_confirmation",
3179
+ "initializing",
3180
+ "processing",
3181
+ "authorized",
3182
+ "canceling"
3183
+ ].includes(status)) {
3184
+ enumValue(
3185
+ session.sessionRole,
3186
+ ["active", "residual"],
3187
+ resource,
3188
+ "$.sessionRole"
3189
+ );
3190
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3191
+ fail(resource, "$", "suppressed not-ready state");
1644
3192
  }
1645
- this.publishableKey = requirePublishableKeyForSecret(
1646
- apiName,
1647
- options.publishableKey,
1648
- options.secretKey
3193
+ validateNoReconciliation(
3194
+ session.reconciliation,
3195
+ resource,
3196
+ "$.reconciliation"
1649
3197
  );
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;
3198
+ if (session.order !== null) fail(resource, "$.order", "null");
3199
+ } else if (status === "unknown") {
3200
+ enumValue(
3201
+ session.sessionRole,
3202
+ ["active", "residual"],
3203
+ resource,
3204
+ "$.sessionRole"
3205
+ );
3206
+ if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
3207
+ fail(resource, "$", "suppressed not-ready state");
1671
3208
  }
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" }
3209
+ validateRequiredReconciliation(
3210
+ session.reconciliation,
3211
+ ["provider_outcome_unknown"],
3212
+ resource,
3213
+ "$.reconciliation"
1685
3214
  );
1686
- }
1687
- unbanCustomer(params) {
1688
- return this.request(
1689
- "/api/community-bans/unban-bearer",
1690
- params,
1691
- { method: "POST" }
3215
+ if (session.order !== null) fail(resource, "$.order", "null");
3216
+ } else if (status === "captured") {
3217
+ validateCaptureEvidence(
3218
+ session.providerEvidence,
3219
+ resource,
3220
+ "$.providerEvidence"
3221
+ );
3222
+ if (session.presentationStatus !== "suppressed")
3223
+ fail(resource, "$.presentationStatus", "suppressed");
3224
+ if (session.finalizationStatus === "pending") {
3225
+ enumValue(
3226
+ session.sessionRole,
3227
+ ["canonical_candidate", "residual"],
3228
+ resource,
3229
+ "$.sessionRole"
3230
+ );
3231
+ if (session.order !== null)
3232
+ fail(resource, "$.order", "null for pending finalization");
3233
+ const reconciliation = record(
3234
+ session.reconciliation,
3235
+ resource,
3236
+ "$.reconciliation"
3237
+ );
3238
+ if (reconciliation.status === "none")
3239
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3240
+ else
3241
+ validateRequiredReconciliation(
3242
+ reconciliation,
3243
+ [
3244
+ "local_commit_ambiguous",
3245
+ "amount_mismatch",
3246
+ "currency_mismatch",
3247
+ "excess_capture_pending_order"
3248
+ ],
3249
+ resource,
3250
+ "$.reconciliation"
3251
+ );
3252
+ } else if (session.finalizationStatus === "committed") {
3253
+ validateOrderReference(session.order, resource, "$.order");
3254
+ const reconciliation = record(
3255
+ session.reconciliation,
3256
+ resource,
3257
+ "$.reconciliation"
3258
+ );
3259
+ if (reconciliation.status === "none") {
3260
+ enumValue(
3261
+ session.sessionRole,
3262
+ ["canonical", "historical"],
3263
+ resource,
3264
+ "$.sessionRole"
3265
+ );
3266
+ validateNoReconciliation(reconciliation, resource, "$.reconciliation");
3267
+ } else {
3268
+ enumValue(
3269
+ session.sessionRole,
3270
+ ["canonical", "residual"],
3271
+ resource,
3272
+ "$.sessionRole"
3273
+ );
3274
+ validateRequiredReconciliation(
3275
+ reconciliation,
3276
+ [
3277
+ "inventory_unavailable",
3278
+ "admission_unavailable",
3279
+ "amount_mismatch",
3280
+ "currency_mismatch",
3281
+ "excess_capture",
3282
+ "late_capture",
3283
+ "cross_checkout_duplicate"
3284
+ ],
3285
+ resource,
3286
+ "$.reconciliation"
3287
+ );
3288
+ }
3289
+ } else fail(resource, "$.finalizationStatus", "pending | committed");
3290
+ } else if (status === "failed") {
3291
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3292
+ fail(resource, "$", "historical suppressed failed state");
3293
+ }
3294
+ validateNoReconciliation(
3295
+ session.reconciliation,
3296
+ resource,
3297
+ "$.reconciliation"
3298
+ );
3299
+ const failure = record(session.failure, resource, "$.failure");
3300
+ exact(failure, ["reason"], ["message"], resource, "$.failure");
3301
+ enumValue(
3302
+ failure.reason,
3303
+ PAYMENT_FAILURE_REASONS,
3304
+ resource,
3305
+ "$.failure.reason"
3306
+ );
3307
+ if (failure.message !== void 0)
3308
+ string(failure.message, resource, "$.failure.message");
3309
+ } else {
3310
+ if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
3311
+ fail(resource, "$", "historical suppressed canceled state");
3312
+ }
3313
+ validateNoReconciliation(
3314
+ session.reconciliation,
3315
+ resource,
3316
+ "$.reconciliation"
3317
+ );
3318
+ enumValue(
3319
+ session.cancellationReason,
3320
+ ["expired", "customer", "operator", "provider"],
3321
+ resource,
3322
+ "$.cancellationReason"
1692
3323
  );
1693
3324
  }
1694
- };
3325
+ return value;
3326
+ }
3327
+
3328
+ // src/core/api/commerce-idempotency.ts
3329
+ 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;
3330
+ var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
3331
+ function isCommerceIdempotencyKey(value) {
3332
+ return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
3333
+ }
3334
+ function assertCommerceIdempotencyKey(value) {
3335
+ if (isCommerceIdempotencyKey(value)) return;
3336
+ throw createValidationError(
3337
+ "idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
3338
+ { field: "idempotencyKey" }
3339
+ );
3340
+ }
1695
3341
 
1696
3342
  // src/core/api/cart-api.ts
1697
3343
  var CartApi = class extends CustomerScopedApi {
1698
3344
  constructor(options) {
1699
3345
  super("CartApi", { ...options, requiresCredential: false });
3346
+ this.serverTransport = Boolean(options.secretKey);
1700
3347
  }
1701
- async execute(endpoint, method, body) {
1702
- return this.request(endpoint, { method, body });
3348
+ endpoint(key) {
3349
+ return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
1703
3350
  }
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);
3351
+ execute(endpoint2, body, idempotencyKey) {
3352
+ return this.requestEndpoint(endpoint2, body, {
3353
+ ...idempotencyKey && {
3354
+ headers: { "X-Idempotency-Key": idempotencyKey }
3355
+ }
3356
+ });
1710
3357
  }
1711
- getCart(cartToken) {
1712
- return this.execute("/api/carts/get", "POST", { cartToken });
3358
+ create(params = {}) {
3359
+ return this.execute(this.endpoint("create"), params).then(
3360
+ (value) => validateCreateCartResult(value)
3361
+ );
1713
3362
  }
1714
- merge(params) {
1715
- return this.execute(
1716
- COMMERCE_ENDPOINTS.carts.merge,
1717
- "POST",
1718
- params
3363
+ retrieve(params) {
3364
+ return this.execute(this.endpoint("retrieve"), params).then(
3365
+ (value) => validatePublicCart(value)
1719
3366
  );
1720
3367
  }
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
- {}
3368
+ mine(params = {}) {
3369
+ const endpoint2 = this.endpoint("mine");
3370
+ return this.execute(endpoint2, params).then(
3371
+ (value) => validateCartMineResult(value)
3372
+ );
3373
+ }
3374
+ merge(params) {
3375
+ const { idempotencyKey, ...body } = params;
3376
+ assertCommerceIdempotencyKey(idempotencyKey);
3377
+ const endpoint2 = this.endpoint("merge");
3378
+ return this.execute(endpoint2, body, idempotencyKey).then(
3379
+ (value) => validateCartMergeResult(value)
1731
3380
  );
1732
3381
  }
1733
3382
  addItem(params) {
1734
- return this.execute(
1735
- COMMERCE_ENDPOINTS.carts.addItem,
1736
- "POST",
1737
- params
3383
+ return this.mutate(this.endpoint("addItem"), params);
3384
+ }
3385
+ mutate(endpoint2, params) {
3386
+ const { idempotencyKey, ...body } = params;
3387
+ assertCommerceIdempotencyKey(idempotencyKey);
3388
+ return this.execute(endpoint2, body, idempotencyKey).then(
3389
+ (value) => validateCartMutationResult(value)
1738
3390
  );
1739
3391
  }
1740
3392
  updateItem(params) {
1741
- return this.execute(
1742
- COMMERCE_ENDPOINTS.carts.updateItem,
1743
- "POST",
1744
- params
1745
- );
3393
+ return this.mutate(this.endpoint("updateItem"), params);
1746
3394
  }
1747
3395
  removeItem(params) {
1748
- return this.execute(
1749
- COMMERCE_ENDPOINTS.carts.removeItem,
1750
- "POST",
1751
- params
1752
- );
3396
+ return this.mutate(this.endpoint("removeItem"), params);
1753
3397
  }
1754
- applyDiscount(params) {
1755
- return this.execute(
1756
- COMMERCE_ENDPOINTS.carts.applyDiscount,
1757
- "POST",
1758
- params
1759
- );
3398
+ clear(params) {
3399
+ return this.mutate(this.endpoint("clear"), params);
1760
3400
  }
1761
- removeDiscount(params) {
1762
- return this.execute(
1763
- COMMERCE_ENDPOINTS.carts.removeDiscount,
1764
- "POST",
1765
- params
1766
- );
3401
+ updateDiscountCodes(params) {
3402
+ return this.mutate(this.endpoint("updateDiscountCodes"), params);
1767
3403
  }
1768
- clearCart(params) {
1769
- return this.execute(
1770
- COMMERCE_ENDPOINTS.carts.clear,
1771
- "POST",
1772
- params
1773
- );
3404
+ updateAttributes(params) {
3405
+ return this.mutate(this.endpoint("updateAttributes"), params);
1774
3406
  }
1775
3407
  };
1776
3408
 
@@ -2577,6 +4209,9 @@ function compareVariantOrder(a, b) {
2577
4209
  }
2578
4210
  function getVariantAvailableForSale(variant) {
2579
4211
  if (variant.isActive === false) return false;
4212
+ if (typeof variant.availableForSale === "boolean") {
4213
+ return variant.availableForSale;
4214
+ }
2580
4215
  if (variant.isUnlimited) return true;
2581
4216
  if (variant.inventoryPolicy === "continue") return true;
2582
4217
  return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
@@ -2686,7 +4321,7 @@ function buildProductListingCard(item, options = {}) {
2686
4321
  { listing: { selectionHintVariant } },
2687
4322
  options
2688
4323
  ),
2689
- title: product.title,
4324
+ title: product.title ?? "",
2690
4325
  representativeVariant,
2691
4326
  primaryImage: listingPrimaryMedia,
2692
4327
  priceRange,
@@ -2814,6 +4449,11 @@ function productDetailResultFromError(error) {
2814
4449
  if (!reason) return void 0;
2815
4450
  return { found: false, reason };
2816
4451
  }
4452
+ var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
4453
+ var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
4454
+ "priceRange.minVariantPrice.amount",
4455
+ "priceRange.maxVariantPrice.amount"
4456
+ ]);
2817
4457
  function nonEmpty(values) {
2818
4458
  return values?.length ? values : void 0;
2819
4459
  }
@@ -2861,14 +4501,34 @@ function buildProductListingPageWhere(params) {
2861
4501
  if (clauses.length === 1) return clauses[0];
2862
4502
  return { and: clauses };
2863
4503
  }
2864
- function buildProductListingPageUrl(params) {
4504
+ function productListingPageUsesBasePriceSort(sort) {
4505
+ const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
4506
+ return values.some(
4507
+ (value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
4508
+ );
4509
+ }
4510
+ function assertMarketListingPageQuerySupported(params) {
4511
+ if (!params.market?.trim()) return;
4512
+ const priceFilter = params.filters?.price;
4513
+ if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
4514
+ throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
4515
+ }
4516
+ }
4517
+ function buildProductListingPageRequest(params) {
4518
+ assertMarketListingPageQuerySupported(params);
2865
4519
  const options = {
4520
+ market: params.market,
4521
+ locale: params.locale,
4522
+ fallbackLocale: params.fallbackLocale,
2866
4523
  page: params.page,
2867
4524
  limit: params.limit,
2868
4525
  sort: params.sort,
2869
4526
  where: buildProductListingPageWhere(params)
2870
4527
  };
2871
- return params.mode === "full" ? listingGroupsQueryUrl(options) : listingGroupsQueryCatalogUrl(options);
4528
+ return {
4529
+ operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
4530
+ query: listingPageSearchParams(options)
4531
+ };
2872
4532
  }
2873
4533
  function withProductListingCards(response, options) {
2874
4534
  return {
@@ -2917,38 +4577,40 @@ var ProductApi = class extends BaseApi {
2917
4577
  * to remain available by the time an order is placed.
2918
4578
  */
2919
4579
  stockCheck(params) {
2920
- return this.request(
2921
- COMMERCE_ENDPOINTS.products.stockCheck,
4580
+ return this.requestEndpoint(
4581
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
2922
4582
  params
2923
4583
  );
2924
4584
  }
2925
4585
  stockSnapshot(params) {
2926
- return this.request(
2927
- stockSnapshotQuery(params),
4586
+ return this.requestEndpoint(
4587
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
2928
4588
  void 0,
2929
- { method: "GET" }
4589
+ { query: stockSnapshotSearchParams(params) }
2930
4590
  );
2931
4591
  }
2932
4592
  listingGroups(params) {
2933
- return this.request(
2934
- listingGroupsQuery(params),
4593
+ return this.requestEndpoint(
4594
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups,
2935
4595
  void 0,
2936
- { method: "GET" }
4596
+ { query: listingGroupsSearchParams(params) }
2937
4597
  );
2938
4598
  }
2939
4599
  listingGroupsCatalog(params) {
2940
- return this.request(
2941
- listingGroupsCatalogQuery(params),
4600
+ return this.requestEndpoint(
4601
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
2942
4602
  void 0,
2943
- { method: "GET" }
4603
+ { query: listingGroupsSearchParams(params) }
2944
4604
  );
2945
4605
  }
2946
4606
  async listingPage(params = {}) {
2947
4607
  if (params.mode === "full") {
2948
- const response2 = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4608
+ const request2 = buildProductListingPageRequest(params);
4609
+ const response2 = await this.requestEndpoint(request2.operation, void 0, { query: request2.query });
2949
4610
  return withProductListingCards(response2, params);
2950
4611
  }
2951
- const response = await this.request(buildProductListingPageUrl(params), void 0, { method: "GET" });
4612
+ const request = buildProductListingPageRequest(params);
4613
+ const response = await this.requestEndpoint(request.operation, void 0, { query: request.query });
2952
4614
  return withProductListingCards(response, params);
2953
4615
  }
2954
4616
  /**
@@ -2963,10 +4625,10 @@ var ProductApi = class extends BaseApi {
2963
4625
  */
2964
4626
  async detail(params) {
2965
4627
  try {
2966
- const product = await this.request(
2967
- productDetailQuery(params),
4628
+ const product = await this.requestEndpoint(
4629
+ COMMERCE_ENDPOINT_OPERATIONS.products.detail,
2968
4630
  void 0,
2969
- { method: "GET" }
4631
+ { query: productDetailSearchParams(params) }
2970
4632
  );
2971
4633
  return { found: true, product };
2972
4634
  } catch (err) {
@@ -2977,10 +4639,10 @@ var ProductApi = class extends BaseApi {
2977
4639
  }
2978
4640
  async detailCatalog(params) {
2979
4641
  try {
2980
- const product = await this.request(
2981
- productDetailCatalogQuery(params),
4642
+ const product = await this.requestEndpoint(
4643
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
2982
4644
  void 0,
2983
- { method: "GET" }
4645
+ { query: productDetailSearchParams(params) }
2984
4646
  );
2985
4647
  return { found: true, product };
2986
4648
  } catch (err) {
@@ -2996,8 +4658,8 @@ var ProductApi = class extends BaseApi {
2996
4658
  * `product-upsert` tool.
2997
4659
  */
2998
4660
  upsert(params) {
2999
- return this.request(
3000
- COMMERCE_ENDPOINTS.products.upsert,
4661
+ return this.requestEndpoint(
4662
+ COMMERCE_ENDPOINT_OPERATIONS.products.upsert,
3001
4663
  normalizeProductUpsertParams(params)
3002
4664
  );
3003
4665
  }
@@ -3009,7 +4671,10 @@ var DiscountApi = class extends BaseApi {
3009
4671
  super("DiscountApi", options);
3010
4672
  }
3011
4673
  validate(params) {
3012
- return this.request("/api/discounts/validate", params);
4674
+ return this.requestEndpoint(
4675
+ COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
4676
+ params
4677
+ );
3013
4678
  }
3014
4679
  };
3015
4680
 
@@ -3019,7 +4684,10 @@ var ShippingApi = class extends BaseApi {
3019
4684
  super("ShippingApi", options);
3020
4685
  }
3021
4686
  calculate(params) {
3022
- return this.request("/api/shipping-policies/calculate", params);
4687
+ return this.requestEndpoint(
4688
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
4689
+ params
4690
+ );
3023
4691
  }
3024
4692
  };
3025
4693
 
@@ -3031,44 +4699,12 @@ function splitIdempotencyKey(params) {
3031
4699
  const { idempotencyKey, ...body } = params;
3032
4700
  return { body, idempotencyKey };
3033
4701
  }
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
4702
  var OrderApi = class extends BaseApi {
3043
4703
  constructor(options) {
3044
4704
  super("OrderApi", options);
3045
4705
  }
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
4706
  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
- );
4707
+ return this.requestEndpoint(COMMERCE_ENDPOINTS.orders.update, params);
3072
4708
  }
3073
4709
  /**
3074
4710
  * Resolve an order + its payment transaction by PG payment id. Replaces raw
@@ -3080,28 +4716,12 @@ var OrderApi = class extends BaseApi {
3080
4716
  pgProvider: params.pgProvider,
3081
4717
  pgPaymentId: params.pgPaymentId
3082
4718
  }).toString();
3083
- return this.request(
3084
- `${COMMERCE_ENDPOINTS.orders.byPayment}?${query}`,
4719
+ return this.requestEndpoint(
4720
+ COMMERCE_ENDPOINTS.orders.byPayment,
3085
4721
  void 0,
3086
- { method: "GET" }
4722
+ { query }
3087
4723
  );
3088
4724
  }
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
4725
  cancelOrder(params) {
3106
4726
  const { idempotencyKey } = params;
3107
4727
  const body = {
@@ -3109,14 +4729,14 @@ var OrderApi = class extends BaseApi {
3109
4729
  reasonCode: params.reasonCode,
3110
4730
  reasonDetail: params.reasonDetail
3111
4731
  };
3112
- return this.request(
4732
+ return this.requestEndpoint(
3113
4733
  COMMERCE_ENDPOINTS.orders.cancel,
3114
4734
  body,
3115
4735
  idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0
3116
4736
  );
3117
4737
  }
3118
4738
  resolveCancelRefund(params) {
3119
- return this.request(
4739
+ return this.requestEndpoint(
3120
4740
  COMMERCE_ENDPOINTS.orders.resolveCancelRefund,
3121
4741
  {
3122
4742
  orderNumber: params.orderNumber,
@@ -3129,49 +4749,35 @@ var OrderApi = class extends BaseApi {
3129
4749
  idempotencyRequestOptions(params.idempotencyKey)
3130
4750
  );
3131
4751
  }
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
4752
  createFulfillment(params) {
3147
4753
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3148
- return this.request(
4754
+ return this.requestEndpoint(
3149
4755
  COMMERCE_ENDPOINTS.orders.createFulfillment,
3150
4756
  body,
3151
4757
  idempotencyRequestOptions(idempotencyKey)
3152
4758
  );
3153
4759
  }
3154
4760
  prepareFulfillmentOrder(params) {
3155
- return this.request(
4761
+ return this.requestEndpoint(
3156
4762
  COMMERCE_ENDPOINTS.fulfillmentOrders.prepare,
3157
4763
  params
3158
4764
  );
3159
4765
  }
3160
4766
  updateFulfillment(params) {
3161
- return this.request(
4767
+ return this.requestEndpoint(
3162
4768
  COMMERCE_ENDPOINTS.orders.updateFulfillment,
3163
4769
  params
3164
4770
  );
3165
4771
  }
3166
4772
  bulkImportFulfillments(params) {
3167
- return this.request(
4773
+ return this.requestEndpoint(
3168
4774
  COMMERCE_ENDPOINTS.fulfillments.bulkImport,
3169
4775
  params
3170
4776
  );
3171
4777
  }
3172
4778
  returnWithRefund(params) {
3173
4779
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3174
- return this.request(
4780
+ return this.requestEndpoint(
3175
4781
  COMMERCE_ENDPOINTS.returns.returnRefund,
3176
4782
  body,
3177
4783
  idempotencyRequestOptions(idempotencyKey)
@@ -3179,19 +4785,139 @@ var OrderApi = class extends BaseApi {
3179
4785
  }
3180
4786
  createReturn(params) {
3181
4787
  const { body, idempotencyKey } = splitIdempotencyKey(params);
3182
- return this.request(
4788
+ return this.requestEndpoint(
3183
4789
  COMMERCE_ENDPOINTS.returns.create,
3184
4790
  body,
3185
4791
  idempotencyRequestOptions(idempotencyKey)
3186
4792
  );
3187
4793
  }
3188
4794
  updateReturn(params) {
3189
- return this.request(COMMERCE_ENDPOINTS.returns.update, params);
4795
+ return this.requestEndpoint(
4796
+ COMMERCE_ENDPOINTS.returns.update,
4797
+ params
4798
+ );
4799
+ }
4800
+ };
4801
+
4802
+ // src/core/api/checkout-api.ts
4803
+ var CheckoutApi = class extends CustomerScopedApi {
4804
+ constructor(options) {
4805
+ super("CheckoutApi", { ...options, requiresCredential: false });
4806
+ }
4807
+ post(endpoint2, body, idempotencyKey) {
4808
+ return this.requestEndpoint(endpoint2, body, {
4809
+ ...idempotencyKey && {
4810
+ headers: { "X-Idempotency-Key": idempotencyKey }
4811
+ }
4812
+ });
4813
+ }
4814
+ async publicCheckout(result) {
4815
+ return validatePublicCheckout(await result);
4816
+ }
4817
+ async serverCheckout(result) {
4818
+ return validateServerCheckout(await result);
4819
+ }
4820
+ async createResult(result) {
4821
+ return validateCreateCheckoutResult(
4822
+ await result,
4823
+ false
4824
+ );
4825
+ }
4826
+ async createServerResult(result) {
4827
+ return validateCreateCheckoutResult(
4828
+ await result,
4829
+ true
4830
+ );
4831
+ }
4832
+ create(params) {
4833
+ const { idempotencyKey, ...body } = params;
4834
+ assertCommerceIdempotencyKey(idempotencyKey);
4835
+ return this.createResult(
4836
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
4837
+ );
4838
+ }
4839
+ createServer(params) {
4840
+ const { idempotencyKey, ...body } = params;
4841
+ assertCommerceIdempotencyKey(idempotencyKey);
4842
+ return this.createServerResult(
4843
+ this.post(
4844
+ COMMERCE_ENDPOINTS.checkouts.server.create,
4845
+ body,
4846
+ idempotencyKey
4847
+ )
4848
+ );
4849
+ }
4850
+ retrieve(params) {
4851
+ return this.publicCheckout(
4852
+ this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
4853
+ );
4854
+ }
4855
+ retrieveServer(params) {
4856
+ return this.serverCheckout(
4857
+ this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
4858
+ );
4859
+ }
4860
+ async query(params = {}) {
4861
+ const result = await this.post(
4862
+ COMMERCE_ENDPOINTS.checkouts.server.query,
4863
+ params
4864
+ );
4865
+ return validateCheckoutQueryResult(result);
4866
+ }
4867
+ };
4868
+
4869
+ // src/core/api/payment-session-api.ts
4870
+ var PaymentSessionApi = class extends CustomerScopedApi {
4871
+ constructor(options) {
4872
+ super("PaymentSessionApi", { ...options, requiresCredential: false });
4873
+ this.serverTransport = Boolean(options.secretKey);
4874
+ }
4875
+ post(endpoint2, body, idempotencyKey) {
4876
+ return this.requestEndpoint(endpoint2, body, {
4877
+ ...idempotencyKey && {
4878
+ headers: { "X-Idempotency-Key": idempotencyKey }
4879
+ }
4880
+ });
4881
+ }
4882
+ async paymentSession(result) {
4883
+ return validatePublicPaymentSession(await result);
4884
+ }
4885
+ create(params) {
4886
+ const { idempotencyKey, ...body } = params;
4887
+ assertCommerceIdempotencyKey(idempotencyKey);
4888
+ return this.paymentSession(
4889
+ this.post(
4890
+ this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
4891
+ body,
4892
+ idempotencyKey
4893
+ )
4894
+ );
4895
+ }
4896
+ retrieve(params) {
4897
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4898
+ return this.paymentSession(this.post(endpoint2, params));
4899
+ }
4900
+ cancel(params) {
4901
+ const { idempotencyKey, ...body } = params;
4902
+ assertCommerceIdempotencyKey(idempotencyKey);
4903
+ const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4904
+ return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
4905
+ }
4906
+ confirm(params) {
4907
+ const { idempotencyKey, ...body } = params;
4908
+ assertCommerceIdempotencyKey(idempotencyKey);
4909
+ return this.paymentSession(
4910
+ this.post(
4911
+ COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
4912
+ body,
4913
+ idempotencyKey
4914
+ )
4915
+ );
3190
4916
  }
3191
4917
  };
3192
4918
 
3193
4919
  // src/core/preview/server-preview-client.ts
3194
- var ServerPreviewClient = class extends BaseApi {
4920
+ var ServerPreviewClient = class extends RawBaseApi {
3195
4921
  constructor(options) {
3196
4922
  super("ServerPreviewClient", options);
3197
4923
  }
@@ -3247,6 +4973,7 @@ var PreviewProductApi = class extends ProductApi {
3247
4973
  };
3248
4974
  var ServerCommerceClient = class {
3249
4975
  constructor(options) {
4976
+ this.market = options.market;
3250
4977
  const publishableKey = requirePublishableKeyForSecret(
3251
4978
  "ServerCommerceClient",
3252
4979
  options.publishableKey,
@@ -3263,33 +4990,33 @@ var ServerCommerceClient = class {
3263
4990
  const discountApi = new DiscountApi(serverOptions);
3264
4991
  const shippingApi = new ShippingApi(serverOptions);
3265
4992
  const orderApi = new OrderApi(serverOptions);
4993
+ const checkoutApi = new CheckoutApi(serverOptions);
4994
+ const paymentSessionApi = new PaymentSessionApi(serverOptions);
3266
4995
  this.product = {
3267
4996
  stockCheck: productApi.stockCheck.bind(productApi),
3268
- listingGroups: productApi.listingGroups.bind(productApi),
3269
- listingPage: productApi.listingPage.bind(productApi),
3270
- detail: productApi.detail.bind(productApi),
4997
+ listingGroups: (params) => productApi.listingGroups(this.withMarket(params)),
4998
+ listingPage: ((params = {}) => productApi.listingPage(
4999
+ this.withMarket(params)
5000
+ )),
5001
+ detail: (params) => productApi.detail(this.withMarket(params)),
5002
+ detailCatalog: (params) => productApi.detailCatalog(this.withMarket(params)),
3271
5003
  previewDetail: productApi.previewDetail.bind(productApi),
3272
5004
  upsert: productApi.upsert.bind(productApi)
3273
5005
  };
3274
- this.cart = {
3275
- create: cartApi.createCart.bind(cartApi),
3276
- get: cartApi.getCart.bind(cartApi),
5006
+ this.carts = {
5007
+ create: (params) => cartApi.create(this.withMarket(params ?? {})),
5008
+ retrieve: cartApi.retrieve.bind(cartApi),
3277
5009
  addItem: cartApi.addItem.bind(cartApi),
3278
5010
  updateItem: cartApi.updateItem.bind(cartApi),
3279
5011
  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)
5012
+ updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
5013
+ updateAttributes: cartApi.updateAttributes.bind(cartApi),
5014
+ clear: cartApi.clear.bind(cartApi),
5015
+ merge: (params) => cartApi.merge(params),
5016
+ mine: (params) => cartApi.mine(params)
3285
5017
  };
3286
5018
  this.orders = {
3287
- checkout: orderApi.checkout.bind(orderApi),
3288
- create: orderApi.createOrder.bind(orderApi),
3289
5019
  update: orderApi.updateOrder.bind(orderApi),
3290
- updateTransaction: orderApi.updateTransaction.bind(orderApi),
3291
- confirmPayment: orderApi.confirmPayment.bind(orderApi),
3292
- confirmPaymentReturningOrder: orderApi.confirmPaymentReturningOrder.bind(orderApi),
3293
5020
  getByPaymentId: orderApi.getByPaymentId.bind(orderApi),
3294
5021
  cancelOrder: orderApi.cancelOrder.bind(orderApi),
3295
5022
  resolveCancelRefund: orderApi.resolveCancelRefund.bind(orderApi),
@@ -3301,6 +5028,17 @@ var ServerCommerceClient = class {
3301
5028
  updateReturn: orderApi.updateReturn.bind(orderApi),
3302
5029
  returnWithRefund: orderApi.returnWithRefund.bind(orderApi)
3303
5030
  };
5031
+ this.checkouts = {
5032
+ create: checkoutApi.createServer.bind(checkoutApi),
5033
+ retrieve: checkoutApi.retrieveServer.bind(checkoutApi),
5034
+ query: checkoutApi.query.bind(checkoutApi)
5035
+ };
5036
+ this.paymentSessions = {
5037
+ create: paymentSessionApi.create.bind(paymentSessionApi),
5038
+ retrieve: (params) => paymentSessionApi.retrieve(params),
5039
+ cancel: (params) => paymentSessionApi.cancel(params),
5040
+ confirm: paymentSessionApi.confirm.bind(paymentSessionApi)
5041
+ };
3304
5042
  this.discounts = {
3305
5043
  validate: discountApi.validate.bind(discountApi)
3306
5044
  };
@@ -3308,6 +5046,14 @@ var ServerCommerceClient = class {
3308
5046
  calculate: shippingApi.calculate.bind(shippingApi)
3309
5047
  };
3310
5048
  }
5049
+ getDefaultMarket() {
5050
+ return this.market;
5051
+ }
5052
+ withMarket(params) {
5053
+ const defaultMarket = this.market?.trim();
5054
+ if (!defaultMarket || params.market?.trim()) return params;
5055
+ return { ...params, market: defaultMarket };
5056
+ }
3311
5057
  };
3312
5058
 
3313
5059
  // src/core/events/events-client.ts
@@ -3327,7 +5073,17 @@ var EventsClient = class {
3327
5073
  getRange(params) {
3328
5074
  return this.execute(
3329
5075
  buildRangeEndpoint(params),
3330
- "GET",
5076
+ resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
5077
+ void 0,
5078
+ { useCustomerAuth: false }
5079
+ );
5080
+ }
5081
+ getAdmissionAvailability(params) {
5082
+ return this.execute(
5083
+ buildAdmissionAvailabilityEndpoint(params),
5084
+ resolveOperationMethod(
5085
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
5086
+ ),
3331
5087
  void 0,
3332
5088
  { useCustomerAuth: false }
3333
5089
  );
@@ -3356,11 +5112,11 @@ var EventsClient = class {
3356
5112
  { useCustomerAuth: false }
3357
5113
  );
3358
5114
  }
3359
- async execute(endpoint, method, body, options = {}) {
5115
+ async execute(endpoint2, method, body, options = {}) {
3360
5116
  const useCustomerAuth = options.useCustomerAuth === true;
3361
5117
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
3362
5118
  try {
3363
- const response = await httpFetch(endpoint, {
5119
+ const response = await httpFetch(endpoint2, {
3364
5120
  method,
3365
5121
  apiUrl: this.apiUrl,
3366
5122
  publishableKey: this.publishableKey,
@@ -3369,7 +5125,7 @@ var EventsClient = class {
3369
5125
  ...body !== void 0 && { body: JSON.stringify(body) }
3370
5126
  });
3371
5127
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
3372
- return parseApiResponse(response, endpoint);
5128
+ return parseApiResponse(response, endpoint2);
3373
5129
  } catch (err) {
3374
5130
  const id = err instanceof SDKError ? err.requestId ?? null : null;
3375
5131
  this.onRequestId?.(id);
@@ -3408,7 +5164,17 @@ function buildRangeEndpoint(params) {
3408
5164
  appendValues(urlParams, "categorySlug", params.categorySlug);
3409
5165
  appendValues(urlParams, "tag", params.tag);
3410
5166
  appendValues(urlParams, "tagSlug", params.tagSlug);
3411
- return `/api/event-occurrences/range?${urlParams.toString()}`;
5167
+ return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
5168
+ query: urlParams
5169
+ });
5170
+ }
5171
+ function buildAdmissionAvailabilityEndpoint(params) {
5172
+ const urlParams = new URLSearchParams();
5173
+ urlParams.set("occurrence", params.occurrence);
5174
+ return resolveOperationPath(
5175
+ EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
5176
+ { query: urlParams }
5177
+ );
3412
5178
  }
3413
5179
  function formatDateParam(value) {
3414
5180
  return value instanceof Date ? value.toISOString() : value;
@@ -3421,11 +5187,56 @@ function appendValues(params, key, value) {
3421
5187
  }
3422
5188
  }
3423
5189
 
5190
+ // src/core/market/market-discovery.ts
5191
+ function toMarketDTO(row) {
5192
+ return {
5193
+ id: row.id,
5194
+ handle: row.handle,
5195
+ name: row.name,
5196
+ countryCode: row.countryCode,
5197
+ targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
5198
+ currency: row.currency,
5199
+ isPrimary: row.isPrimary === true,
5200
+ isActive: row.isActive === true
5201
+ };
5202
+ }
5203
+ var MarketDiscovery = class {
5204
+ constructor(read) {
5205
+ this.read = read;
5206
+ }
5207
+ async list() {
5208
+ const res = await this.read({
5209
+ where: { isActive: { equals: true } },
5210
+ limit: 100
5211
+ });
5212
+ if (res.hasNextPage) {
5213
+ console.warn(
5214
+ "[markets.list] more than 100 active markets; results truncated to 100."
5215
+ );
5216
+ }
5217
+ return res.docs.map(toMarketDTO);
5218
+ }
5219
+ async default() {
5220
+ const res = await this.read({
5221
+ where: { isPrimary: { equals: true }, isActive: { equals: true } },
5222
+ limit: 1
5223
+ });
5224
+ const row = res.docs[0];
5225
+ return row ? toMarketDTO(row) : null;
5226
+ }
5227
+ };
5228
+
3424
5229
  // src/core/api/tenant-introspection-api.ts
3425
- var TenantIntrospectionApi = class extends BaseApi {
5230
+ var TenantIntrospectionApi = class extends RawBaseApi {
3426
5231
  constructor(options) {
3427
5232
  super("TenantIntrospectionApi", options);
3428
5233
  }
5234
+ context(params = {}) {
5235
+ const endpoint2 = params.includeCounts ? "/api/tenants/context?counts=true" : "/api/tenants/context";
5236
+ return this.request(endpoint2, void 0, {
5237
+ method: "GET"
5238
+ });
5239
+ }
3429
5240
  collectionSchema(collection) {
3430
5241
  return this.request(
3431
5242
  `/api/tenants/schema/${encodeURIComponent(collection)}`,
@@ -3459,40 +5270,30 @@ var MembershipApi = class extends BaseApi {
3459
5270
  */
3460
5271
  subscribe(params) {
3461
5272
  const { subscribeIntentKey, ...body } = params;
3462
- return this.request(
3463
- MEMBERSHIP_ENDPOINTS.subscribe,
5273
+ return this.requestEndpoint(
5274
+ MEMBERSHIP_ENDPOINT_OPERATIONS.subscribe,
3464
5275
  body,
3465
5276
  idempotencyRequestOptions(subscribeIntentKey)
3466
5277
  );
3467
5278
  }
3468
5279
  /**
3469
5280
  * 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.
5281
+ * By default this sets `cancelAtPeriodEnd`, keeps benefits until
5282
+ * `currentPeriodEnd`, and stops renewal. Pass `immediate=true` to cancel
5283
+ * immediately and revoke membership groups now.
3473
5284
  */
3474
5285
  cancel(params) {
3475
5286
  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" }
5287
+ return this.requestEndpoint(
5288
+ MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
5289
+ immediate !== void 0 ? { immediate } : {},
5290
+ { pathParams: { id } }
3490
5291
  );
3491
5292
  }
3492
5293
  };
3493
5294
 
3494
5295
  // src/core/client/client.server.ts
3495
- var ServerClient = class {
5296
+ var ServerClient = class _ServerClient {
3496
5297
  constructor(options) {
3497
5298
  this.lastRequestId = null;
3498
5299
  if (typeof window !== "undefined") {
@@ -3521,17 +5322,18 @@ var ServerClient = class {
3521
5322
  publishableKey: this.config.publishableKey,
3522
5323
  secretKey: this.config.secretKey,
3523
5324
  apiUrl: this.config.apiUrl,
5325
+ market: this.config.market,
3524
5326
  onRequestId
3525
5327
  };
3526
5328
  this.commerce = new ServerCommerceClient(serverOptions);
3527
5329
  const membershipApi = new MembershipApi(serverOptions);
3528
5330
  this.memberships = {
3529
5331
  subscribe: membershipApi.subscribe.bind(membershipApi),
3530
- cancel: membershipApi.cancel.bind(membershipApi),
3531
- me: membershipApi.me.bind(membershipApi)
5332
+ cancel: membershipApi.cancel.bind(membershipApi)
3532
5333
  };
3533
5334
  const tenantIntrospectionApi = new TenantIntrospectionApi(serverOptions);
3534
5335
  this.tenant = {
5336
+ context: tenantIntrospectionApi.context.bind(tenantIntrospectionApi),
3535
5337
  collectionSchema: tenantIntrospectionApi.collectionSchema.bind(
3536
5338
  tenantIntrospectionApi
3537
5339
  ),
@@ -3559,6 +5361,9 @@ var ServerClient = class {
3559
5361
  onRequestId,
3560
5362
  this.config.apiUrl
3561
5363
  );
5364
+ this.markets = new MarketDiscovery(
5365
+ (options2) => this.collections.from("markets").find(options2)
5366
+ );
3562
5367
  }
3563
5368
  get events() {
3564
5369
  if (!this._events) {
@@ -3580,6 +5385,9 @@ var ServerClient = class {
3580
5385
  getState() {
3581
5386
  return { ...this.state };
3582
5387
  }
5388
+ withMarket(market) {
5389
+ return new _ServerClient({ ...this.config, market });
5390
+ }
3583
5391
  getConfig() {
3584
5392
  const { secretKey: _, ...safeConfig } = this.config;
3585
5393
  return safeConfig;