@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/server.cjs CHANGED
@@ -23,6 +23,7 @@ __export(server_exports, {
23
23
  BenefitVouchersApi: () => BenefitVouchersApi,
24
24
  CollectionClient: () => CollectionClient,
25
25
  CommunityClient: () => CommunityClient,
26
+ CreditsApi: () => CreditsApi,
26
27
  CustomerGroupApi: () => CustomerGroupApi,
27
28
  EventsClient: () => EventsClient,
28
29
  ExternalCustomerLinksApi: () => ExternalCustomerLinksApi,
@@ -142,6 +143,7 @@ var COMMERCE_ERROR_CODES = [
142
143
  "cart_not_active",
143
144
  "cart_locked",
144
145
  "cart_empty",
146
+ "shipping_address_required",
145
147
  "cart_market_unavailable",
146
148
  "cart_market_mismatch",
147
149
  "checkout_not_open",
@@ -158,6 +160,7 @@ var COMMERCE_ERROR_CODES = [
158
160
  "price_changed",
159
161
  "pricing_fact_in_use",
160
162
  "insufficient_stock",
163
+ "credit_insufficient",
161
164
  "reservation_conflict",
162
165
  "stock_lock_unavailable",
163
166
  "variant_not_found",
@@ -621,6 +624,8 @@ async function parseErrorBody(response) {
621
624
  try {
622
625
  const body = await response.json();
623
626
  const reason = typeof body.reason === "string" ? body.reason : typeof body.code === "string" ? body.code : void 0;
627
+ const payloadErrorReason = Array.isArray(body.errors) ? readPayloadErrorReason(body.errors) : void 0;
628
+ const payloadReasonField = payloadErrorReason !== void 0 ? { payloadErrorReason } : {};
624
629
  if (body.errors && Array.isArray(body.errors)) {
625
630
  const fieldErrors = [];
626
631
  for (const e of body.errors) {
@@ -643,6 +648,7 @@ async function parseErrorBody(response) {
643
648
  errorMessage: `HTTP ${response.status}: ${details}`,
644
649
  userMessage: details,
645
650
  reason,
651
+ ...payloadReasonField,
646
652
  body,
647
653
  errors: fieldErrors.length > 0 ? fieldErrors : body.errors
648
654
  };
@@ -653,6 +659,7 @@ async function parseErrorBody(response) {
653
659
  errorMessage: `HTTP ${response.status}: ${body.error}`,
654
660
  userMessage: body.error,
655
661
  reason,
662
+ ...payloadReasonField,
656
663
  body
657
664
  };
658
665
  }
@@ -661,14 +668,23 @@ async function parseErrorBody(response) {
661
668
  errorMessage: `HTTP ${response.status}: ${body.message}`,
662
669
  userMessage: body.message,
663
670
  reason,
671
+ ...payloadReasonField,
664
672
  body
665
673
  };
666
674
  }
667
- return { ...fallback, reason, body };
675
+ return { ...fallback, reason, ...payloadReasonField, body };
668
676
  } catch {
669
677
  return fallback;
670
678
  }
671
679
  }
680
+ function readPayloadErrorReason(errors) {
681
+ const data = errors[0]?.data;
682
+ if (!data || typeof data !== "object") return void 0;
683
+ const { reason, code } = data;
684
+ if (typeof reason === "string") return reason;
685
+ if (typeof code === "string") return code;
686
+ return void 0;
687
+ }
672
688
  function getParsedErrorSuggestion(status, parsed) {
673
689
  if (status === 403 && parsed.reason === "origin_not_allowed") {
674
690
  return "Add the request origin to the tenant Browser API origins, then retry the browser request.";
@@ -714,7 +730,10 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, cano
714
730
  if (retryAfter !== void 0) {
715
731
  Object.assign(withRequestId, { retryAfter });
716
732
  }
717
- return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
733
+ return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(
734
+ withRequestId,
735
+ parsed.reason ?? parsed.payloadErrorReason
736
+ );
718
737
  };
719
738
  if (status === 400 || status === 422) {
720
739
  return finalize(
@@ -1133,6 +1152,7 @@ async function parseApiResponse(response, endpoint, options = {}) {
1133
1152
  // ../../internal/http-contracts/src/index.ts
1134
1153
  var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1135
1154
  var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
1155
+ var CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE = "application/vnd.01software.credit-funding.v1+json";
1136
1156
  var operation = (collection, method, path, errorFamily) => Object.freeze({
1137
1157
  [operationBrand]: true,
1138
1158
  collection,
@@ -1296,6 +1316,11 @@ var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
1296
1316
  ]);
1297
1317
  var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1298
1318
  subscribe: operation(null, "post", "/memberships/subscribe"),
1319
+ endSubscribeIntent: operation(
1320
+ null,
1321
+ "post",
1322
+ "/memberships/subscribe-intent/end"
1323
+ ),
1299
1324
  billingCustody: operation(null, "post", "/memberships/billing-custody"),
1300
1325
  cancel: operation(null, "post", "/memberships/:id/cancel"),
1301
1326
  me: operation(null, "get", "/memberships/me"),
@@ -1341,6 +1366,19 @@ var BENEFIT_VOUCHER_ENDPOINT_OPERATIONS = {
1341
1366
  void: operation("customers", "post", "/benefit-vouchers/void"),
1342
1367
  listMine: operation("customers", "get", "/me/benefit-vouchers")
1343
1368
  };
1369
+ var CUSTOMER_CREDIT_ENDPOINT_OPERATIONS = {
1370
+ grant: strictCommerceOperation("customers", "post", "/credits/grant"),
1371
+ getGrant: strictCommerceOperation("customers", "post", "/credits/get-grant"),
1372
+ getAccount: strictCommerceOperation("customers", "post", "/credits/account"),
1373
+ revoke: strictCommerceOperation("customers", "post", "/credits/revoke"),
1374
+ mine: strictCommerceOperation("customers", "get", "/me/credits"),
1375
+ history: strictCommerceOperation("customers", "get", "/me/credits/history"),
1376
+ configure: strictCommerceOperation(
1377
+ "customers",
1378
+ "post",
1379
+ "/credits/configuration"
1380
+ )
1381
+ };
1344
1382
  var CUSTOMER_GROUP_ENDPOINT_OPERATIONS = {
1345
1383
  members: operation("customer-groups", "get", "/:id/members"),
1346
1384
  grant: operation("customer-groups", "post", "/:id/members/grant"),
@@ -1760,6 +1798,179 @@ var BenefitVouchersApi = class extends BaseApi {
1760
1798
  }
1761
1799
  };
1762
1800
 
1801
+ // src/core/api/customer-credit-types.ts
1802
+ function parseCustomerCreditAccount(value) {
1803
+ const data = object2(value, ["summary", "history"]);
1804
+ return {
1805
+ summary: parseMyCustomerCredits(data.summary),
1806
+ history: parseMyCustomerCreditHistory(data.history)
1807
+ };
1808
+ }
1809
+ function invalid() {
1810
+ throw createApiError("Invalid customer credit response", 502);
1811
+ }
1812
+ function object2(value, keys) {
1813
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(value, key)))
1814
+ invalid();
1815
+ return value;
1816
+ }
1817
+ function money(value) {
1818
+ return typeof value === "string" && /^(0|[1-9][0-9]*)$/.test(value);
1819
+ }
1820
+ function uuid2(value) {
1821
+ 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(
1822
+ value
1823
+ );
1824
+ }
1825
+ function time2(value) {
1826
+ if (typeof value !== "string") return false;
1827
+ const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
1828
+ if (!match) return false;
1829
+ const [, year, month, day, hour, minute, second = "0"] = match;
1830
+ const y = Number(year), m = Number(month), d = Number(day);
1831
+ const days = [
1832
+ 31,
1833
+ y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 29 : 28,
1834
+ 31,
1835
+ 30,
1836
+ 31,
1837
+ 30,
1838
+ 31,
1839
+ 31,
1840
+ 30,
1841
+ 31,
1842
+ 30,
1843
+ 31
1844
+ ];
1845
+ return m >= 1 && m <= 12 && d >= 1 && d <= days[m - 1] && Number(hour) < 24 && Number(minute) < 60 && Number(second) < 60;
1846
+ }
1847
+ var states = ["available", "held", "spent", "expired", "revoked"];
1848
+ function balances(value) {
1849
+ const data = object2(value, states);
1850
+ if (states.some((key) => !money(data[key]))) invalid();
1851
+ }
1852
+ function page(value) {
1853
+ if (value.currency !== "KRW" || !time2(value.evaluatedAt) || !Number.isSafeInteger(value.page) || value.page < 1 || typeof value.hasNextPage !== "boolean")
1854
+ invalid();
1855
+ }
1856
+ function parseCustomerCreditGrant(value) {
1857
+ const data = object2(value, [
1858
+ "id",
1859
+ "customerId",
1860
+ "templateId",
1861
+ "templateVersion",
1862
+ "mode",
1863
+ "maximum",
1864
+ "amount",
1865
+ "currency",
1866
+ "validityDays",
1867
+ "grantedAt",
1868
+ "expiresAt",
1869
+ "sourceNamespace",
1870
+ "sourceRef"
1871
+ ]);
1872
+ if (!uuid2(data.id) || !uuid2(data.customerId) || !uuid2(data.templateId) || !Number.isSafeInteger(data.templateVersion) || data.templateVersion < 1 || !["fixed", "bounded"].includes(data.mode) || !money(data.maximum) || !money(data.amount) || data.currency !== "KRW" || !Number.isInteger(data.validityDays) || data.validityDays < 1 || data.validityDays > 1825 || !time2(data.grantedAt) || !time2(data.expiresAt) || typeof data.sourceNamespace !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/.test(data.sourceNamespace) || typeof data.sourceRef !== "string" || !data.sourceRef.length || data.sourceRef.length > 256 || // eslint-disable-next-line no-control-regex -- The public source identity explicitly forbids ASCII control characters.
1873
+ /[\u0000-\u001f\u007f]/.test(data.sourceRef))
1874
+ invalid();
1875
+ return value;
1876
+ }
1877
+ function parseRevokeCustomerCredit(value) {
1878
+ const data = object2(value, ["revoked", "pending", "spent"]);
1879
+ if (!money(data.revoked) || !money(data.pending) || !money(data.spent))
1880
+ invalid();
1881
+ return value;
1882
+ }
1883
+ function parseMyCustomerCredits(value) {
1884
+ const data = object2(value, [
1885
+ "currency",
1886
+ "evaluatedAt",
1887
+ "granted",
1888
+ "balances",
1889
+ "buckets",
1890
+ "page",
1891
+ "hasNextPage"
1892
+ ]);
1893
+ page(data);
1894
+ balances(data.balances);
1895
+ if (!money(data.granted) || !Array.isArray(data.buckets) || data.buckets.length > 50)
1896
+ invalid();
1897
+ for (const value2 of data.buckets) {
1898
+ const bucket = object2(value2, [
1899
+ "id",
1900
+ "grantId",
1901
+ "kind",
1902
+ "grantedAt",
1903
+ "expiresAt",
1904
+ "isRevoked",
1905
+ "balances"
1906
+ ]);
1907
+ if (!uuid2(bucket.id) || !uuid2(bucket.grantId) || !["original", "grace"].includes(bucket.kind) || !time2(bucket.grantedAt) || !time2(bucket.expiresAt) || typeof bucket.isRevoked !== "boolean")
1908
+ invalid();
1909
+ balances(bucket.balances);
1910
+ }
1911
+ return value;
1912
+ }
1913
+ function parseMyCustomerCreditHistory(value) {
1914
+ const data = object2(value, [
1915
+ "currency",
1916
+ "evaluatedAt",
1917
+ "entries",
1918
+ "page",
1919
+ "hasNextPage"
1920
+ ]);
1921
+ page(data);
1922
+ if (!Array.isArray(data.entries) || data.entries.length > 50) invalid();
1923
+ for (const value2 of data.entries) {
1924
+ const entry = object2(value2, [
1925
+ "id",
1926
+ "grantId",
1927
+ "kind",
1928
+ "amount",
1929
+ "fromState",
1930
+ "toState",
1931
+ "createdAt"
1932
+ ]);
1933
+ if (!uuid2(entry.id) || !uuid2(entry.grantId) || !money(entry.amount) || !time2(entry.createdAt) || ![
1934
+ "grant",
1935
+ "reserve",
1936
+ "consume",
1937
+ "release",
1938
+ "restore",
1939
+ "expire",
1940
+ "revoke"
1941
+ ].includes(entry.kind) || entry.fromState !== null && !states.includes(entry.fromState) || entry.toState !== null && !states.includes(entry.toState))
1942
+ invalid();
1943
+ }
1944
+ return value;
1945
+ }
1946
+
1947
+ // src/core/api/credits-api.ts
1948
+ var CreditsApi = class extends BaseApi {
1949
+ constructor(options) {
1950
+ super("CreditsApi", options);
1951
+ }
1952
+ async grant(input) {
1953
+ return parseCustomerCreditGrant(
1954
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.grant, input)
1955
+ );
1956
+ }
1957
+ async getGrant(input) {
1958
+ return parseCustomerCreditGrant(
1959
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.getGrant, input)
1960
+ );
1961
+ }
1962
+ async getAccount(input) {
1963
+ return parseCustomerCreditAccount(
1964
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.getAccount, input)
1965
+ );
1966
+ }
1967
+ async revoke(input) {
1968
+ return parseRevokeCustomerCredit(
1969
+ await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.revoke, input)
1970
+ );
1971
+ }
1972
+ };
1973
+
1763
1974
  // src/core/collection/http-client.ts
1764
1975
  var import_qs_esm = require("qs-esm");
1765
1976
  function validateWhere(where) {
@@ -2011,6 +2222,9 @@ function resolveMetaImage(ref) {
2011
2222
  }
2012
2223
 
2013
2224
  // src/core/collection/query-builder.ts
2225
+ function toWriteOptions(options) {
2226
+ return options?.locale === void 0 ? void 0 : { locale: options.locale };
2227
+ }
2014
2228
  var CollectionQueryBuilder = class {
2015
2229
  constructor(api, collection) {
2016
2230
  this.api = api;
@@ -2041,36 +2255,50 @@ var CollectionQueryBuilder = class {
2041
2255
  /**
2042
2256
  * Create a new document
2043
2257
  * POST /api/{collection}
2258
+ * Pass `locale` to write localized fields in a tenant-enabled locale.
2044
2259
  * @returns Payload CMS mutation response with doc and message
2045
2260
  */
2046
2261
  async create(data, options) {
2047
2262
  const endpoint = `/api/${String(this.collection)}`;
2263
+ const writeOptions = toWriteOptions(options);
2048
2264
  if (options?.file) {
2049
2265
  return this.api.requestCreateWithFile(
2050
2266
  endpoint,
2051
2267
  data,
2052
2268
  options.file,
2053
- options.filename
2269
+ options.filename,
2270
+ writeOptions
2054
2271
  );
2055
2272
  }
2056
- return this.api.requestCreate(endpoint, data);
2273
+ return this.api.requestCreate(
2274
+ endpoint,
2275
+ data,
2276
+ writeOptions
2277
+ );
2057
2278
  }
2058
2279
  /**
2059
2280
  * Update a document by ID
2060
2281
  * PATCH /api/{collection}/{id}
2282
+ * Pass `locale` to write localized fields in a tenant-enabled locale.
2061
2283
  * @returns Payload CMS mutation response with doc and message
2062
2284
  */
2063
2285
  async update(id, data, options) {
2064
2286
  const endpoint = `/api/${String(this.collection)}/${String(id)}`;
2287
+ const writeOptions = toWriteOptions(options);
2065
2288
  if (options?.file) {
2066
2289
  return this.api.requestUpdateWithFile(
2067
2290
  endpoint,
2068
2291
  data,
2069
2292
  options.file,
2070
- options.filename
2293
+ options.filename,
2294
+ writeOptions
2071
2295
  );
2072
2296
  }
2073
- return this.api.requestUpdate(endpoint, data);
2297
+ return this.api.requestUpdate(
2298
+ endpoint,
2299
+ data,
2300
+ writeOptions
2301
+ );
2074
2302
  }
2075
2303
  /**
2076
2304
  * Count documents
@@ -2114,10 +2342,11 @@ var CollectionQueryBuilder = class {
2114
2342
  * PATCH /api/{collection}
2115
2343
  * @returns Payload CMS find response with updated docs
2116
2344
  */
2117
- async updateMany(where, data) {
2345
+ async updateMany(where, data, options) {
2118
2346
  return this.api.requestUpdateMany(
2119
2347
  `/api/${String(this.collection)}`,
2120
- { where, data }
2348
+ { where, data },
2349
+ toWriteOptions(options)
2121
2350
  );
2122
2351
  }
2123
2352
  /**
@@ -2212,8 +2441,9 @@ var CollectionClient = class extends HttpClient {
2212
2441
  * Create document
2213
2442
  * POST /api/{collection}
2214
2443
  */
2215
- async requestCreate(endpoint, data) {
2216
- const response = await this.fetchWithTracking(endpoint, {
2444
+ async requestCreate(endpoint, data, options) {
2445
+ const url = this.buildUrl(endpoint, options);
2446
+ const response = await this.fetchWithTracking(url, {
2217
2447
  ...this.defaultOptions,
2218
2448
  method: "POST",
2219
2449
  body: data ? JSON.stringify(data) : void 0
@@ -2224,8 +2454,9 @@ var CollectionClient = class extends HttpClient {
2224
2454
  * Update document
2225
2455
  * PATCH /api/{collection}/{id}
2226
2456
  */
2227
- async requestUpdate(endpoint, data) {
2228
- const response = await this.fetchWithTracking(endpoint, {
2457
+ async requestUpdate(endpoint, data, options) {
2458
+ const url = this.buildUrl(endpoint, options);
2459
+ const response = await this.fetchWithTracking(url, {
2229
2460
  ...this.defaultOptions,
2230
2461
  method: "PATCH",
2231
2462
  body: data ? JSON.stringify(data) : void 0
@@ -2248,8 +2479,8 @@ var CollectionClient = class extends HttpClient {
2248
2479
  * Update multiple documents (bulk update)
2249
2480
  * PATCH /api/{collection}
2250
2481
  */
2251
- async requestUpdateMany(endpoint, data) {
2252
- const url = this.buildUrl(endpoint, { where: data.where });
2482
+ async requestUpdateMany(endpoint, data, options) {
2483
+ const url = this.buildUrl(endpoint, { where: data.where, ...options });
2253
2484
  const response = await this.fetchWithTracking(url, {
2254
2485
  ...this.defaultOptions,
2255
2486
  method: "PATCH",
@@ -2285,8 +2516,9 @@ var CollectionClient = class extends HttpClient {
2285
2516
  * Create document with file upload
2286
2517
  * POST /api/{collection} (multipart/form-data)
2287
2518
  */
2288
- async requestCreateWithFile(endpoint, data, file, filename) {
2289
- const response = await this.fetchWithTracking(endpoint, {
2519
+ async requestCreateWithFile(endpoint, data, file, filename, options) {
2520
+ const url = this.buildUrl(endpoint, options);
2521
+ const response = await this.fetchWithTracking(url, {
2290
2522
  ...this.defaultOptions,
2291
2523
  method: "POST",
2292
2524
  body: buildPayloadFormData(data, file, filename)
@@ -2297,8 +2529,9 @@ var CollectionClient = class extends HttpClient {
2297
2529
  * Update document with file upload
2298
2530
  * PATCH /api/{collection}/{id} (multipart/form-data)
2299
2531
  */
2300
- async requestUpdateWithFile(endpoint, data, file, filename) {
2301
- const response = await this.fetchWithTracking(endpoint, {
2532
+ async requestUpdateWithFile(endpoint, data, file, filename, options) {
2533
+ const url = this.buildUrl(endpoint, options);
2534
+ const response = await this.fetchWithTracking(url, {
2302
2535
  ...this.defaultOptions,
2303
2536
  method: "PATCH",
2304
2537
  body: buildPayloadFormData(data, file, filename)
@@ -2554,11 +2787,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
2554
2787
  * - `rootComment`: comments belonging to a thread rooted at that comment.
2555
2788
  */
2556
2789
  listComments(params) {
2557
- const { postId, page, limit, rootComment, topLevelOnly, sort } = params;
2790
+ const { postId, page: page2, limit, rootComment, topLevelOnly, sort } = params;
2558
2791
  return this.execute(
2559
2792
  this.buildCommentsListQuery({
2560
2793
  postId,
2561
- page,
2794
+ page: page2,
2562
2795
  limit,
2563
2796
  rootComment,
2564
2797
  topLevelOnly,
@@ -2569,11 +2802,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
2569
2802
  }
2570
2803
  /** Direct replies to a comment (`where[parent][equals]`). */
2571
2804
  listReplies(params) {
2572
- const { commentId, page, limit, sort } = params;
2805
+ const { commentId, page: page2, limit, sort } = params;
2573
2806
  return this.execute(
2574
2807
  this.buildCommentsListQuery({
2575
2808
  parentId: commentId,
2576
- page,
2809
+ page: page2,
2577
2810
  limit,
2578
2811
  sort
2579
2812
  }),
@@ -2757,7 +2990,18 @@ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2757
2990
  function managedPaymentProviders(providers) {
2758
2991
  return providers;
2759
2992
  }
2760
- var PAYMENT_PROVIDERS = managedPaymentProviders(["toss", "portone"]);
2993
+ var PAYMENT_PROVIDERS = managedPaymentProviders([
2994
+ "toss",
2995
+ "portone",
2996
+ "stripe"
2997
+ ]);
2998
+ var CANCEL_RECOVERY_METHODS = {
2999
+ toss: "cancel()",
3000
+ portone: "cancelPortOne()",
3001
+ stripe: null
3002
+ };
3003
+ var STRIPE_RETURN_URL_RAW_CHARACTERS = /^[^\s\u0000-\u001F\u007F\\]+$/;
3004
+ var STRIPE_RETURN_URL_AUTHORITY = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+(?:[/?#]|$)/;
2761
3005
  var PAYMENT_PROVIDER_STATUSES = [
2762
3006
  "requires_payment_method",
2763
3007
  "requires_action",
@@ -2818,11 +3062,8 @@ function fail(resource, path, expected) {
2818
3062
  invalidCanonicalResponse(resource, { path, expected });
2819
3063
  }
2820
3064
  function providerMismatch(resource, expected, actual, operation2) {
2821
- if (operation2 === "cancel") {
2822
- const method = {
2823
- toss: "cancel()",
2824
- portone: "cancelPortOne()"
2825
- }[actual];
3065
+ const method = CANCEL_RECOVERY_METHODS[actual];
3066
+ if (operation2 === "cancel" && method !== null) {
2826
3067
  throw createApiError(
2827
3068
  `Canonical ${resource} response provider mismatch: expected ${expected}, received ${actual}.`,
2828
3069
  502,
@@ -2851,6 +3092,17 @@ function exact(value, required, optional, resource, path) {
2851
3092
  const unexpected = Object.keys(value).find((key) => !allowed.has(key));
2852
3093
  if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
2853
3094
  }
3095
+ function responseExtensionKeys(value, keys, resource, path) {
3096
+ if (!keys.some((key) => Object.prototype.hasOwnProperty.call(value, key)))
3097
+ return [];
3098
+ enumValue(
3099
+ value.deliveryMethod,
3100
+ ["shipping", "pickup"],
3101
+ resource,
3102
+ `${path}.deliveryMethod`
3103
+ );
3104
+ return [...keys];
3105
+ }
2854
3106
  function string(value, resource, path) {
2855
3107
  if (typeof value !== "string" || value.length === 0) {
2856
3108
  fail(resource, path, "non-empty string");
@@ -3205,6 +3457,12 @@ function validatePublicCart(value, resource = "Cart") {
3205
3457
  exact(
3206
3458
  cart,
3207
3459
  [
3460
+ ...responseExtensionKeys(
3461
+ cart,
3462
+ ["deliveryMethod", "shippingMinor", "totalMinor"],
3463
+ resource,
3464
+ "$"
3465
+ ),
3208
3466
  "id",
3209
3467
  "status",
3210
3468
  "revision",
@@ -3275,6 +3533,13 @@ function validatePublicCart(value, resource = "Cart") {
3275
3533
  if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
3276
3534
  fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
3277
3535
  }
3536
+ if ("deliveryMethod" in cart) {
3537
+ const shipping = safeMinor(cart.shippingMinor, resource, "$.shippingMinor");
3538
+ const total = safeMinor(cart.totalMinor, resource, "$.totalMinor");
3539
+ if (BigInt(total) !== BigInt(estimatedTotal) + BigInt(shipping)) {
3540
+ fail(resource, "$.totalMinor", "estimatedTotalMinor + shippingMinor");
3541
+ }
3542
+ }
3278
3543
  timestamp(cart.expiresAt, resource, "$.expiresAt");
3279
3544
  timestamp(cart.createdAt, resource, "$.createdAt");
3280
3545
  timestamp(cart.updatedAt, resource, "$.updatedAt");
@@ -3518,6 +3783,17 @@ function validateCheckoutCore(value, resource, list, server) {
3518
3783
  "$.status"
3519
3784
  );
3520
3785
  const keys = checkoutVariantKeys(status, checkout.placedVia);
3786
+ keys.required.push(
3787
+ ...responseExtensionKeys(
3788
+ checkout,
3789
+ ["deliveryMethod", "source"],
3790
+ resource,
3791
+ "$"
3792
+ )
3793
+ );
3794
+ if ("deliveryMethod" in checkout)
3795
+ enumValue(checkout.source, ["web", "in_person"], resource, "$.source");
3796
+ keys.optional.push("funding");
3521
3797
  if (list) {
3522
3798
  keys.required = keys.required.filter(
3523
3799
  (key) => !["items", "shippingAddress", "attributes"].includes(key)
@@ -3529,6 +3805,33 @@ function validateCheckoutCore(value, resource, list, server) {
3529
3805
  exact(checkout, keys.required, keys.optional, resource, "$");
3530
3806
  string(checkout.id, resource, "$.id");
3531
3807
  validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
3808
+ if (Object.prototype.hasOwnProperty.call(checkout, "funding")) {
3809
+ const funding = record(checkout.funding, resource, "$.funding");
3810
+ exact(
3811
+ funding,
3812
+ ["creditAmount", "providerPayableAmount"],
3813
+ [],
3814
+ resource,
3815
+ "$.funding"
3816
+ );
3817
+ const credit = safeMinor(
3818
+ funding.creditAmount,
3819
+ resource,
3820
+ "$.funding.creditAmount"
3821
+ );
3822
+ const provider = safeMinor(
3823
+ funding.providerPayableAmount,
3824
+ resource,
3825
+ "$.funding.providerPayableAmount"
3826
+ );
3827
+ const amounts = checkout.amounts;
3828
+ if (BigInt(credit) + BigInt(provider) !== BigInt(amounts.totalMinor) || credit > 0 && amounts.currency !== "KRW")
3829
+ fail(
3830
+ resource,
3831
+ "$.funding",
3832
+ "exact purchase total split; positive credits require KRW"
3833
+ );
3834
+ }
3532
3835
  if (!list) {
3533
3836
  const items = array(checkout.items, resource, "$.items");
3534
3837
  if (items.length === 0) fail(resource, "$.items", "non-empty array");
@@ -3687,10 +3990,10 @@ function validateCheckoutQueryResult(value) {
3687
3990
  return value;
3688
3991
  }
3689
3992
  function validateMoney(value, resource, path) {
3690
- const money = record(value, resource, path);
3691
- exact(money, ["amountMinor", "currency"], [], resource, path);
3692
- safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
3693
- currency(money.currency, resource, `${path}.currency`);
3993
+ const money2 = record(value, resource, path);
3994
+ exact(money2, ["amountMinor", "currency"], [], resource, path);
3995
+ safeMinor(money2.amountMinor, resource, `${path}.amountMinor`);
3996
+ currency(money2.currency, resource, `${path}.currency`);
3694
3997
  }
3695
3998
  function validateCustomPaymentSession(value) {
3696
3999
  const resource = "custom PaymentSession";
@@ -3951,6 +4254,65 @@ function validateRequiredReconciliation(value, allowed, resource, path) {
3951
4254
  }
3952
4255
  function validateNextAction(value, provider, resource, path) {
3953
4256
  const action = record(value, resource, path);
4257
+ if (provider === "stripe") {
4258
+ exact(
4259
+ action,
4260
+ ["type", "clientSecret", "publishableKey", "returnUrl"],
4261
+ [],
4262
+ resource,
4263
+ path
4264
+ );
4265
+ if (action.type !== "stripe_payment_element")
4266
+ fail(resource, `${path}.type`, "stripe_payment_element");
4267
+ const clientSecret = boundedString(
4268
+ action.clientSecret,
4269
+ 255,
4270
+ resource,
4271
+ `${path}.clientSecret`
4272
+ );
4273
+ if (!/^pi_[A-Za-z0-9]+_secret_[A-Za-z0-9]+$/.test(clientSecret)) {
4274
+ fail(
4275
+ resource,
4276
+ `${path}.clientSecret`,
4277
+ "Stripe PaymentIntent client secret"
4278
+ );
4279
+ }
4280
+ const publishableKey = boundedString(
4281
+ action.publishableKey,
4282
+ 255,
4283
+ resource,
4284
+ `${path}.publishableKey`
4285
+ );
4286
+ if (!/^pk_(?:test|live)_[A-Za-z0-9]+$/.test(publishableKey)) {
4287
+ fail(resource, `${path}.publishableKey`, "Stripe publishable key");
4288
+ }
4289
+ const returnUrl = boundedString(
4290
+ action.returnUrl,
4291
+ 2048,
4292
+ resource,
4293
+ `${path}.returnUrl`
4294
+ );
4295
+ if (!STRIPE_RETURN_URL_RAW_CHARACTERS.test(returnUrl) || !STRIPE_RETURN_URL_AUTHORITY.test(returnUrl)) {
4296
+ fail(
4297
+ resource,
4298
+ `${path}.returnUrl`,
4299
+ "HTTPS or loopback URL without embedded credentials"
4300
+ );
4301
+ }
4302
+ try {
4303
+ const parsed = new URL(returnUrl);
4304
+ const loopback = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
4305
+ if (!loopback && parsed.protocol !== "https:" || parsed.username || parsed.password)
4306
+ throw new Error("unsafe return URL");
4307
+ } catch {
4308
+ fail(
4309
+ resource,
4310
+ `${path}.returnUrl`,
4311
+ "HTTPS or loopback URL without embedded credentials"
4312
+ );
4313
+ }
4314
+ return;
4315
+ }
3954
4316
  if (provider === "portone") {
3955
4317
  if (action.type === "portone_sdk") {
3956
4318
  const hasCancelable = "cancelable" in action;
@@ -4326,7 +4688,7 @@ function validatePublicPaymentSession(value, expectedProvider, operation2) {
4326
4688
  );
4327
4689
  }
4328
4690
  if (expectedProvider !== void 0 && provider !== expectedProvider) {
4329
- if (operation2 === "cancel" && status !== "canceling" && status !== "canceled") {
4691
+ if (operation2 === "cancel" && CANCEL_RECOVERY_METHODS[provider] !== null && status !== "canceling" && status !== "canceled") {
4330
4692
  fail(
4331
4693
  resource,
4332
4694
  "$.providerStatus",
@@ -5867,8 +6229,9 @@ var CheckoutApi = class extends CustomerScopedApi {
5867
6229
  }
5868
6230
  post(endpoint, body, idempotencyKey) {
5869
6231
  return this.requestEndpoint(endpoint, body, {
5870
- ...idempotencyKey && {
5871
- headers: { "X-Idempotency-Key": idempotencyKey }
6232
+ headers: {
6233
+ Accept: CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE,
6234
+ ...idempotencyKey && { "X-Idempotency-Key": idempotencyKey }
5872
6235
  }
5873
6236
  });
5874
6237
  }
@@ -5878,34 +6241,58 @@ var CheckoutApi = class extends CustomerScopedApi {
5878
6241
  async serverCheckout(result) {
5879
6242
  return validateServerCheckout(await result);
5880
6243
  }
5881
- async createResult(result) {
5882
- return validateCreateCheckoutResult(
6244
+ async createResult(result, creditAmount) {
6245
+ const parsed = validateCreateCheckoutResult(
5883
6246
  await result,
5884
6247
  false
5885
6248
  );
6249
+ this.assertRequestedCredit(parsed.checkout, creditAmount);
6250
+ return parsed;
5886
6251
  }
5887
- async createServerResult(result) {
5888
- return validateCreateCheckoutResult(
6252
+ async createServerResult(result, creditAmount) {
6253
+ const parsed = validateCreateCheckoutResult(
5889
6254
  await result,
5890
6255
  true
5891
6256
  );
6257
+ this.assertRequestedCredit(parsed.checkout, creditAmount);
6258
+ return parsed;
6259
+ }
6260
+ assertCreditInput(amount) {
6261
+ if (amount !== void 0 && (!Number.isSafeInteger(amount) || amount <= 0))
6262
+ throw createValidationError(
6263
+ "creditAmount must be a positive safe integer."
6264
+ );
6265
+ }
6266
+ assertRequestedCredit(checkout, requested) {
6267
+ if (requested !== void 0 && checkout.funding?.creditAmount !== requested)
6268
+ throw createApiError(
6269
+ "Credit funding was not confirmed by the server.",
6270
+ 502,
6271
+ { resource: "Checkout", path: "$.funding" },
6272
+ "The response does not confirm the requested credit funding.",
6273
+ "Retry the same create with the original idempotency key and credit amount, or retrieve the Checkout; never retry without credit."
6274
+ );
5892
6275
  }
5893
6276
  create(params) {
5894
6277
  const { idempotencyKey, ...body } = params;
5895
6278
  assertCommerceIdempotencyKey(idempotencyKey);
6279
+ this.assertCreditInput(body.creditAmount);
5896
6280
  return this.createResult(
5897
- this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
6281
+ this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey),
6282
+ body.creditAmount
5898
6283
  );
5899
6284
  }
5900
6285
  createServer(params) {
5901
6286
  const { idempotencyKey, ...body } = params;
5902
6287
  assertCommerceIdempotencyKey(idempotencyKey);
6288
+ this.assertCreditInput(body.creditAmount);
5903
6289
  return this.createServerResult(
5904
6290
  this.post(
5905
6291
  COMMERCE_ENDPOINTS.checkouts.server.create,
5906
6292
  body,
5907
6293
  idempotencyKey
5908
- )
6294
+ ),
6295
+ body.creditAmount
5909
6296
  );
5910
6297
  }
5911
6298
  retrieve(params) {
@@ -6552,7 +6939,16 @@ var MembershipApi = class extends BaseApi {
6552
6939
  * to activate the membership.
6553
6940
  *
6554
6941
  * `subscribeIntentKey` is used as the HTTP idempotency key so the call is
6555
- * safely retryable.
6942
+ * safely retryable. Trials are once per tenant/customer/plan; a prior recipient
6943
+ * gets the paid prepare response (409 conflict without writes if the delegated
6944
+ * connection is unavailable). Catalog trialDays is not customer eligibility.
6945
+ * Display firstCharge amount/currency/periodStart and obtain explicit customer
6946
+ * consent before PSP execution; refusal must never dispatch payment.
6947
+ * Completed trial replays keep their result. Existing payload/live duplicate
6948
+ * checks run first (another live Membership is 409 duplicate_subscription).
6949
+ * If an unfinished trial replay passes those checks after another intent
6950
+ * received the trial, it returns 409 idempotency_conflict without writes;
6951
+ * its original snapshot is never rewritten into a paid intent.
6556
6952
  */
6557
6953
  subscribe(params) {
6558
6954
  const { subscribeIntentKey, ...body } = params;
@@ -6562,6 +6958,21 @@ var MembershipApi = class extends BaseApi {
6562
6958
  idempotencyRequestOptions(subscribeIntentKey)
6563
6959
  );
6564
6960
  }
6961
+ /**
6962
+ * End an unprepared or terminal intent without changing membership evidence.
6963
+ * Use an opaque random, non-personal key of 1–512 visible ASCII characters;
6964
+ * other keys are rejected because headers and JSON can encode them differently.
6965
+ */
6966
+ async endSubscribeIntent(params) {
6967
+ const result = await this.requestEndpoint(
6968
+ MEMBERSHIP_ENDPOINT_OPERATIONS.endSubscribeIntent,
6969
+ params
6970
+ );
6971
+ if (!result || typeof result !== "object" || Array.isArray(result) || Object.keys(result).length !== 1 || !("status" in result) || result.status !== "ended" && result.status !== "existing") {
6972
+ throw new Error("Invalid membership intent termination response");
6973
+ }
6974
+ return { status: result.status };
6975
+ }
6565
6976
  /**
6566
6977
  * Cancel a membership by id.
6567
6978
  * By default this sets `cancelAtPeriodEnd`, keeps benefits until
@@ -6659,7 +7070,7 @@ function getExternalEffectClaimErrorReason(error) {
6659
7070
  const reason = getSDKErrorReason(error);
6660
7071
  return errorReasons.has(reason) ? reason : void 0;
6661
7072
  }
6662
- var states = /* @__PURE__ */ new Set([
7073
+ var states2 = /* @__PURE__ */ new Set([
6663
7074
  "pre_dispatch_claimed",
6664
7075
  "armed_unknown",
6665
7076
  "reported_effect",
@@ -6684,7 +7095,7 @@ function claimFromResponse(value) {
6684
7095
  const claim = value.claim;
6685
7096
  if (!claim || typeof claim !== "object") invalidResponse();
6686
7097
  const row = claim;
6687
- if (typeof row.id !== "string" || !states.has(row.state) || row.armedAt !== null && typeof row.armedAt !== "string" || row.firstReportOutcome !== null && row.firstReportOutcome !== "effect" && row.firstReportOutcome !== "no_effect" || row.reportAuthority !== "tenant_supplied_unverified" || typeof row.leaseGranted !== "boolean" || row.leaseToken !== null && typeof row.leaseToken !== "string" || !Number.isSafeInteger(row.leaseGeneration) || row.leaseGranted && row.leaseToken === null || !row.leaseGranted && row.leaseToken !== null)
7098
+ if (typeof row.id !== "string" || !states2.has(row.state) || row.armedAt !== null && typeof row.armedAt !== "string" || row.firstReportOutcome !== null && row.firstReportOutcome !== "effect" && row.firstReportOutcome !== "no_effect" || row.reportAuthority !== "tenant_supplied_unverified" || typeof row.leaseGranted !== "boolean" || row.leaseToken !== null && typeof row.leaseToken !== "string" || !Number.isSafeInteger(row.leaseGeneration) || row.leaseGranted && row.leaseToken === null || !row.leaseGranted && row.leaseToken !== null)
6688
7099
  invalidResponse();
6689
7100
  return {
6690
7101
  id: row.id,
@@ -6807,8 +7218,8 @@ var InstallationCredentialsApi = class extends BaseApi {
6807
7218
  function invalidResponse3() {
6808
7219
  throw createApiError("Invalid external-customer link response", 200);
6809
7220
  }
6810
- var uuid2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
6811
- var isUuid = (value) => typeof value === "string" && (uuid2.test(value) || value === "00000000-0000-0000-0000-000000000000" || value.toLowerCase() === "ffffffff-ffff-ffff-ffff-ffffffffffff");
7221
+ var uuid3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
7222
+ var isUuid = (value) => typeof value === "string" && (uuid3.test(value) || value === "00000000-0000-0000-0000-000000000000" || value.toLowerCase() === "ffffffff-ffff-ffff-ffff-ffffffffffff");
6812
7223
  var isIdentity = (value) => typeof value === "string" && value.length > 0 && value.length <= 256 && value === value.trim() && // eslint-disable-next-line no-control-regex -- Normalized identity forbids C0 controls.
6813
7224
  !/[\u0000-\u001f]/.test(value) && !/[\uD800-\uDFFF]/u.test(value);
6814
7225
  var isDateTime = (value) => {
@@ -6949,6 +7360,7 @@ var ServerClient = class _ServerClient {
6949
7360
  const membershipApi = new MembershipApi(serverOptions);
6950
7361
  this.memberships = {
6951
7362
  subscribe: membershipApi.subscribe.bind(membershipApi),
7363
+ endSubscribeIntent: membershipApi.endSubscribeIntent.bind(membershipApi),
6952
7364
  cancel: membershipApi.cancel.bind(membershipApi),
6953
7365
  billingCustody: membershipApi.billingCustody.bind(membershipApi)
6954
7366
  };
@@ -6956,6 +7368,7 @@ var ServerClient = class _ServerClient {
6956
7368
  this.externalEffectClaims = new ExternalEffectClaimsApi(serverOptions);
6957
7369
  this.installationCredentials = new InstallationCredentialsApi(serverOptions);
6958
7370
  this.benefitVouchers = new BenefitVouchersApi(serverOptions);
7371
+ this.credits = new CreditsApi(serverOptions);
6959
7372
  this.externalCustomerLinks = new ExternalCustomerLinksApi(serverOptions);
6960
7373
  const tenantIntrospectionApi = new TenantIntrospectionApi(serverOptions);
6961
7374
  this.tenant = {