@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/index.cjs CHANGED
@@ -228,6 +228,7 @@ var COMMERCE_ERROR_CODES = [
228
228
  "cart_not_active",
229
229
  "cart_locked",
230
230
  "cart_empty",
231
+ "shipping_address_required",
231
232
  "cart_market_unavailable",
232
233
  "cart_market_mismatch",
233
234
  "checkout_not_open",
@@ -244,6 +245,7 @@ var COMMERCE_ERROR_CODES = [
244
245
  "price_changed",
245
246
  "pricing_fact_in_use",
246
247
  "insufficient_stock",
248
+ "credit_insufficient",
247
249
  "reservation_conflict",
248
250
  "stock_lock_unavailable",
249
251
  "variant_not_found",
@@ -707,6 +709,8 @@ async function parseErrorBody(response) {
707
709
  try {
708
710
  const body = await response.json();
709
711
  const reason = typeof body.reason === "string" ? body.reason : typeof body.code === "string" ? body.code : void 0;
712
+ const payloadErrorReason = Array.isArray(body.errors) ? readPayloadErrorReason(body.errors) : void 0;
713
+ const payloadReasonField = payloadErrorReason !== void 0 ? { payloadErrorReason } : {};
710
714
  if (body.errors && Array.isArray(body.errors)) {
711
715
  const fieldErrors = [];
712
716
  for (const e of body.errors) {
@@ -729,6 +733,7 @@ async function parseErrorBody(response) {
729
733
  errorMessage: `HTTP ${response.status}: ${details}`,
730
734
  userMessage: details,
731
735
  reason,
736
+ ...payloadReasonField,
732
737
  body,
733
738
  errors: fieldErrors.length > 0 ? fieldErrors : body.errors
734
739
  };
@@ -739,6 +744,7 @@ async function parseErrorBody(response) {
739
744
  errorMessage: `HTTP ${response.status}: ${body.error}`,
740
745
  userMessage: body.error,
741
746
  reason,
747
+ ...payloadReasonField,
742
748
  body
743
749
  };
744
750
  }
@@ -747,14 +753,23 @@ async function parseErrorBody(response) {
747
753
  errorMessage: `HTTP ${response.status}: ${body.message}`,
748
754
  userMessage: body.message,
749
755
  reason,
756
+ ...payloadReasonField,
750
757
  body
751
758
  };
752
759
  }
753
- return { ...fallback, reason, body };
760
+ return { ...fallback, reason, ...payloadReasonField, body };
754
761
  } catch {
755
762
  return fallback;
756
763
  }
757
764
  }
765
+ function readPayloadErrorReason(errors) {
766
+ const data = errors[0]?.data;
767
+ if (!data || typeof data !== "object") return void 0;
768
+ const { reason, code } = data;
769
+ if (typeof reason === "string") return reason;
770
+ if (typeof code === "string") return code;
771
+ return void 0;
772
+ }
758
773
  function getParsedErrorSuggestion(status, parsed) {
759
774
  if (status === 403 && parsed.reason === "origin_not_allowed") {
760
775
  return "Add the request origin to the tenant Browser API origins, then retry the browser request.";
@@ -800,7 +815,10 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, cano
800
815
  if (retryAfter !== void 0) {
801
816
  Object.assign(withRequestId, { retryAfter });
802
817
  }
803
- return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
818
+ return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(
819
+ withRequestId,
820
+ parsed.reason ?? parsed.payloadErrorReason
821
+ );
804
822
  };
805
823
  if (status === 400 || status === 422) {
806
824
  return finalize(
@@ -1219,6 +1237,7 @@ async function parseApiResponse(response, endpoint, options = {}) {
1219
1237
  // ../../internal/http-contracts/src/index.ts
1220
1238
  var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1221
1239
  var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
1240
+ var CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE = "application/vnd.01software.credit-funding.v1+json";
1222
1241
  var operation = (collection, method, path, errorFamily) => Object.freeze({
1223
1242
  [operationBrand]: true,
1224
1243
  collection,
@@ -1382,6 +1401,11 @@ var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
1382
1401
  ]);
1383
1402
  var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1384
1403
  subscribe: operation(null, "post", "/memberships/subscribe"),
1404
+ endSubscribeIntent: operation(
1405
+ null,
1406
+ "post",
1407
+ "/memberships/subscribe-intent/end"
1408
+ ),
1385
1409
  billingCustody: operation(null, "post", "/memberships/billing-custody"),
1386
1410
  cancel: operation(null, "post", "/memberships/:id/cancel"),
1387
1411
  me: operation(null, "get", "/memberships/me"),
@@ -1427,6 +1451,19 @@ var BENEFIT_VOUCHER_ENDPOINT_OPERATIONS = {
1427
1451
  void: operation("customers", "post", "/benefit-vouchers/void"),
1428
1452
  listMine: operation("customers", "get", "/me/benefit-vouchers")
1429
1453
  };
1454
+ var CUSTOMER_CREDIT_ENDPOINT_OPERATIONS = {
1455
+ grant: strictCommerceOperation("customers", "post", "/credits/grant"),
1456
+ getGrant: strictCommerceOperation("customers", "post", "/credits/get-grant"),
1457
+ getAccount: strictCommerceOperation("customers", "post", "/credits/account"),
1458
+ revoke: strictCommerceOperation("customers", "post", "/credits/revoke"),
1459
+ mine: strictCommerceOperation("customers", "get", "/me/credits"),
1460
+ history: strictCommerceOperation("customers", "get", "/me/credits/history"),
1461
+ configure: strictCommerceOperation(
1462
+ "customers",
1463
+ "post",
1464
+ "/credits/configuration"
1465
+ )
1466
+ };
1430
1467
  var CUSTOMER_GROUP_ENDPOINT_OPERATIONS = {
1431
1468
  members: operation("customer-groups", "get", "/:id/members"),
1432
1469
  grant: operation("customer-groups", "post", "/:id/members/grant"),
@@ -1816,6 +1853,140 @@ var CustomerBenefitVouchersApi = class extends CustomerScopedApi {
1816
1853
  }
1817
1854
  };
1818
1855
 
1856
+ // src/core/api/customer-credit-types.ts
1857
+ function invalid() {
1858
+ throw createApiError("Invalid customer credit response", 502);
1859
+ }
1860
+ function object2(value, keys) {
1861
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(value, key)))
1862
+ invalid();
1863
+ return value;
1864
+ }
1865
+ function money(value) {
1866
+ return typeof value === "string" && /^(0|[1-9][0-9]*)$/.test(value);
1867
+ }
1868
+ function uuid2(value) {
1869
+ 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(
1870
+ value
1871
+ );
1872
+ }
1873
+ function time2(value) {
1874
+ if (typeof value !== "string") return false;
1875
+ const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
1876
+ if (!match) return false;
1877
+ const [, year, month, day, hour, minute, second = "0"] = match;
1878
+ const y = Number(year), m = Number(month), d = Number(day);
1879
+ const days = [
1880
+ 31,
1881
+ y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 29 : 28,
1882
+ 31,
1883
+ 30,
1884
+ 31,
1885
+ 30,
1886
+ 31,
1887
+ 31,
1888
+ 30,
1889
+ 31,
1890
+ 30,
1891
+ 31
1892
+ ];
1893
+ return m >= 1 && m <= 12 && d >= 1 && d <= days[m - 1] && Number(hour) < 24 && Number(minute) < 60 && Number(second) < 60;
1894
+ }
1895
+ var states = ["available", "held", "spent", "expired", "revoked"];
1896
+ function balances(value) {
1897
+ const data = object2(value, states);
1898
+ if (states.some((key) => !money(data[key]))) invalid();
1899
+ }
1900
+ function page(value) {
1901
+ if (value.currency !== "KRW" || !time2(value.evaluatedAt) || !Number.isSafeInteger(value.page) || value.page < 1 || typeof value.hasNextPage !== "boolean")
1902
+ invalid();
1903
+ }
1904
+ function parseMyCustomerCredits(value) {
1905
+ const data = object2(value, [
1906
+ "currency",
1907
+ "evaluatedAt",
1908
+ "granted",
1909
+ "balances",
1910
+ "buckets",
1911
+ "page",
1912
+ "hasNextPage"
1913
+ ]);
1914
+ page(data);
1915
+ balances(data.balances);
1916
+ if (!money(data.granted) || !Array.isArray(data.buckets) || data.buckets.length > 50)
1917
+ invalid();
1918
+ for (const value2 of data.buckets) {
1919
+ const bucket = object2(value2, [
1920
+ "id",
1921
+ "grantId",
1922
+ "kind",
1923
+ "grantedAt",
1924
+ "expiresAt",
1925
+ "isRevoked",
1926
+ "balances"
1927
+ ]);
1928
+ if (!uuid2(bucket.id) || !uuid2(bucket.grantId) || !["original", "grace"].includes(bucket.kind) || !time2(bucket.grantedAt) || !time2(bucket.expiresAt) || typeof bucket.isRevoked !== "boolean")
1929
+ invalid();
1930
+ balances(bucket.balances);
1931
+ }
1932
+ return value;
1933
+ }
1934
+ function parseMyCustomerCreditHistory(value) {
1935
+ const data = object2(value, [
1936
+ "currency",
1937
+ "evaluatedAt",
1938
+ "entries",
1939
+ "page",
1940
+ "hasNextPage"
1941
+ ]);
1942
+ page(data);
1943
+ if (!Array.isArray(data.entries) || data.entries.length > 50) invalid();
1944
+ for (const value2 of data.entries) {
1945
+ const entry = object2(value2, [
1946
+ "id",
1947
+ "grantId",
1948
+ "kind",
1949
+ "amount",
1950
+ "fromState",
1951
+ "toState",
1952
+ "createdAt"
1953
+ ]);
1954
+ if (!uuid2(entry.id) || !uuid2(entry.grantId) || !money(entry.amount) || !time2(entry.createdAt) || ![
1955
+ "grant",
1956
+ "reserve",
1957
+ "consume",
1958
+ "release",
1959
+ "restore",
1960
+ "expire",
1961
+ "revoke"
1962
+ ].includes(entry.kind) || entry.fromState !== null && !states.includes(entry.fromState) || entry.toState !== null && !states.includes(entry.toState))
1963
+ invalid();
1964
+ }
1965
+ return value;
1966
+ }
1967
+
1968
+ // src/core/api/customer-credits-api.ts
1969
+ var CustomerCreditsApi = class extends CustomerScopedApi {
1970
+ async mine(params = {}) {
1971
+ const query = new URLSearchParams();
1972
+ if (params.page !== void 0) query.set("page", String(params.page));
1973
+ return parseMyCustomerCredits(
1974
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.mine, void 0, {
1975
+ query
1976
+ })
1977
+ );
1978
+ }
1979
+ async history(params = {}) {
1980
+ const query = new URLSearchParams();
1981
+ if (params.page !== void 0) query.set("page", String(params.page));
1982
+ return parseMyCustomerCreditHistory(
1983
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.history, void 0, {
1984
+ query
1985
+ })
1986
+ );
1987
+ }
1988
+ };
1989
+
1819
1990
  // src/core/collection/http-client.ts
1820
1991
  var import_qs_esm = require("qs-esm");
1821
1992
  function validateWhere(where) {
@@ -2273,11 +2444,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
2273
2444
  * - `rootComment`: comments belonging to a thread rooted at that comment.
2274
2445
  */
2275
2446
  listComments(params) {
2276
- const { postId, page, limit, rootComment, topLevelOnly, sort } = params;
2447
+ const { postId, page: page2, limit, rootComment, topLevelOnly, sort } = params;
2277
2448
  return this.execute(
2278
2449
  this.buildCommentsListQuery({
2279
2450
  postId,
2280
- page,
2451
+ page: page2,
2281
2452
  limit,
2282
2453
  rootComment,
2283
2454
  topLevelOnly,
@@ -2288,11 +2459,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
2288
2459
  }
2289
2460
  /** Direct replies to a comment (`where[parent][equals]`). */
2290
2461
  listReplies(params) {
2291
- const { commentId, page, limit, sort } = params;
2462
+ const { commentId, page: page2, limit, sort } = params;
2292
2463
  return this.execute(
2293
2464
  this.buildCommentsListQuery({
2294
2465
  parentId: commentId,
2295
- page,
2466
+ page: page2,
2296
2467
  limit,
2297
2468
  sort
2298
2469
  }),
@@ -2549,7 +2720,18 @@ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2549
2720
  function managedPaymentProviders(providers) {
2550
2721
  return providers;
2551
2722
  }
2552
- var PAYMENT_PROVIDERS = managedPaymentProviders(["toss", "portone"]);
2723
+ var PAYMENT_PROVIDERS = managedPaymentProviders([
2724
+ "toss",
2725
+ "portone",
2726
+ "stripe"
2727
+ ]);
2728
+ var CANCEL_RECOVERY_METHODS = {
2729
+ toss: "cancel()",
2730
+ portone: "cancelPortOne()",
2731
+ stripe: null
2732
+ };
2733
+ var STRIPE_RETURN_URL_RAW_CHARACTERS = /^[^\s\u0000-\u001F\u007F\\]+$/;
2734
+ var STRIPE_RETURN_URL_AUTHORITY = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+(?:[/?#]|$)/;
2553
2735
  var PAYMENT_PROVIDER_STATUSES = [
2554
2736
  "requires_payment_method",
2555
2737
  "requires_action",
@@ -2598,11 +2780,8 @@ function fail(resource, path, expected) {
2598
2780
  invalidCanonicalResponse(resource, { path, expected });
2599
2781
  }
2600
2782
  function providerMismatch(resource, expected, actual, operation2) {
2601
- if (operation2 === "cancel") {
2602
- const method = {
2603
- toss: "cancel()",
2604
- portone: "cancelPortOne()"
2605
- }[actual];
2783
+ const method = CANCEL_RECOVERY_METHODS[actual];
2784
+ if (operation2 === "cancel" && method !== null) {
2606
2785
  throw createApiError(
2607
2786
  `Canonical ${resource} response provider mismatch: expected ${expected}, received ${actual}.`,
2608
2787
  502,
@@ -2631,6 +2810,17 @@ function exact(value, required, optional, resource, path) {
2631
2810
  const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2632
2811
  if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2633
2812
  }
2813
+ function responseExtensionKeys(value, keys, resource, path) {
2814
+ if (!keys.some((key) => Object.prototype.hasOwnProperty.call(value, key)))
2815
+ return [];
2816
+ enumValue(
2817
+ value.deliveryMethod,
2818
+ ["shipping", "pickup"],
2819
+ resource,
2820
+ `${path}.deliveryMethod`
2821
+ );
2822
+ return [...keys];
2823
+ }
2634
2824
  function string(value, resource, path) {
2635
2825
  if (typeof value !== "string" || value.length === 0) {
2636
2826
  fail(resource, path, "non-empty string");
@@ -2970,6 +3160,12 @@ function validatePublicCart(value, resource = "Cart") {
2970
3160
  exact(
2971
3161
  cart,
2972
3162
  [
3163
+ ...responseExtensionKeys(
3164
+ cart,
3165
+ ["deliveryMethod", "shippingMinor", "totalMinor"],
3166
+ resource,
3167
+ "$"
3168
+ ),
2973
3169
  "id",
2974
3170
  "status",
2975
3171
  "revision",
@@ -3040,6 +3236,13 @@ function validatePublicCart(value, resource = "Cart") {
3040
3236
  if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
3041
3237
  fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
3042
3238
  }
3239
+ if ("deliveryMethod" in cart) {
3240
+ const shipping = safeMinor(cart.shippingMinor, resource, "$.shippingMinor");
3241
+ const total = safeMinor(cart.totalMinor, resource, "$.totalMinor");
3242
+ if (BigInt(total) !== BigInt(estimatedTotal) + BigInt(shipping)) {
3243
+ fail(resource, "$.totalMinor", "estimatedTotalMinor + shippingMinor");
3244
+ }
3245
+ }
3043
3246
  timestamp(cart.expiresAt, resource, "$.expiresAt");
3044
3247
  timestamp(cart.createdAt, resource, "$.createdAt");
3045
3248
  timestamp(cart.updatedAt, resource, "$.updatedAt");
@@ -3198,6 +3401,12 @@ function validatePublicOrderAt(value, resource, path) {
3198
3401
  exact(
3199
3402
  order,
3200
3403
  [
3404
+ ...responseExtensionKeys(
3405
+ order,
3406
+ ["deliveryMethod", "pickup", "source"],
3407
+ resource,
3408
+ path
3409
+ ),
3201
3410
  "id",
3202
3411
  "orderNumber",
3203
3412
  "amounts",
@@ -3219,6 +3428,37 @@ function validatePublicOrderAt(value, resource, path) {
3219
3428
  resource,
3220
3429
  path
3221
3430
  );
3431
+ if ("deliveryMethod" in order) {
3432
+ enumValue(
3433
+ order.source,
3434
+ ["web", "app", "manual", "api", "import", "in_person"],
3435
+ resource,
3436
+ `${path}.source`
3437
+ );
3438
+ if (order.deliveryMethod === "shipping") {
3439
+ if (order.pickup !== null)
3440
+ fail(resource, `${path}.pickup`, "null for shipping");
3441
+ } else {
3442
+ const pickup = record(order.pickup, resource, `${path}.pickup`);
3443
+ exact(
3444
+ pickup,
3445
+ ["status", "readyAt", "pickedUpAt"],
3446
+ [],
3447
+ resource,
3448
+ `${path}.pickup`
3449
+ );
3450
+ enumValue(
3451
+ pickup.status,
3452
+ ["pending", "ready_for_pickup", "picked_up", "canceled"],
3453
+ resource,
3454
+ `${path}.pickup.status`
3455
+ );
3456
+ for (const key of ["readyAt", "pickedUpAt"]) {
3457
+ if (pickup[key] !== null)
3458
+ timestamp(pickup[key], resource, `${path}.pickup.${key}`);
3459
+ }
3460
+ }
3461
+ }
3222
3462
  string(order.id, resource, `${path}.id`);
3223
3463
  string(order.orderNumber, resource, `${path}.orderNumber`);
3224
3464
  const amounts = record(order.amounts, resource, `${path}.amounts`);
@@ -3539,6 +3779,17 @@ function validateCheckoutCore(value, resource, list, server) {
3539
3779
  "$.status"
3540
3780
  );
3541
3781
  const keys = checkoutVariantKeys(status, checkout.placedVia);
3782
+ keys.required.push(
3783
+ ...responseExtensionKeys(
3784
+ checkout,
3785
+ ["deliveryMethod", "source"],
3786
+ resource,
3787
+ "$"
3788
+ )
3789
+ );
3790
+ if ("deliveryMethod" in checkout)
3791
+ enumValue(checkout.source, ["web", "in_person"], resource, "$.source");
3792
+ keys.optional.push("funding");
3542
3793
  if (list) {
3543
3794
  keys.required = keys.required.filter(
3544
3795
  (key) => !["items", "shippingAddress", "attributes"].includes(key)
@@ -3550,6 +3801,33 @@ function validateCheckoutCore(value, resource, list, server) {
3550
3801
  exact(checkout, keys.required, keys.optional, resource, "$");
3551
3802
  string(checkout.id, resource, "$.id");
3552
3803
  validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
3804
+ if (Object.prototype.hasOwnProperty.call(checkout, "funding")) {
3805
+ const funding = record(checkout.funding, resource, "$.funding");
3806
+ exact(
3807
+ funding,
3808
+ ["creditAmount", "providerPayableAmount"],
3809
+ [],
3810
+ resource,
3811
+ "$.funding"
3812
+ );
3813
+ const credit = safeMinor(
3814
+ funding.creditAmount,
3815
+ resource,
3816
+ "$.funding.creditAmount"
3817
+ );
3818
+ const provider = safeMinor(
3819
+ funding.providerPayableAmount,
3820
+ resource,
3821
+ "$.funding.providerPayableAmount"
3822
+ );
3823
+ const amounts = checkout.amounts;
3824
+ if (BigInt(credit) + BigInt(provider) !== BigInt(amounts.totalMinor) || credit > 0 && amounts.currency !== "KRW")
3825
+ fail(
3826
+ resource,
3827
+ "$.funding",
3828
+ "exact purchase total split; positive credits require KRW"
3829
+ );
3830
+ }
3553
3831
  if (!list) {
3554
3832
  const items = array(checkout.items, resource, "$.items");
3555
3833
  if (items.length === 0) fail(resource, "$.items", "non-empty array");
@@ -3708,10 +3986,10 @@ function validateCheckoutQueryResult(value) {
3708
3986
  return value;
3709
3987
  }
3710
3988
  function validateMoney(value, resource, path) {
3711
- const money = record(value, resource, path);
3712
- exact(money, ["amountMinor", "currency"], [], resource, path);
3713
- safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3714
- currency(money.currency, resource, `${path}.currency`);
3989
+ const money2 = record(value, resource, path);
3990
+ exact(money2, ["amountMinor", "currency"], [], resource, path);
3991
+ safeMinor(money2.amountMinor, resource, `${path}.amountMinor`);
3992
+ currency(money2.currency, resource, `${path}.currency`);
3715
3993
  }
3716
3994
  function validateCaptureEvidence(value, resource, path) {
3717
3995
  const evidence = record(value, resource, path);
@@ -3747,6 +4025,65 @@ function validateRequiredReconciliation(value, allowed, resource, path) {
3747
4025
  }
3748
4026
  function validateNextAction(value, provider, resource, path) {
3749
4027
  const action = record(value, resource, path);
4028
+ if (provider === "stripe") {
4029
+ exact(
4030
+ action,
4031
+ ["type", "clientSecret", "publishableKey", "returnUrl"],
4032
+ [],
4033
+ resource,
4034
+ path
4035
+ );
4036
+ if (action.type !== "stripe_payment_element")
4037
+ fail(resource, `${path}.type`, "stripe_payment_element");
4038
+ const clientSecret = boundedString(
4039
+ action.clientSecret,
4040
+ 255,
4041
+ resource,
4042
+ `${path}.clientSecret`
4043
+ );
4044
+ if (!/^pi_[A-Za-z0-9]+_secret_[A-Za-z0-9]+$/.test(clientSecret)) {
4045
+ fail(
4046
+ resource,
4047
+ `${path}.clientSecret`,
4048
+ "Stripe PaymentIntent client secret"
4049
+ );
4050
+ }
4051
+ const publishableKey = boundedString(
4052
+ action.publishableKey,
4053
+ 255,
4054
+ resource,
4055
+ `${path}.publishableKey`
4056
+ );
4057
+ if (!/^pk_(?:test|live)_[A-Za-z0-9]+$/.test(publishableKey)) {
4058
+ fail(resource, `${path}.publishableKey`, "Stripe publishable key");
4059
+ }
4060
+ const returnUrl = boundedString(
4061
+ action.returnUrl,
4062
+ 2048,
4063
+ resource,
4064
+ `${path}.returnUrl`
4065
+ );
4066
+ if (!STRIPE_RETURN_URL_RAW_CHARACTERS.test(returnUrl) || !STRIPE_RETURN_URL_AUTHORITY.test(returnUrl)) {
4067
+ fail(
4068
+ resource,
4069
+ `${path}.returnUrl`,
4070
+ "HTTPS or loopback URL without embedded credentials"
4071
+ );
4072
+ }
4073
+ try {
4074
+ const parsed = new URL(returnUrl);
4075
+ const loopback = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
4076
+ if (!loopback && parsed.protocol !== "https:" || parsed.username || parsed.password)
4077
+ throw new Error("unsafe return URL");
4078
+ } catch {
4079
+ fail(
4080
+ resource,
4081
+ `${path}.returnUrl`,
4082
+ "HTTPS or loopback URL without embedded credentials"
4083
+ );
4084
+ }
4085
+ return;
4086
+ }
3750
4087
  if (provider === "portone") {
3751
4088
  if (action.type === "portone_sdk") {
3752
4089
  const hasCancelable = "cancelable" in action;
@@ -4122,7 +4459,7 @@ function validatePublicPaymentSession(value, expectedProvider, operation2) {
4122
4459
  );
4123
4460
  }
4124
4461
  if (expectedProvider !== void 0 && provider !== expectedProvider) {
4125
- if (operation2 === "cancel" && status !== "canceling" && status !== "canceled") {
4462
+ if (operation2 === "cancel" && CANCEL_RECOVERY_METHODS[provider] !== null && status !== "canceling" && status !== "canceled") {
4126
4463
  fail(
4127
4464
  resource,
4128
4465
  "$.providerStatus",
@@ -5018,8 +5355,9 @@ var CheckoutApi = class extends CustomerScopedApi {
5018
5355
  }
5019
5356
  post(endpoint, body, idempotencyKey) {
5020
5357
  return this.requestEndpoint(endpoint, body, {
5021
- ...idempotencyKey && {
5022
- headers: { "X-Idempotency-Key": idempotencyKey }
5358
+ headers: {
5359
+ Accept: CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE,
5360
+ ...idempotencyKey && { "X-Idempotency-Key": idempotencyKey }
5023
5361
  }
5024
5362
  });
5025
5363
  }
@@ -5029,34 +5367,58 @@ var CheckoutApi = class extends CustomerScopedApi {
5029
5367
  async serverCheckout(result) {
5030
5368
  return validateServerCheckout(await result);
5031
5369
  }
5032
- async createResult(result) {
5033
- return validateCreateCheckoutResult(
5370
+ async createResult(result, creditAmount) {
5371
+ const parsed = validateCreateCheckoutResult(
5034
5372
  await result,
5035
5373
  false
5036
5374
  );
5375
+ this.assertRequestedCredit(parsed.checkout, creditAmount);
5376
+ return parsed;
5037
5377
  }
5038
- async createServerResult(result) {
5039
- return validateCreateCheckoutResult(
5378
+ async createServerResult(result, creditAmount) {
5379
+ const parsed = validateCreateCheckoutResult(
5040
5380
  await result,
5041
5381
  true
5042
5382
  );
5383
+ this.assertRequestedCredit(parsed.checkout, creditAmount);
5384
+ return parsed;
5385
+ }
5386
+ assertCreditInput(amount) {
5387
+ if (amount !== void 0 && (!Number.isSafeInteger(amount) || amount <= 0))
5388
+ throw createValidationError(
5389
+ "creditAmount must be a positive safe integer."
5390
+ );
5391
+ }
5392
+ assertRequestedCredit(checkout, requested) {
5393
+ if (requested !== void 0 && checkout.funding?.creditAmount !== requested)
5394
+ throw createApiError(
5395
+ "Credit funding was not confirmed by the server.",
5396
+ 502,
5397
+ { resource: "Checkout", path: "$.funding" },
5398
+ "The response does not confirm the requested credit funding.",
5399
+ "Retry the same create with the original idempotency key and credit amount, or retrieve the Checkout; never retry without credit."
5400
+ );
5043
5401
  }
5044
5402
  create(params) {
5045
5403
  const { idempotencyKey, ...body } = params;
5046
5404
  assertCommerceIdempotencyKey(idempotencyKey);
5405
+ this.assertCreditInput(body.creditAmount);
5047
5406
  return this.createResult(
5048
- this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
5407
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey),
5408
+ body.creditAmount
5049
5409
  );
5050
5410
  }
5051
5411
  createServer(params) {
5052
5412
  const { idempotencyKey, ...body } = params;
5053
5413
  assertCommerceIdempotencyKey(idempotencyKey);
5414
+ this.assertCreditInput(body.creditAmount);
5054
5415
  return this.createServerResult(
5055
5416
  this.post(
5056
5417
  COMMERCE_ENDPOINTS.checkouts.server.create,
5057
5418
  body,
5058
5419
  idempotencyKey
5059
- )
5420
+ ),
5421
+ body.creditAmount
5060
5422
  );
5061
5423
  }
5062
5424
  retrieve(params) {
@@ -7434,6 +7796,13 @@ var Client = class _Client {
7434
7796
  this.markets = new MarketDiscovery(
7435
7797
  (options2) => this.collections.from("markets").find(options2)
7436
7798
  );
7799
+ this.credits = new CustomerCreditsApi("CustomerCreditsApi", {
7800
+ publishableKey: this.config.publishableKey,
7801
+ apiUrl: this.config.apiUrl,
7802
+ customerToken: () => this.customer.auth.getToken(),
7803
+ onUnauthorized,
7804
+ onRequestId
7805
+ });
7437
7806
  this.benefitVouchers = new CustomerBenefitVouchersApi(
7438
7807
  "CustomerBenefitVouchersApi",
7439
7808
  {
@@ -7464,7 +7833,8 @@ var Client = class _Client {
7464
7833
  ...this.config,
7465
7834
  customer: this.config.customer?.persist === false ? {
7466
7835
  ...this.config.customer,
7467
- token: this.customer.auth.getToken() ?? void 0
7836
+ token: this.customer.auth.getToken() ?? void 0,
7837
+ refreshToken: this.customer.auth.getRefreshToken() ?? void 0
7468
7838
  } : this.config.customer,
7469
7839
  market
7470
7840
  });