@01.software/sdk 0.70.1 → 0.72.1

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 (70) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/MIGRATION.md +28 -0
  3. package/README.md +253 -11
  4. package/dist/client.cjs +396 -26
  5. package/dist/client.cjs.map +1 -1
  6. package/dist/client.d.cts +7 -6
  7. package/dist/client.d.ts +7 -6
  8. package/dist/client.js +396 -26
  9. package/dist/client.js.map +1 -1
  10. package/dist/{collection-client-BHLStm1K.d.cts → collection-client-B3CnqMDQ.d.cts} +14 -18
  11. package/dist/{collection-client-B1FSJ24_.d.ts → collection-client-uOgS_1bC.d.ts} +14 -18
  12. package/dist/{const-ty8u0TDI.d.ts → const-BJBK7jBl.d.ts} +1 -1
  13. package/dist/{const-BfQfV-rr.d.cts → const-_ZfJjRQG.d.cts} +1 -1
  14. package/dist/embedded-admin/server.cjs +117 -2
  15. package/dist/embedded-admin/server.cjs.map +1 -1
  16. package/dist/embedded-admin/server.d.cts +30 -2
  17. package/dist/embedded-admin/server.d.ts +30 -2
  18. package/dist/embedded-admin/server.js +117 -2
  19. package/dist/embedded-admin/server.js.map +1 -1
  20. package/dist/embedded-admin.cjs +135 -7
  21. package/dist/embedded-admin.cjs.map +1 -1
  22. package/dist/embedded-admin.d.cts +35 -2
  23. package/dist/embedded-admin.d.ts +35 -2
  24. package/dist/embedded-admin.js +135 -7
  25. package/dist/embedded-admin.js.map +1 -1
  26. package/dist/errors.cjs +2 -0
  27. package/dist/errors.cjs.map +1 -1
  28. package/dist/errors.d.cts +3 -3
  29. package/dist/errors.d.ts +3 -3
  30. package/dist/errors.js +2 -0
  31. package/dist/errors.js.map +1 -1
  32. package/dist/{index-DnKgjPGM.d.ts → index-CBaP4q8r.d.ts} +3 -3
  33. package/dist/{index-CX6si6YC.d.cts → index-CI_LFWiG.d.cts} +3 -3
  34. package/dist/index.cjs +396 -26
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +24 -9
  37. package/dist/index.d.ts +24 -9
  38. package/dist/index.js +396 -26
  39. package/dist/index.js.map +1 -1
  40. package/dist/{payload-types-DTAaWKrp.d.cts → payload-types-BRg8Yary.d.cts} +262 -177
  41. package/dist/{payload-types-DTAaWKrp.d.ts → payload-types-BRg8Yary.d.ts} +262 -177
  42. package/dist/query.cjs +20 -0
  43. package/dist/query.cjs.map +1 -1
  44. package/dist/query.d.cts +5 -5
  45. package/dist/query.d.ts +5 -5
  46. package/dist/query.js +20 -0
  47. package/dist/query.js.map +1 -1
  48. package/dist/realtime.d.cts +2 -2
  49. package/dist/realtime.d.ts +2 -2
  50. package/dist/server.cjs +459 -46
  51. package/dist/server.cjs.map +1 -1
  52. package/dist/server.d.cts +10 -8
  53. package/dist/server.d.ts +10 -8
  54. package/dist/server.js +459 -46
  55. package/dist/server.js.map +1 -1
  56. package/dist/storefront-cache.cjs +2 -0
  57. package/dist/storefront-cache.cjs.map +1 -1
  58. package/dist/storefront-cache.js +2 -0
  59. package/dist/storefront-cache.js.map +1 -1
  60. package/dist/{types-DdlhpNVv.d.ts → types-Cmnxxvuv.d.ts} +238 -21
  61. package/dist/{types-Bzgf4mTo.d.cts → types-CnkJQUez.d.cts} +238 -21
  62. package/dist/{types-DX8Z44yQ.d.ts → types-DLjSqL0P.d.ts} +2 -2
  63. package/dist/{types-CpSiyJud.d.cts → types-FyklqLAk.d.cts} +2 -2
  64. package/dist/ui/form.d.cts +1 -1
  65. package/dist/ui/form.d.ts +1 -1
  66. package/dist/ui/video.d.cts +1 -1
  67. package/dist/ui/video.d.ts +1 -1
  68. package/dist/webhook.d.cts +5 -5
  69. package/dist/webhook.d.ts +5 -5
  70. package/package.json +2 -4
package/dist/client.cjs CHANGED
@@ -128,6 +128,7 @@ var COMMERCE_ERROR_CODES = [
128
128
  "cart_not_active",
129
129
  "cart_locked",
130
130
  "cart_empty",
131
+ "shipping_address_required",
131
132
  "cart_market_unavailable",
132
133
  "cart_market_mismatch",
133
134
  "checkout_not_open",
@@ -144,6 +145,7 @@ var COMMERCE_ERROR_CODES = [
144
145
  "price_changed",
145
146
  "pricing_fact_in_use",
146
147
  "insufficient_stock",
148
+ "credit_insufficient",
147
149
  "reservation_conflict",
148
150
  "stock_lock_unavailable",
149
151
  "variant_not_found",
@@ -607,6 +609,8 @@ async function parseErrorBody(response) {
607
609
  try {
608
610
  const body = await response.json();
609
611
  const reason = typeof body.reason === "string" ? body.reason : typeof body.code === "string" ? body.code : void 0;
612
+ const payloadErrorReason = Array.isArray(body.errors) ? readPayloadErrorReason(body.errors) : void 0;
613
+ const payloadReasonField = payloadErrorReason !== void 0 ? { payloadErrorReason } : {};
610
614
  if (body.errors && Array.isArray(body.errors)) {
611
615
  const fieldErrors = [];
612
616
  for (const e of body.errors) {
@@ -629,6 +633,7 @@ async function parseErrorBody(response) {
629
633
  errorMessage: `HTTP ${response.status}: ${details}`,
630
634
  userMessage: details,
631
635
  reason,
636
+ ...payloadReasonField,
632
637
  body,
633
638
  errors: fieldErrors.length > 0 ? fieldErrors : body.errors
634
639
  };
@@ -639,6 +644,7 @@ async function parseErrorBody(response) {
639
644
  errorMessage: `HTTP ${response.status}: ${body.error}`,
640
645
  userMessage: body.error,
641
646
  reason,
647
+ ...payloadReasonField,
642
648
  body
643
649
  };
644
650
  }
@@ -647,14 +653,23 @@ async function parseErrorBody(response) {
647
653
  errorMessage: `HTTP ${response.status}: ${body.message}`,
648
654
  userMessage: body.message,
649
655
  reason,
656
+ ...payloadReasonField,
650
657
  body
651
658
  };
652
659
  }
653
- return { ...fallback, reason, body };
660
+ return { ...fallback, reason, ...payloadReasonField, body };
654
661
  } catch {
655
662
  return fallback;
656
663
  }
657
664
  }
665
+ function readPayloadErrorReason(errors) {
666
+ const data = errors[0]?.data;
667
+ if (!data || typeof data !== "object") return void 0;
668
+ const { reason, code } = data;
669
+ if (typeof reason === "string") return reason;
670
+ if (typeof code === "string") return code;
671
+ return void 0;
672
+ }
658
673
  function getParsedErrorSuggestion(status, parsed) {
659
674
  if (status === 403 && parsed.reason === "origin_not_allowed") {
660
675
  return "Add the request origin to the tenant Browser API origins, then retry the browser request.";
@@ -700,7 +715,10 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, cano
700
715
  if (retryAfter !== void 0) {
701
716
  Object.assign(withRequestId, { retryAfter });
702
717
  }
703
- return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
718
+ return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(
719
+ withRequestId,
720
+ parsed.reason ?? parsed.payloadErrorReason
721
+ );
704
722
  };
705
723
  if (status === 400 || status === 422) {
706
724
  return finalize(
@@ -1119,6 +1137,7 @@ async function parseApiResponse(response, endpoint, options = {}) {
1119
1137
  // ../../internal/http-contracts/src/index.ts
1120
1138
  var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1121
1139
  var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
1140
+ var CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE = "application/vnd.01software.credit-funding.v1+json";
1122
1141
  var operation = (collection, method, path, errorFamily) => Object.freeze({
1123
1142
  [operationBrand]: true,
1124
1143
  collection,
@@ -1282,6 +1301,11 @@ var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
1282
1301
  ]);
1283
1302
  var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1284
1303
  subscribe: operation(null, "post", "/memberships/subscribe"),
1304
+ endSubscribeIntent: operation(
1305
+ null,
1306
+ "post",
1307
+ "/memberships/subscribe-intent/end"
1308
+ ),
1285
1309
  billingCustody: operation(null, "post", "/memberships/billing-custody"),
1286
1310
  cancel: operation(null, "post", "/memberships/:id/cancel"),
1287
1311
  me: operation(null, "get", "/memberships/me"),
@@ -1327,6 +1351,19 @@ var BENEFIT_VOUCHER_ENDPOINT_OPERATIONS = {
1327
1351
  void: operation("customers", "post", "/benefit-vouchers/void"),
1328
1352
  listMine: operation("customers", "get", "/me/benefit-vouchers")
1329
1353
  };
1354
+ var CUSTOMER_CREDIT_ENDPOINT_OPERATIONS = {
1355
+ grant: strictCommerceOperation("customers", "post", "/credits/grant"),
1356
+ getGrant: strictCommerceOperation("customers", "post", "/credits/get-grant"),
1357
+ getAccount: strictCommerceOperation("customers", "post", "/credits/account"),
1358
+ revoke: strictCommerceOperation("customers", "post", "/credits/revoke"),
1359
+ mine: strictCommerceOperation("customers", "get", "/me/credits"),
1360
+ history: strictCommerceOperation("customers", "get", "/me/credits/history"),
1361
+ configure: strictCommerceOperation(
1362
+ "customers",
1363
+ "post",
1364
+ "/credits/configuration"
1365
+ )
1366
+ };
1330
1367
  var CUSTOMER_GROUP_ENDPOINT_OPERATIONS = {
1331
1368
  members: operation("customer-groups", "get", "/:id/members"),
1332
1369
  grant: operation("customer-groups", "post", "/:id/members/grant"),
@@ -1716,6 +1753,140 @@ var CustomerBenefitVouchersApi = class extends CustomerScopedApi {
1716
1753
  }
1717
1754
  };
1718
1755
 
1756
+ // src/core/api/customer-credit-types.ts
1757
+ function invalid() {
1758
+ throw createApiError("Invalid customer credit response", 502);
1759
+ }
1760
+ function object2(value, keys) {
1761
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(value, key)))
1762
+ invalid();
1763
+ return value;
1764
+ }
1765
+ function money(value) {
1766
+ return typeof value === "string" && /^(0|[1-9][0-9]*)$/.test(value);
1767
+ }
1768
+ function uuid2(value) {
1769
+ return typeof value === "string" && /^([0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i.test(
1770
+ value
1771
+ );
1772
+ }
1773
+ function time2(value) {
1774
+ if (typeof value !== "string") return false;
1775
+ const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
1776
+ if (!match) return false;
1777
+ const [, year, month, day, hour, minute, second = "0"] = match;
1778
+ const y = Number(year), m = Number(month), d = Number(day);
1779
+ const days = [
1780
+ 31,
1781
+ y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 29 : 28,
1782
+ 31,
1783
+ 30,
1784
+ 31,
1785
+ 30,
1786
+ 31,
1787
+ 31,
1788
+ 30,
1789
+ 31,
1790
+ 30,
1791
+ 31
1792
+ ];
1793
+ return m >= 1 && m <= 12 && d >= 1 && d <= days[m - 1] && Number(hour) < 24 && Number(minute) < 60 && Number(second) < 60;
1794
+ }
1795
+ var states = ["available", "held", "spent", "expired", "revoked"];
1796
+ function balances(value) {
1797
+ const data = object2(value, states);
1798
+ if (states.some((key) => !money(data[key]))) invalid();
1799
+ }
1800
+ function page(value) {
1801
+ if (value.currency !== "KRW" || !time2(value.evaluatedAt) || !Number.isSafeInteger(value.page) || value.page < 1 || typeof value.hasNextPage !== "boolean")
1802
+ invalid();
1803
+ }
1804
+ function parseMyCustomerCredits(value) {
1805
+ const data = object2(value, [
1806
+ "currency",
1807
+ "evaluatedAt",
1808
+ "granted",
1809
+ "balances",
1810
+ "buckets",
1811
+ "page",
1812
+ "hasNextPage"
1813
+ ]);
1814
+ page(data);
1815
+ balances(data.balances);
1816
+ if (!money(data.granted) || !Array.isArray(data.buckets) || data.buckets.length > 50)
1817
+ invalid();
1818
+ for (const value2 of data.buckets) {
1819
+ const bucket = object2(value2, [
1820
+ "id",
1821
+ "grantId",
1822
+ "kind",
1823
+ "grantedAt",
1824
+ "expiresAt",
1825
+ "isRevoked",
1826
+ "balances"
1827
+ ]);
1828
+ if (!uuid2(bucket.id) || !uuid2(bucket.grantId) || !["original", "grace"].includes(bucket.kind) || !time2(bucket.grantedAt) || !time2(bucket.expiresAt) || typeof bucket.isRevoked !== "boolean")
1829
+ invalid();
1830
+ balances(bucket.balances);
1831
+ }
1832
+ return value;
1833
+ }
1834
+ function parseMyCustomerCreditHistory(value) {
1835
+ const data = object2(value, [
1836
+ "currency",
1837
+ "evaluatedAt",
1838
+ "entries",
1839
+ "page",
1840
+ "hasNextPage"
1841
+ ]);
1842
+ page(data);
1843
+ if (!Array.isArray(data.entries) || data.entries.length > 50) invalid();
1844
+ for (const value2 of data.entries) {
1845
+ const entry = object2(value2, [
1846
+ "id",
1847
+ "grantId",
1848
+ "kind",
1849
+ "amount",
1850
+ "fromState",
1851
+ "toState",
1852
+ "createdAt"
1853
+ ]);
1854
+ if (!uuid2(entry.id) || !uuid2(entry.grantId) || !money(entry.amount) || !time2(entry.createdAt) || ![
1855
+ "grant",
1856
+ "reserve",
1857
+ "consume",
1858
+ "release",
1859
+ "restore",
1860
+ "expire",
1861
+ "revoke"
1862
+ ].includes(entry.kind) || entry.fromState !== null && !states.includes(entry.fromState) || entry.toState !== null && !states.includes(entry.toState))
1863
+ invalid();
1864
+ }
1865
+ return value;
1866
+ }
1867
+
1868
+ // src/core/api/customer-credits-api.ts
1869
+ var CustomerCreditsApi = class extends CustomerScopedApi {
1870
+ async mine(params = {}) {
1871
+ const query = new URLSearchParams();
1872
+ if (params.page !== void 0) query.set("page", String(params.page));
1873
+ return parseMyCustomerCredits(
1874
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.mine, void 0, {
1875
+ query
1876
+ })
1877
+ );
1878
+ }
1879
+ async history(params = {}) {
1880
+ const query = new URLSearchParams();
1881
+ if (params.page !== void 0) query.set("page", String(params.page));
1882
+ return parseMyCustomerCreditHistory(
1883
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.history, void 0, {
1884
+ query
1885
+ })
1886
+ );
1887
+ }
1888
+ };
1889
+
1719
1890
  // src/core/collection/http-client.ts
1720
1891
  var import_qs_esm = require("qs-esm");
1721
1892
  function validateWhere(where) {
@@ -2166,11 +2337,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
2166
2337
  * - `rootComment`: comments belonging to a thread rooted at that comment.
2167
2338
  */
2168
2339
  listComments(params) {
2169
- const { postId, page, limit, rootComment, topLevelOnly, sort } = params;
2340
+ const { postId, page: page2, limit, rootComment, topLevelOnly, sort } = params;
2170
2341
  return this.execute(
2171
2342
  this.buildCommentsListQuery({
2172
2343
  postId,
2173
- page,
2344
+ page: page2,
2174
2345
  limit,
2175
2346
  rootComment,
2176
2347
  topLevelOnly,
@@ -2181,11 +2352,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
2181
2352
  }
2182
2353
  /** Direct replies to a comment (`where[parent][equals]`). */
2183
2354
  listReplies(params) {
2184
- const { commentId, page, limit, sort } = params;
2355
+ const { commentId, page: page2, limit, sort } = params;
2185
2356
  return this.execute(
2186
2357
  this.buildCommentsListQuery({
2187
2358
  parentId: commentId,
2188
- page,
2359
+ page: page2,
2189
2360
  limit,
2190
2361
  sort
2191
2362
  }),
@@ -2442,7 +2613,18 @@ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2442
2613
  function managedPaymentProviders(providers) {
2443
2614
  return providers;
2444
2615
  }
2445
- var PAYMENT_PROVIDERS = managedPaymentProviders(["toss", "portone"]);
2616
+ var PAYMENT_PROVIDERS = managedPaymentProviders([
2617
+ "toss",
2618
+ "portone",
2619
+ "stripe"
2620
+ ]);
2621
+ var CANCEL_RECOVERY_METHODS = {
2622
+ toss: "cancel()",
2623
+ portone: "cancelPortOne()",
2624
+ stripe: null
2625
+ };
2626
+ var STRIPE_RETURN_URL_RAW_CHARACTERS = /^[^\s\u0000-\u001F\u007F\\]+$/;
2627
+ var STRIPE_RETURN_URL_AUTHORITY = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+(?:[/?#]|$)/;
2446
2628
  var PAYMENT_PROVIDER_STATUSES = [
2447
2629
  "requires_payment_method",
2448
2630
  "requires_action",
@@ -2491,11 +2673,8 @@ function fail(resource, path, expected) {
2491
2673
  invalidCanonicalResponse(resource, { path, expected });
2492
2674
  }
2493
2675
  function providerMismatch(resource, expected, actual, operation2) {
2494
- if (operation2 === "cancel") {
2495
- const method = {
2496
- toss: "cancel()",
2497
- portone: "cancelPortOne()"
2498
- }[actual];
2676
+ const method = CANCEL_RECOVERY_METHODS[actual];
2677
+ if (operation2 === "cancel" && method !== null) {
2499
2678
  throw createApiError(
2500
2679
  `Canonical ${resource} response provider mismatch: expected ${expected}, received ${actual}.`,
2501
2680
  502,
@@ -2524,6 +2703,17 @@ function exact(value, required, optional, resource, path) {
2524
2703
  const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2525
2704
  if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2526
2705
  }
2706
+ function responseExtensionKeys(value, keys, resource, path) {
2707
+ if (!keys.some((key) => Object.prototype.hasOwnProperty.call(value, key)))
2708
+ return [];
2709
+ enumValue(
2710
+ value.deliveryMethod,
2711
+ ["shipping", "pickup"],
2712
+ resource,
2713
+ `${path}.deliveryMethod`
2714
+ );
2715
+ return [...keys];
2716
+ }
2527
2717
  function string(value, resource, path) {
2528
2718
  if (typeof value !== "string" || value.length === 0) {
2529
2719
  fail(resource, path, "non-empty string");
@@ -2863,6 +3053,12 @@ function validatePublicCart(value, resource = "Cart") {
2863
3053
  exact(
2864
3054
  cart,
2865
3055
  [
3056
+ ...responseExtensionKeys(
3057
+ cart,
3058
+ ["deliveryMethod", "shippingMinor", "totalMinor"],
3059
+ resource,
3060
+ "$"
3061
+ ),
2866
3062
  "id",
2867
3063
  "status",
2868
3064
  "revision",
@@ -2933,6 +3129,13 @@ function validatePublicCart(value, resource = "Cart") {
2933
3129
  if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
2934
3130
  fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
2935
3131
  }
3132
+ if ("deliveryMethod" in cart) {
3133
+ const shipping = safeMinor(cart.shippingMinor, resource, "$.shippingMinor");
3134
+ const total = safeMinor(cart.totalMinor, resource, "$.totalMinor");
3135
+ if (BigInt(total) !== BigInt(estimatedTotal) + BigInt(shipping)) {
3136
+ fail(resource, "$.totalMinor", "estimatedTotalMinor + shippingMinor");
3137
+ }
3138
+ }
2936
3139
  timestamp(cart.expiresAt, resource, "$.expiresAt");
2937
3140
  timestamp(cart.createdAt, resource, "$.createdAt");
2938
3141
  timestamp(cart.updatedAt, resource, "$.updatedAt");
@@ -3091,6 +3294,12 @@ function validatePublicOrderAt(value, resource, path) {
3091
3294
  exact(
3092
3295
  order,
3093
3296
  [
3297
+ ...responseExtensionKeys(
3298
+ order,
3299
+ ["deliveryMethod", "pickup", "source"],
3300
+ resource,
3301
+ path
3302
+ ),
3094
3303
  "id",
3095
3304
  "orderNumber",
3096
3305
  "amounts",
@@ -3112,6 +3321,37 @@ function validatePublicOrderAt(value, resource, path) {
3112
3321
  resource,
3113
3322
  path
3114
3323
  );
3324
+ if ("deliveryMethod" in order) {
3325
+ enumValue(
3326
+ order.source,
3327
+ ["web", "app", "manual", "api", "import", "in_person"],
3328
+ resource,
3329
+ `${path}.source`
3330
+ );
3331
+ if (order.deliveryMethod === "shipping") {
3332
+ if (order.pickup !== null)
3333
+ fail(resource, `${path}.pickup`, "null for shipping");
3334
+ } else {
3335
+ const pickup = record(order.pickup, resource, `${path}.pickup`);
3336
+ exact(
3337
+ pickup,
3338
+ ["status", "readyAt", "pickedUpAt"],
3339
+ [],
3340
+ resource,
3341
+ `${path}.pickup`
3342
+ );
3343
+ enumValue(
3344
+ pickup.status,
3345
+ ["pending", "ready_for_pickup", "picked_up", "canceled"],
3346
+ resource,
3347
+ `${path}.pickup.status`
3348
+ );
3349
+ for (const key of ["readyAt", "pickedUpAt"]) {
3350
+ if (pickup[key] !== null)
3351
+ timestamp(pickup[key], resource, `${path}.pickup.${key}`);
3352
+ }
3353
+ }
3354
+ }
3115
3355
  string(order.id, resource, `${path}.id`);
3116
3356
  string(order.orderNumber, resource, `${path}.orderNumber`);
3117
3357
  const amounts = record(order.amounts, resource, `${path}.amounts`);
@@ -3432,6 +3672,17 @@ function validateCheckoutCore(value, resource, list, server) {
3432
3672
  "$.status"
3433
3673
  );
3434
3674
  const keys = checkoutVariantKeys(status, checkout.placedVia);
3675
+ keys.required.push(
3676
+ ...responseExtensionKeys(
3677
+ checkout,
3678
+ ["deliveryMethod", "source"],
3679
+ resource,
3680
+ "$"
3681
+ )
3682
+ );
3683
+ if ("deliveryMethod" in checkout)
3684
+ enumValue(checkout.source, ["web", "in_person"], resource, "$.source");
3685
+ keys.optional.push("funding");
3435
3686
  if (list) {
3436
3687
  keys.required = keys.required.filter(
3437
3688
  (key) => !["items", "shippingAddress", "attributes"].includes(key)
@@ -3443,6 +3694,33 @@ function validateCheckoutCore(value, resource, list, server) {
3443
3694
  exact(checkout, keys.required, keys.optional, resource, "$");
3444
3695
  string(checkout.id, resource, "$.id");
3445
3696
  validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
3697
+ if (Object.prototype.hasOwnProperty.call(checkout, "funding")) {
3698
+ const funding = record(checkout.funding, resource, "$.funding");
3699
+ exact(
3700
+ funding,
3701
+ ["creditAmount", "providerPayableAmount"],
3702
+ [],
3703
+ resource,
3704
+ "$.funding"
3705
+ );
3706
+ const credit = safeMinor(
3707
+ funding.creditAmount,
3708
+ resource,
3709
+ "$.funding.creditAmount"
3710
+ );
3711
+ const provider = safeMinor(
3712
+ funding.providerPayableAmount,
3713
+ resource,
3714
+ "$.funding.providerPayableAmount"
3715
+ );
3716
+ const amounts = checkout.amounts;
3717
+ if (BigInt(credit) + BigInt(provider) !== BigInt(amounts.totalMinor) || credit > 0 && amounts.currency !== "KRW")
3718
+ fail(
3719
+ resource,
3720
+ "$.funding",
3721
+ "exact purchase total split; positive credits require KRW"
3722
+ );
3723
+ }
3446
3724
  if (!list) {
3447
3725
  const items = array(checkout.items, resource, "$.items");
3448
3726
  if (items.length === 0) fail(resource, "$.items", "non-empty array");
@@ -3601,10 +3879,10 @@ function validateCheckoutQueryResult(value) {
3601
3879
  return value;
3602
3880
  }
3603
3881
  function validateMoney(value, resource, path) {
3604
- const money = record(value, resource, path);
3605
- exact(money, ["amountMinor", "currency"], [], resource, path);
3606
- safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3607
- currency(money.currency, resource, `${path}.currency`);
3882
+ const money2 = record(value, resource, path);
3883
+ exact(money2, ["amountMinor", "currency"], [], resource, path);
3884
+ safeMinor(money2.amountMinor, resource, `${path}.amountMinor`);
3885
+ currency(money2.currency, resource, `${path}.currency`);
3608
3886
  }
3609
3887
  function validateCaptureEvidence(value, resource, path) {
3610
3888
  const evidence = record(value, resource, path);
@@ -3640,6 +3918,65 @@ function validateRequiredReconciliation(value, allowed, resource, path) {
3640
3918
  }
3641
3919
  function validateNextAction(value, provider, resource, path) {
3642
3920
  const action = record(value, resource, path);
3921
+ if (provider === "stripe") {
3922
+ exact(
3923
+ action,
3924
+ ["type", "clientSecret", "publishableKey", "returnUrl"],
3925
+ [],
3926
+ resource,
3927
+ path
3928
+ );
3929
+ if (action.type !== "stripe_payment_element")
3930
+ fail(resource, `${path}.type`, "stripe_payment_element");
3931
+ const clientSecret = boundedString(
3932
+ action.clientSecret,
3933
+ 255,
3934
+ resource,
3935
+ `${path}.clientSecret`
3936
+ );
3937
+ if (!/^pi_[A-Za-z0-9]+_secret_[A-Za-z0-9]+$/.test(clientSecret)) {
3938
+ fail(
3939
+ resource,
3940
+ `${path}.clientSecret`,
3941
+ "Stripe PaymentIntent client secret"
3942
+ );
3943
+ }
3944
+ const publishableKey = boundedString(
3945
+ action.publishableKey,
3946
+ 255,
3947
+ resource,
3948
+ `${path}.publishableKey`
3949
+ );
3950
+ if (!/^pk_(?:test|live)_[A-Za-z0-9]+$/.test(publishableKey)) {
3951
+ fail(resource, `${path}.publishableKey`, "Stripe publishable key");
3952
+ }
3953
+ const returnUrl = boundedString(
3954
+ action.returnUrl,
3955
+ 2048,
3956
+ resource,
3957
+ `${path}.returnUrl`
3958
+ );
3959
+ if (!STRIPE_RETURN_URL_RAW_CHARACTERS.test(returnUrl) || !STRIPE_RETURN_URL_AUTHORITY.test(returnUrl)) {
3960
+ fail(
3961
+ resource,
3962
+ `${path}.returnUrl`,
3963
+ "HTTPS or loopback URL without embedded credentials"
3964
+ );
3965
+ }
3966
+ try {
3967
+ const parsed = new URL(returnUrl);
3968
+ const loopback = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
3969
+ if (!loopback && parsed.protocol !== "https:" || parsed.username || parsed.password)
3970
+ throw new Error("unsafe return URL");
3971
+ } catch {
3972
+ fail(
3973
+ resource,
3974
+ `${path}.returnUrl`,
3975
+ "HTTPS or loopback URL without embedded credentials"
3976
+ );
3977
+ }
3978
+ return;
3979
+ }
3643
3980
  if (provider === "portone") {
3644
3981
  if (action.type === "portone_sdk") {
3645
3982
  const hasCancelable = "cancelable" in action;
@@ -4015,7 +4352,7 @@ function validatePublicPaymentSession(value, expectedProvider, operation2) {
4015
4352
  );
4016
4353
  }
4017
4354
  if (expectedProvider !== void 0 && provider !== expectedProvider) {
4018
- if (operation2 === "cancel" && status !== "canceling" && status !== "canceled") {
4355
+ if (operation2 === "cancel" && CANCEL_RECOVERY_METHODS[provider] !== null && status !== "canceling" && status !== "canceled") {
4019
4356
  fail(
4020
4357
  resource,
4021
4358
  "$.providerStatus",
@@ -4907,8 +5244,9 @@ var CheckoutApi = class extends CustomerScopedApi {
4907
5244
  }
4908
5245
  post(endpoint, body, idempotencyKey) {
4909
5246
  return this.requestEndpoint(endpoint, body, {
4910
- ...idempotencyKey && {
4911
- headers: { "X-Idempotency-Key": idempotencyKey }
5247
+ headers: {
5248
+ Accept: CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE,
5249
+ ...idempotencyKey && { "X-Idempotency-Key": idempotencyKey }
4912
5250
  }
4913
5251
  });
4914
5252
  }
@@ -4918,34 +5256,58 @@ var CheckoutApi = class extends CustomerScopedApi {
4918
5256
  async serverCheckout(result) {
4919
5257
  return validateServerCheckout(await result);
4920
5258
  }
4921
- async createResult(result) {
4922
- return validateCreateCheckoutResult(
5259
+ async createResult(result, creditAmount) {
5260
+ const parsed = validateCreateCheckoutResult(
4923
5261
  await result,
4924
5262
  false
4925
5263
  );
5264
+ this.assertRequestedCredit(parsed.checkout, creditAmount);
5265
+ return parsed;
4926
5266
  }
4927
- async createServerResult(result) {
4928
- return validateCreateCheckoutResult(
5267
+ async createServerResult(result, creditAmount) {
5268
+ const parsed = validateCreateCheckoutResult(
4929
5269
  await result,
4930
5270
  true
4931
5271
  );
5272
+ this.assertRequestedCredit(parsed.checkout, creditAmount);
5273
+ return parsed;
5274
+ }
5275
+ assertCreditInput(amount) {
5276
+ if (amount !== void 0 && (!Number.isSafeInteger(amount) || amount <= 0))
5277
+ throw createValidationError(
5278
+ "creditAmount must be a positive safe integer."
5279
+ );
5280
+ }
5281
+ assertRequestedCredit(checkout, requested) {
5282
+ if (requested !== void 0 && checkout.funding?.creditAmount !== requested)
5283
+ throw createApiError(
5284
+ "Credit funding was not confirmed by the server.",
5285
+ 502,
5286
+ { resource: "Checkout", path: "$.funding" },
5287
+ "The response does not confirm the requested credit funding.",
5288
+ "Retry the same create with the original idempotency key and credit amount, or retrieve the Checkout; never retry without credit."
5289
+ );
4932
5290
  }
4933
5291
  create(params) {
4934
5292
  const { idempotencyKey, ...body } = params;
4935
5293
  assertCommerceIdempotencyKey(idempotencyKey);
5294
+ this.assertCreditInput(body.creditAmount);
4936
5295
  return this.createResult(
4937
- this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
5296
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey),
5297
+ body.creditAmount
4938
5298
  );
4939
5299
  }
4940
5300
  createServer(params) {
4941
5301
  const { idempotencyKey, ...body } = params;
4942
5302
  assertCommerceIdempotencyKey(idempotencyKey);
5303
+ this.assertCreditInput(body.creditAmount);
4943
5304
  return this.createServerResult(
4944
5305
  this.post(
4945
5306
  COMMERCE_ENDPOINTS.checkouts.server.create,
4946
5307
  body,
4947
5308
  idempotencyKey
4948
- )
5309
+ ),
5310
+ body.creditAmount
4949
5311
  );
4950
5312
  }
4951
5313
  retrieve(params) {
@@ -6607,6 +6969,13 @@ var Client = class _Client {
6607
6969
  this.markets = new MarketDiscovery(
6608
6970
  (options2) => this.collections.from("markets").find(options2)
6609
6971
  );
6972
+ this.credits = new CustomerCreditsApi("CustomerCreditsApi", {
6973
+ publishableKey: this.config.publishableKey,
6974
+ apiUrl: this.config.apiUrl,
6975
+ customerToken: () => this.customer.auth.getToken(),
6976
+ onUnauthorized,
6977
+ onRequestId
6978
+ });
6610
6979
  this.benefitVouchers = new CustomerBenefitVouchersApi(
6611
6980
  "CustomerBenefitVouchersApi",
6612
6981
  {
@@ -6637,7 +7006,8 @@ var Client = class _Client {
6637
7006
  ...this.config,
6638
7007
  customer: this.config.customer?.persist === false ? {
6639
7008
  ...this.config.customer,
6640
- token: this.customer.auth.getToken() ?? void 0
7009
+ token: this.customer.auth.getToken() ?? void 0,
7010
+ refreshToken: this.customer.auth.getRefreshToken() ?? void 0
6641
7011
  } : this.config.customer,
6642
7012
  market
6643
7013
  });