@01.software/sdk 0.44.0 → 0.46.0

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