@01.software/sdk 0.49.0 → 0.56.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 (74) hide show
  1. package/CHANGELOG.md +257 -1
  2. package/MIGRATION.md +56 -0
  3. package/README.md +269 -56
  4. package/dist/client.cjs +608 -190
  5. package/dist/client.cjs.map +1 -1
  6. package/dist/client.d.cts +6 -6
  7. package/dist/client.d.ts +6 -6
  8. package/dist/client.js +608 -190
  9. package/dist/client.js.map +1 -1
  10. package/dist/{collection-client-DnDt6EQz.d.ts → collection-client-Bmr53saa.d.ts} +6 -4
  11. package/dist/{collection-client-XfGLPuTf.d.cts → collection-client-DxuBDso_.d.cts} +6 -4
  12. package/dist/{const-CBba4lDo.d.cts → const-BKUqg96Q.d.ts} +5 -5
  13. package/dist/{const-DCNV5Kq7.d.ts → const-Cv1DCsp6.d.cts} +5 -5
  14. package/dist/embedded-admin/server.cjs +306 -0
  15. package/dist/embedded-admin/server.cjs.map +1 -0
  16. package/dist/embedded-admin/server.d.cts +33 -0
  17. package/dist/embedded-admin/server.d.ts +33 -0
  18. package/dist/embedded-admin/server.js +288 -0
  19. package/dist/embedded-admin/server.js.map +1 -0
  20. package/dist/embedded-admin.cjs +400 -0
  21. package/dist/embedded-admin.cjs.map +1 -0
  22. package/dist/embedded-admin.d.cts +61 -0
  23. package/dist/embedded-admin.d.ts +61 -0
  24. package/dist/embedded-admin.js +377 -0
  25. package/dist/embedded-admin.js.map +1 -0
  26. package/dist/errors.cjs +1 -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 +1 -0
  31. package/dist/errors.js.map +1 -1
  32. package/dist/{index-DUuIqUS8.d.ts → index-CGsT4AQ8.d.cts} +89 -10
  33. package/dist/{index-CbKyoEzy.d.cts → index-DFHLLqYu.d.ts} +89 -10
  34. package/dist/index.cjs +752 -436
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +12 -69
  37. package/dist/index.d.ts +12 -69
  38. package/dist/index.js +752 -436
  39. package/dist/index.js.map +1 -1
  40. package/dist/{payload-types-MKbx5MuJ.d.cts → payload-types-Bk-duc5k.d.cts} +545 -141
  41. package/dist/{payload-types-MKbx5MuJ.d.ts → payload-types-Bk-duc5k.d.ts} +545 -141
  42. package/dist/query.cjs +108 -71
  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 +108 -71
  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 +502 -175
  51. package/dist/server.cjs.map +1 -1
  52. package/dist/server.d.cts +9 -8
  53. package/dist/server.d.ts +9 -8
  54. package/dist/server.js +502 -175
  55. package/dist/server.js.map +1 -1
  56. package/dist/storefront-cache.cjs +1 -0
  57. package/dist/storefront-cache.cjs.map +1 -1
  58. package/dist/storefront-cache.js +1 -0
  59. package/dist/storefront-cache.js.map +1 -1
  60. package/dist/{types-1UeOk1Uy.d.cts → types-CEK8uTvU.d.ts} +287 -30
  61. package/dist/{types-BKr_2avj.d.cts → types-CNdpj2fI.d.cts} +2 -2
  62. package/dist/{types-L_nh-ED7.d.ts → types-D4mjGFj4.d.ts} +2 -2
  63. package/dist/{types-Du4s5anw.d.ts → types-Dhk5NX7Z.d.cts} +287 -30
  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.cjs +135 -80
  69. package/dist/webhook.cjs.map +1 -1
  70. package/dist/webhook.d.cts +21 -5
  71. package/dist/webhook.d.ts +21 -5
  72. package/dist/webhook.js +135 -80
  73. package/dist/webhook.js.map +1 -1
  74. package/package.json +28 -6
package/dist/client.cjs CHANGED
@@ -140,6 +140,7 @@ var COMMERCE_ERROR_CODES = [
140
140
  "payment_session_not_cancelable",
141
141
  "payment_session_conflict",
142
142
  "provider_identity_mismatch",
143
+ "managed_refund_attestation_forbidden",
143
144
  "payment_method_unavailable",
144
145
  "provider_unavailable",
145
146
  "lock_timeout",
@@ -682,11 +683,11 @@ function parseRetryAfter(response) {
682
683
  permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
683
684
  };
684
685
  }
685
- function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
686
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, canonicalCommerceError) {
686
687
  const errorDetails = {
687
688
  ...details,
688
689
  ...parsed.errors && { errors: parsed.errors },
689
- ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
690
+ ...!canonicalCommerceError && parsed.body && { body: parsed.body }
690
691
  };
691
692
  const suggestion = getParsedErrorSuggestion(status, parsed);
692
693
  const finalize = (error) => {
@@ -694,7 +695,7 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, erro
694
695
  if (retryAfter !== void 0) {
695
696
  Object.assign(withRequestId, { retryAfter });
696
697
  }
697
- return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
698
+ return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
698
699
  };
699
700
  if (status === 400 || status === 422) {
700
701
  return finalize(
@@ -800,6 +801,7 @@ async function httpFetch(url, options) {
800
801
  retry,
801
802
  onUnauthorized,
802
803
  errorFamily,
804
+ typedCommerceErrorReasons,
803
805
  ...requestInit
804
806
  } = options || {};
805
807
  const baseUrl = resolveApiUrl(apiUrl);
@@ -853,7 +855,8 @@ async function httpFetch(url, options) {
853
855
  });
854
856
  if (!response.ok) {
855
857
  const parsed = await parseErrorBody(response);
856
- const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
858
+ const canonicalCommerceError = errorFamily === "commerce" || typeof parsed.reason === "string" && typedCommerceErrorReasons?.includes(parsed.reason) === true;
859
+ const commerceEnvelope = canonicalCommerceError ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
857
860
  if (isUsageLimitExceededResponse(response)) {
858
861
  const limit = parseInt(
859
862
  response.headers.get("X-Usage-Limit") || "0",
@@ -881,7 +884,7 @@ async function httpFetch(url, options) {
881
884
  ),
882
885
  requestId
883
886
  );
884
- throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : enhanceNonCommerceError(usageError, parsed.reason);
887
+ throw canonicalCommerceError ? enhanceCommerceError(usageError, parsed.body, requestId) : enhanceNonCommerceError(usageError, parsed.reason);
885
888
  }
886
889
  if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
887
890
  hasRetried401 = true;
@@ -906,7 +909,7 @@ async function httpFetch(url, options) {
906
909
  details,
907
910
  requestId,
908
911
  retryAfter.seconds,
909
- errorFamily
912
+ canonicalCommerceError
910
913
  );
911
914
  const method2 = (requestInit.method || "GET").toUpperCase();
912
915
  const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
@@ -1084,15 +1087,15 @@ var HttpClient = class {
1084
1087
  throw err;
1085
1088
  }
1086
1089
  }
1087
- buildUrl(endpoint2, options) {
1088
- if (!options) return endpoint2;
1090
+ buildUrl(endpoint, options) {
1091
+ if (!options) return endpoint;
1089
1092
  const { fallbackLocale, ...rest } = options;
1090
1093
  const queryOptions = fallbackLocale === void 0 ? rest : {
1091
1094
  ...rest,
1092
1095
  "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
1093
1096
  };
1094
1097
  const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
1095
- return queryString ? `${endpoint2}${queryString}` : endpoint2;
1098
+ return queryString ? `${endpoint}${queryString}` : endpoint;
1096
1099
  }
1097
1100
  assertJsonResponse(response) {
1098
1101
  const contentType = response.headers.get("content-type");
@@ -1234,39 +1237,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
1234
1237
  from(collection) {
1235
1238
  return new ReadOnlyCollectionQueryBuilder(this, collection);
1236
1239
  }
1237
- async requestFind(endpoint2, options) {
1238
- const url = this.buildUrl(endpoint2, options);
1240
+ async requestFind(endpoint, options) {
1241
+ const url = this.buildUrl(endpoint, options);
1239
1242
  const response = await this.fetchWithTracking(url, {
1240
1243
  ...this.defaultOptions,
1241
1244
  method: "GET"
1242
1245
  });
1243
1246
  return this.parseFindResponse(response);
1244
1247
  }
1245
- async requestFindEndpoint(endpoint2, data) {
1246
- const response = await this.fetchWithTracking(endpoint2, {
1248
+ async requestFindEndpoint(endpoint, data) {
1249
+ const response = await this.fetchWithTracking(endpoint, {
1247
1250
  ...this.defaultOptions,
1248
1251
  method: "POST",
1249
1252
  body: data ? JSON.stringify(data) : void 0
1250
1253
  });
1251
1254
  return this.parseFindResponse(response);
1252
1255
  }
1253
- async requestFindEndpointGet(endpoint2) {
1254
- const response = await this.fetchWithTracking(endpoint2, {
1256
+ async requestFindEndpointGet(endpoint) {
1257
+ const response = await this.fetchWithTracking(endpoint, {
1255
1258
  ...this.defaultOptions,
1256
1259
  method: "GET"
1257
1260
  });
1258
1261
  return this.parseFindResponse(response);
1259
1262
  }
1260
- async requestFindById(endpoint2, options) {
1261
- const url = this.buildUrl(endpoint2, options);
1263
+ async requestFindById(endpoint, options) {
1264
+ const url = this.buildUrl(endpoint, options);
1262
1265
  const response = await this.fetchWithTracking(url, {
1263
1266
  ...this.defaultOptions,
1264
1267
  method: "GET"
1265
1268
  });
1266
1269
  return this.parseDocumentResponse(response);
1267
1270
  }
1268
- async requestCount(endpoint2, options) {
1269
- const url = this.buildUrl(endpoint2, options);
1271
+ async requestCount(endpoint, options) {
1272
+ const url = this.buildUrl(endpoint, options);
1270
1273
  const response = await this.fetchWithTracking(url, {
1271
1274
  ...this.defaultOptions,
1272
1275
  method: "GET"
@@ -1276,7 +1279,7 @@ var ReadOnlyCollectionClient = class extends HttpClient {
1276
1279
  };
1277
1280
 
1278
1281
  // src/core/api/parse-response.ts
1279
- async function parseApiResponse(response, endpoint2, options = {}) {
1282
+ async function parseApiResponse(response, endpoint, options = {}) {
1280
1283
  if (response.status === 204 || response.headers.get("content-length") === "0") {
1281
1284
  return void 0;
1282
1285
  }
@@ -1285,7 +1288,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
1285
1288
  parsed = await response.json();
1286
1289
  } catch {
1287
1290
  throw createApiError(
1288
- `Invalid JSON response from ${endpoint2}`,
1291
+ `Invalid JSON response from ${endpoint}`,
1289
1292
  response.status,
1290
1293
  void 0,
1291
1294
  "Server returned an invalid response.",
@@ -1335,6 +1338,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
1335
1338
 
1336
1339
  // ../../internal/http-contracts/src/index.ts
1337
1340
  var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1341
+ var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
1338
1342
  var operation = (collection, method, path, errorFamily) => Object.freeze({
1339
1343
  [operationBrand]: true,
1340
1344
  collection,
@@ -1343,6 +1347,10 @@ var operation = (collection, method, path, errorFamily) => Object.freeze({
1343
1347
  ...errorFamily && { errorFamily }
1344
1348
  });
1345
1349
  var strictCommerceOperation = (collection, method, path) => operation(collection, method, path, "commerce");
1350
+ var selectiveCommerceOperation = (collection, method, path, typedCommerceErrorReasons) => Object.freeze({
1351
+ ...operation(collection, method, path),
1352
+ typedCommerceErrorReasons: Object.freeze([...typedCommerceErrorReasons])
1353
+ });
1346
1354
  var COMMERCE_ENDPOINT_OPERATIONS = {
1347
1355
  products: {
1348
1356
  detail: operation("products", "get", "/detail"),
@@ -1374,7 +1382,12 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
1374
1382
  confirmPayment: operation("orders", "post", "/confirm-payment"),
1375
1383
  byPayment: operation("orders", "get", "/by-payment"),
1376
1384
  cancel: operation("orders", "post", "/cancel"),
1377
- resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1385
+ resolveCancelRefund: selectiveCommerceOperation(
1386
+ "orders",
1387
+ "post",
1388
+ "/resolve-cancel-refund",
1389
+ ["managed_refund_attestation_forbidden"]
1390
+ ),
1378
1391
  checkout: strictCommerceOperation("orders", "post", "/checkout"),
1379
1392
  createFulfillment: operation("orders", "post", "/create-fulfillment"),
1380
1393
  updateFulfillment: operation("orders", "post", "/update-fulfillment")
@@ -1383,6 +1396,11 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
1383
1396
  detail: strictCommerceOperation("checkouts", "post", "/detail"),
1384
1397
  query: strictCommerceOperation("checkouts", "post", "/query")
1385
1398
  },
1399
+ draftOrders: {
1400
+ calculate: operation("draft-orders", "post", "/:id/calculate"),
1401
+ complete: operation("draft-orders", "post", "/:id/complete"),
1402
+ finalize: operation("draft-orders", "post", "/:id/finalize")
1403
+ },
1386
1404
  transactions: {
1387
1405
  update: operation("transactions", "post", "/update")
1388
1406
  },
@@ -1445,6 +1463,16 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
1445
1463
  "payment-sessions",
1446
1464
  "post",
1447
1465
  "/server/confirm"
1466
+ ),
1467
+ findPortOne: strictCommerceOperation(
1468
+ "payment-sessions",
1469
+ "post",
1470
+ "/server/portone/find"
1471
+ ),
1472
+ reconcilePortOne: strictCommerceOperation(
1473
+ "payment-sessions",
1474
+ "post",
1475
+ "/server/portone/reconcile"
1448
1476
  )
1449
1477
  },
1450
1478
  custom: {
@@ -1464,12 +1492,34 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
1464
1492
  validate: operation("discounts", "post", "/validate")
1465
1493
  }
1466
1494
  };
1495
+ var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
1496
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.create,
1497
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.retrieve,
1498
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.create,
1499
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.retrieve
1500
+ ]);
1467
1501
  var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1468
1502
  subscribe: operation(null, "post", "/memberships/subscribe"),
1469
1503
  cancel: operation(null, "post", "/memberships/:id/cancel"),
1470
- me: operation(null, "get", "/memberships/me")
1504
+ me: operation(null, "get", "/memberships/me"),
1505
+ chargeResult: operation(null, "post", "/memberships/:id/charge-result"),
1506
+ refundResult: operation(null, "post", "/memberships/:id/refund-result"),
1507
+ revoke: operation(null, "post", "/memberships/:id/revoke")
1508
+ };
1509
+ var CUSTOMER_GROUP_ENDPOINT_OPERATIONS = {
1510
+ members: operation("customer-groups", "get", "/:id/members"),
1511
+ grant: operation("customer-groups", "post", "/:id/members/grant"),
1512
+ revoke: operation("customer-groups", "post", "/:id/members/revoke")
1513
+ };
1514
+ var EMBEDDED_ADMIN_ENDPOINT_OPERATIONS = {
1515
+ show: operation("tenants", "get", "/embedded-admin-app"),
1516
+ configure: operation("tenants", "patch", "/embedded-admin-app"),
1517
+ disable: operation("tenants", "delete", "/embedded-admin-app")
1471
1518
  };
1472
1519
  var EVENTS_ENDPOINT_OPERATIONS = {
1520
+ events: {
1521
+ convertSchedule: operation("events", "post", "/:id/schedule")
1522
+ },
1473
1523
  occurrences: {
1474
1524
  range: operation("event-occurrences", "get", "/range"),
1475
1525
  admissionAvailability: operation(
@@ -1510,46 +1560,51 @@ function resolveOperationMethod(descriptor) {
1510
1560
  }
1511
1561
 
1512
1562
  // src/core/api/endpoints.ts
1513
- var endpoint = (method, path) => ({ method, path });
1514
1563
  var sharedEndpoint = (descriptor) => descriptor;
1515
- function resolveOperationMethod2(descriptor) {
1516
- return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1517
- }
1518
1564
  function resolveOperationErrorFamily(descriptor) {
1519
- return "collection" in descriptor ? descriptor.errorFamily : void 0;
1520
- }
1521
- function resolveOperationPath2(descriptor, options) {
1522
- if ("collection" in descriptor) {
1523
- return resolveOperationPath(descriptor, options);
1524
- }
1525
- const query = options?.query?.toString().replace(/^\?/, "");
1526
- return query ? `${descriptor.path}?${query}` : descriptor.path;
1565
+ return descriptor.errorFamily;
1527
1566
  }
1528
1567
  var COMMERCE_ENDPOINTS = {
1529
1568
  products: {
1530
- detail: endpoint("GET", "/api/products/detail"),
1531
- detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1532
- listingGroups: endpoint("GET", "/api/products/listing-groups"),
1533
- listingGroupsCatalog: endpoint(
1534
- "GET",
1535
- "/api/products/listing-groups/catalog"
1569
+ detail: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.detail),
1570
+ detailCatalog: sharedEndpoint(
1571
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog
1572
+ ),
1573
+ listingGroups: sharedEndpoint(
1574
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups
1575
+ ),
1576
+ listingGroupsCatalog: sharedEndpoint(
1577
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog
1578
+ ),
1579
+ // The manifest keeps the GET read and the POST body-query apart; this
1580
+ // semantic name has always resolved to the GET one.
1581
+ listingGroupsQuery: sharedEndpoint(
1582
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet
1583
+ ),
1584
+ listingGroupsQueryCatalog: sharedEndpoint(
1585
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog
1536
1586
  ),
1537
- listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1538
- listingGroupsQueryCatalog: endpoint(
1539
- "GET",
1540
- "/api/products/listing-groups/query/catalog"
1587
+ stockCheck: sharedEndpoint(
1588
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck
1541
1589
  ),
1542
- stockCheck: endpoint("POST", "/api/products/stock-check"),
1543
- stockSnapshot: endpoint("GET", "/api/products/stock"),
1544
- upsert: endpoint("POST", "/api/products/upsert")
1590
+ stockSnapshot: sharedEndpoint(
1591
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot
1592
+ ),
1593
+ upsert: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.upsert)
1545
1594
  },
1546
1595
  orders: {
1547
- update: endpoint("POST", "/api/orders/update"),
1548
- byPayment: endpoint("GET", "/api/orders/by-payment"),
1549
- cancel: endpoint("POST", "/api/orders/cancel"),
1550
- resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1551
- createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1552
- updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1596
+ update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.update),
1597
+ byPayment: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.byPayment),
1598
+ cancel: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.cancel),
1599
+ resolveCancelRefund: sharedEndpoint(
1600
+ COMMERCE_ENDPOINT_OPERATIONS.orders.resolveCancelRefund
1601
+ ),
1602
+ createFulfillment: sharedEndpoint(
1603
+ COMMERCE_ENDPOINT_OPERATIONS.orders.createFulfillment
1604
+ ),
1605
+ updateFulfillment: sharedEndpoint(
1606
+ COMMERCE_ENDPOINT_OPERATIONS.orders.updateFulfillment
1607
+ )
1553
1608
  },
1554
1609
  checkouts: {
1555
1610
  create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.checkout),
@@ -1561,18 +1616,21 @@ var COMMERCE_ENDPOINTS = {
1561
1616
  }
1562
1617
  },
1563
1618
  returns: {
1564
- create: endpoint("POST", "/api/returns/create"),
1565
- update: endpoint("POST", "/api/returns/update"),
1566
- returnRefund: endpoint("POST", "/api/returns/return-refund")
1619
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.create),
1620
+ update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.update),
1621
+ returnRefund: sharedEndpoint(
1622
+ COMMERCE_ENDPOINT_OPERATIONS.returns.returnRefund
1623
+ )
1567
1624
  },
1568
1625
  fulfillmentOrders: {
1569
- prepare: endpoint(
1570
- "POST",
1571
- "/api/fulfillment-orders/prepare-fulfillment-order"
1626
+ prepare: sharedEndpoint(
1627
+ COMMERCE_ENDPOINT_OPERATIONS.fulfillmentOrders.prepare
1572
1628
  )
1573
1629
  },
1574
1630
  fulfillments: {
1575
- bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1631
+ bulkImport: sharedEndpoint(
1632
+ COMMERCE_ENDPOINT_OPERATIONS.fulfillments.bulkImport
1633
+ )
1576
1634
  },
1577
1635
  carts: {
1578
1636
  create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
@@ -1637,42 +1695,21 @@ var COMMERCE_ENDPOINTS = {
1637
1695
  ),
1638
1696
  confirm: sharedEndpoint(
1639
1697
  COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.confirm
1698
+ ),
1699
+ findPortOne: sharedEndpoint(
1700
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.findPortOne
1701
+ ),
1702
+ reconcilePortOne: sharedEndpoint(
1703
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.reconcilePortOne
1640
1704
  )
1641
1705
  }
1642
1706
  },
1643
1707
  shippingPolicies: {
1644
- calculate: endpoint("POST", "/api/shipping-policies/calculate")
1708
+ calculate: sharedEndpoint(
1709
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate
1710
+ )
1645
1711
  }
1646
1712
  };
1647
- function isCommerceEndpointDescriptor(value) {
1648
- if (!value || typeof value !== "object") return false;
1649
- const candidate = value;
1650
- return typeof candidate.method === "string" && typeof candidate.path === "string";
1651
- }
1652
- function flattenEndpointPaths(value) {
1653
- if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1654
- if (!value || typeof value !== "object") return [];
1655
- return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1656
- }
1657
- function flattenEndpointDescriptors(value) {
1658
- if (isCommerceEndpointDescriptor(value)) return [value];
1659
- if (!value || typeof value !== "object") return [];
1660
- return Object.values(value).flatMap(
1661
- (entry) => flattenEndpointDescriptors(entry)
1662
- );
1663
- }
1664
- var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1665
- var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1666
- var MEMBERSHIP_ENDPOINTS = {
1667
- subscribe: "/api/memberships/subscribe",
1668
- cancel: (id) => `/api/memberships/${id}/cancel`,
1669
- me: "/api/memberships/me"
1670
- };
1671
- var MEMBERSHIP_ENDPOINT_PATHS = [
1672
- MEMBERSHIP_ENDPOINTS.subscribe,
1673
- MEMBERSHIP_ENDPOINTS.cancel(":id"),
1674
- MEMBERSHIP_ENDPOINTS.me
1675
- ];
1676
1713
 
1677
1714
  // src/core/api/customer-scoped-api.ts
1678
1715
  var CustomerScopedTransport = class {
@@ -1693,10 +1730,10 @@ var CustomerScopedTransport = class {
1693
1730
  this.onUnauthorized = options.onUnauthorized;
1694
1731
  this.onRequestId = options.onRequestId;
1695
1732
  }
1696
- async request(endpoint2, options) {
1733
+ async request(endpoint, options) {
1697
1734
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1698
1735
  try {
1699
- const response = await httpFetch(endpoint2, {
1736
+ const response = await httpFetch(endpoint, {
1700
1737
  method: options.method,
1701
1738
  apiUrl: this.apiUrl,
1702
1739
  publishableKey: this.publishableKey,
@@ -1710,7 +1747,7 @@ var CustomerScopedTransport = class {
1710
1747
  ...options.errorFamily && { errorFamily: options.errorFamily }
1711
1748
  });
1712
1749
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1713
- return parseApiResponse(response, endpoint2, {
1750
+ return parseApiResponse(response, endpoint, {
1714
1751
  errorFamily: options.errorFamily
1715
1752
  });
1716
1753
  } catch (err) {
@@ -1724,12 +1761,12 @@ var CustomerScopedApi = class {
1724
1761
  constructor(apiName, options) {
1725
1762
  this.transport = new CustomerScopedTransport(apiName, options);
1726
1763
  }
1727
- requestEndpoint(endpoint2, body, options) {
1728
- return this.transport.request(resolveOperationPath2(endpoint2, options), {
1729
- method: resolveOperationMethod2(endpoint2),
1764
+ requestEndpoint(endpoint, body, options) {
1765
+ return this.transport.request(resolveOperationPath(endpoint, options), {
1766
+ method: resolveOperationMethod(endpoint),
1730
1767
  body,
1731
1768
  headers: options?.headers,
1732
- errorFamily: resolveOperationErrorFamily(endpoint2)
1769
+ errorFamily: resolveOperationErrorFamily(endpoint)
1733
1770
  });
1734
1771
  }
1735
1772
  };
@@ -1737,8 +1774,8 @@ var RawCustomerScopedApi = class {
1737
1774
  constructor(apiName, options) {
1738
1775
  this.transport = new CustomerScopedTransport(apiName, options);
1739
1776
  }
1740
- request(endpoint2, options) {
1741
- return this.transport.request(endpoint2, options);
1777
+ request(endpoint, options) {
1778
+ return this.transport.request(endpoint, options);
1742
1779
  }
1743
1780
  };
1744
1781
 
@@ -1813,11 +1850,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
1813
1850
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1814
1851
  return `/api/comments/public?${urlParams.toString()}`;
1815
1852
  }
1816
- async execute(endpoint2, method, body) {
1817
- return this.request(endpoint2, { method, body });
1853
+ async execute(endpoint, method, body) {
1854
+ return this.request(endpoint, { method, body });
1818
1855
  }
1819
- async executeDoc(endpoint2, method, body) {
1820
- const response = await this.execute(endpoint2, method, body);
1856
+ async executeDoc(endpoint, method, body) {
1857
+ const response = await this.execute(endpoint, method, body);
1821
1858
  return unwrapPayloadDoc(response);
1822
1859
  }
1823
1860
  createPost(params) {
@@ -2083,8 +2120,8 @@ var CommunityClient = class extends RawCustomerScopedApi {
2083
2120
 
2084
2121
  // src/core/content/content-client.ts
2085
2122
  var PublicContentApi = class extends RawCustomerScopedApi {
2086
- get(endpoint2) {
2087
- return this.request(endpoint2, { method: "GET" });
2123
+ get(endpoint) {
2124
+ return this.request(endpoint, { method: "GET" });
2088
2125
  }
2089
2126
  };
2090
2127
  function appendCommonParams(search, options, defaultSort) {
@@ -2182,7 +2219,10 @@ var ORDER_PRIMARY_DISPLAY_STATUSES = [
2182
2219
  ];
2183
2220
  var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
2184
2221
  var ABANDONED_REASONS = ["expired", "customer", "operator"];
2185
- var PAYMENT_PROVIDERS = ["toss", "portone"];
2222
+ function managedPaymentProviders(providers) {
2223
+ return providers;
2224
+ }
2225
+ var PAYMENT_PROVIDERS = managedPaymentProviders(["toss", "portone"]);
2186
2226
  var PAYMENT_PROVIDER_STATUSES = [
2187
2227
  "requires_payment_method",
2188
2228
  "requires_action",
@@ -2230,6 +2270,26 @@ function invalidCanonicalResponse(resource, details) {
2230
2270
  function fail(resource, path, expected) {
2231
2271
  invalidCanonicalResponse(resource, { path, expected });
2232
2272
  }
2273
+ function providerMismatch(resource, expected, actual, operation2) {
2274
+ if (operation2 === "cancel") {
2275
+ const method = {
2276
+ toss: "cancel()",
2277
+ portone: "cancelPortOne()"
2278
+ }[actual];
2279
+ throw createApiError(
2280
+ `Canonical ${resource} response provider mismatch: expected ${expected}, received ${actual}.`,
2281
+ 502,
2282
+ { resource, path: "$.provider", expected, actual },
2283
+ `The server applied the cancellation to a ${actual} PaymentSession, but this SDK method expects ${expected}.`,
2284
+ `Re-invoke ${method} with the same idempotencyKey; do not create a new key.`
2285
+ );
2286
+ }
2287
+ invalidCanonicalResponse(resource, {
2288
+ path: "$.provider",
2289
+ expected,
2290
+ actual
2291
+ });
2292
+ }
2233
2293
  function record(value, resource, path) {
2234
2294
  if (!value || typeof value !== "object" || Array.isArray(value)) {
2235
2295
  fail(resource, path, "object");
@@ -2265,6 +2325,9 @@ function nullableString(value, resource, path) {
2265
2325
  fail(resource, path, "string or null");
2266
2326
  }
2267
2327
  }
2328
+ function nullableNonEmptyString(value, resource, path) {
2329
+ if (value !== null) string(value, resource, path);
2330
+ }
2268
2331
  function cartLineQuantity(value, resource, path) {
2269
2332
  const quantity = positiveInteger(value, resource, path);
2270
2333
  if (quantity > MAX_CART_LINE_QUANTITY) {
@@ -2774,8 +2837,8 @@ function validatePublicOrderItem(value, resource, path) {
2774
2837
  validateReference(item.variant, resource, `${path}.variant`);
2775
2838
  }
2776
2839
  string(item.productTitle, resource, `${path}.productTitle`);
2777
- nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2778
- nullableString(item.sku, resource, `${path}.sku`);
2840
+ nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
2841
+ nullableNonEmptyString(item.sku, resource, `${path}.sku`);
2779
2842
  validateAdmissions(item.admissions, resource, `${path}.admissions`);
2780
2843
  const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
2781
2844
  const unitPrice = safeMinor(
@@ -3026,8 +3089,8 @@ function validateCheckoutItem(value, resource, path) {
3026
3089
  validateReference(item.product, resource, `${path}.product`);
3027
3090
  validateReference(item.variant, resource, `${path}.variant`);
3028
3091
  string(item.productTitle, resource, `${path}.productTitle`);
3029
- nullableString(item.variantTitle, resource, `${path}.variantTitle`);
3030
- nullableString(item.sku, resource, `${path}.sku`);
3092
+ nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
3093
+ nullableNonEmptyString(item.sku, resource, `${path}.sku`);
3031
3094
  validateAdmissions(item.admissions, resource, `${path}.admissions`);
3032
3095
  cartLineQuantity(item.quantity, resource, `${path}.quantity`);
3033
3096
  const unitPrice = safeMinor(
@@ -3359,11 +3422,21 @@ function validateNextAction(value, provider, resource, path) {
3359
3422
  const action = record(value, resource, path);
3360
3423
  if (provider === "portone") {
3361
3424
  if (action.type === "portone_sdk") {
3425
+ const hasCancelable = "cancelable" in action;
3426
+ const hasRetryPolicy = "retryPolicy" in action;
3427
+ if (hasCancelable !== hasRetryPolicy) {
3428
+ fail(
3429
+ resource,
3430
+ path,
3431
+ "exact released action or exact negotiated capability action"
3432
+ );
3433
+ }
3362
3434
  exact(
3363
3435
  action,
3364
3436
  [
3365
3437
  "type",
3366
3438
  "version",
3439
+ ...hasCancelable ? ["cancelable", "retryPolicy"] : [],
3367
3440
  "storeId",
3368
3441
  "channelKey",
3369
3442
  "paymentId",
@@ -3378,6 +3451,11 @@ function validateNextAction(value, provider, resource, path) {
3378
3451
  path
3379
3452
  );
3380
3453
  if (action.version !== "v2") fail(resource, `${path}.version`, "v2");
3454
+ if (hasCancelable && action.cancelable !== false)
3455
+ fail(resource, `${path}.cancelable`, "false");
3456
+ if (hasRetryPolicy && action.retryPolicy !== "same_action_only") {
3457
+ fail(resource, `${path}.retryPolicy`, "same_action_only");
3458
+ }
3381
3459
  for (const key of ["storeId", "channelKey"]) {
3382
3460
  boundedString(action[key], 255, resource, `${path}.${key}`);
3383
3461
  }
@@ -3424,6 +3502,10 @@ function validateNextAction(value, provider, resource, path) {
3424
3502
  "HTTPS or loopback URL without embedded credentials"
3425
3503
  );
3426
3504
  }
3505
+ if (!hasCancelable) {
3506
+ action.cancelable = false;
3507
+ action.retryPolicy = "same_action_only";
3508
+ }
3427
3509
  return;
3428
3510
  }
3429
3511
  exact(action, ["type", "checkoutUrl"], [], resource, path);
@@ -3500,7 +3582,7 @@ function validateNextAction(value, provider, resource, path) {
3500
3582
  if (action.customerEmail !== void 0)
3501
3583
  validateCustomer({ email: action.customerEmail }, resource, path);
3502
3584
  }
3503
- function validatePublicPaymentSession(value, expectedProvider) {
3585
+ function validatePublicPaymentSession(value, expectedProvider, operation2) {
3504
3586
  const resource = "PaymentSession";
3505
3587
  const session = record(value, resource, "$");
3506
3588
  const provider = enumValue(
@@ -3509,9 +3591,6 @@ function validatePublicPaymentSession(value, expectedProvider) {
3509
3591
  resource,
3510
3592
  "$.provider"
3511
3593
  );
3512
- if (expectedProvider !== void 0 && provider !== expectedProvider) {
3513
- fail(resource, "$.provider", expectedProvider);
3514
- }
3515
3594
  const status = enumValue(
3516
3595
  session.providerStatus,
3517
3596
  PAYMENT_PROVIDER_STATUSES,
@@ -3715,44 +3794,128 @@ function validatePublicPaymentSession(value, expectedProvider) {
3715
3794
  "$.cancellationReason"
3716
3795
  );
3717
3796
  }
3797
+ if (expectedProvider !== void 0 && provider !== expectedProvider) {
3798
+ if (operation2 === "cancel" && status !== "canceling" && status !== "canceled") {
3799
+ fail(
3800
+ resource,
3801
+ "$.providerStatus",
3802
+ "canceling or canceled after a successful cancellation"
3803
+ );
3804
+ }
3805
+ providerMismatch(resource, expectedProvider, provider, operation2);
3806
+ }
3718
3807
  return value;
3719
3808
  }
3720
3809
 
3721
3810
  // src/core/customer/customer-auth.ts
3722
3811
  var DEFAULT_TIMEOUT2 = 15e3;
3723
- function safeGetItem(key) {
3812
+ var REFRESH_LOCK_TIMEOUT = DEFAULT_TIMEOUT2 * 3;
3813
+ var SESSION_RECORD_VERSION = 1;
3814
+ var STORAGE_UNUSABLE = /* @__PURE__ */ Symbol("storage-unusable");
3815
+ function canonicalApiIdentity(apiUrl) {
3724
3816
  try {
3725
- return localStorage.getItem(key);
3817
+ const url = new URL(apiUrl);
3818
+ return `${url.protocol.toLowerCase()}//${url.host.toLowerCase()}${url.pathname.replace(/\/+$/, "")}`;
3819
+ } catch {
3820
+ return apiUrl.trim().toLowerCase().replace(/\/+$/, "");
3821
+ }
3822
+ }
3823
+ function buildRefreshLockName(apiUrl, publishableKey, storageKey) {
3824
+ return `01software:customer-auth-refresh:${canonicalApiIdentity(apiUrl)}:${publishableKey}:${storageKey}`;
3825
+ }
3826
+ function getRefreshLockRequester() {
3827
+ try {
3828
+ if (typeof navigator === "undefined") return null;
3829
+ const locks = navigator.locks;
3830
+ if (!locks || typeof locks.request !== "function") return null;
3831
+ return (name, options, callback) => locks.request(
3832
+ name,
3833
+ options,
3834
+ () => callback()
3835
+ );
3726
3836
  } catch {
3727
3837
  return null;
3728
3838
  }
3729
3839
  }
3840
+ function parseSessionRecord(raw) {
3841
+ try {
3842
+ const parsed = JSON.parse(raw);
3843
+ if (!parsed || typeof parsed !== "object") return null;
3844
+ const candidate = parsed;
3845
+ if (candidate.v !== SESSION_RECORD_VERSION) return null;
3846
+ if (typeof candidate.rev !== "number" || !Number.isFinite(candidate.rev)) {
3847
+ return null;
3848
+ }
3849
+ const token = candidate.token;
3850
+ const refreshToken = candidate.refreshToken;
3851
+ if (token !== null && typeof token !== "string") return null;
3852
+ if (refreshToken !== null && typeof refreshToken !== "string") return null;
3853
+ return {
3854
+ v: SESSION_RECORD_VERSION,
3855
+ rev: candidate.rev,
3856
+ token,
3857
+ refreshToken
3858
+ };
3859
+ } catch {
3860
+ return null;
3861
+ }
3862
+ }
3863
+ function readSessionRecord(recordKey, mirrorKey, mirrorRefreshKey) {
3864
+ let raw;
3865
+ try {
3866
+ raw = localStorage.getItem(recordKey);
3867
+ } catch {
3868
+ return STORAGE_UNUSABLE;
3869
+ }
3870
+ if (raw !== null) {
3871
+ const parsed = parseSessionRecord(raw);
3872
+ return parsed ? { record: parsed, stored: true } : STORAGE_UNUSABLE;
3873
+ }
3874
+ try {
3875
+ return {
3876
+ record: {
3877
+ v: SESSION_RECORD_VERSION,
3878
+ rev: 0,
3879
+ token: localStorage.getItem(mirrorKey),
3880
+ refreshToken: localStorage.getItem(mirrorRefreshKey)
3881
+ },
3882
+ stored: false
3883
+ };
3884
+ } catch {
3885
+ return STORAGE_UNUSABLE;
3886
+ }
3887
+ }
3730
3888
  var CustomerAuth = class {
3731
3889
  constructor(publishableKey, options, apiUrl) {
3732
3890
  this.refreshPromise = null;
3891
+ /** Canonical record key; null unless persistence is active in a browser. */
3892
+ this.persistRecordKey = null;
3893
+ /** Advisory single-value access mirror, plus the retired refresh mirror. */
3894
+ this.persistMirrorKey = null;
3895
+ this.persistMirrorRefreshKey = null;
3896
+ /** Cross-context refresh lock name; null when there is no shared storage. */
3897
+ this.refreshLockName = null;
3898
+ /** Revision of the canonical record this instance last observed. */
3899
+ this.sessionRev = 0;
3733
3900
  this.publishableKey = publishableKey;
3734
3901
  this.baseUrl = resolveApiUrl(apiUrl);
3735
3902
  const persist = options?.persist ?? true;
3736
3903
  if (persist) {
3737
3904
  const key = typeof persist === "string" ? persist : "customer-token";
3738
- const refreshKey = `${key}:refresh`;
3739
3905
  const isBrowser = typeof window !== "undefined";
3740
- this.token = isBrowser ? safeGetItem(key) : null;
3741
- this.refreshTokenValue = isBrowser ? safeGetItem(refreshKey) : null;
3742
- this.onTokenChange = isBrowser ? (token) => {
3743
- try {
3744
- if (token) localStorage.setItem(key, token);
3745
- else localStorage.removeItem(key);
3746
- } catch {
3747
- }
3748
- } : void 0;
3749
- this.onRefreshTokenChange = isBrowser ? (refreshToken) => {
3750
- try {
3751
- if (refreshToken) localStorage.setItem(refreshKey, refreshToken);
3752
- else localStorage.removeItem(refreshKey);
3753
- } catch {
3754
- }
3755
- } : void 0;
3906
+ this.token = null;
3907
+ this.refreshTokenValue = null;
3908
+ if (isBrowser) {
3909
+ this.persistRecordKey = `${key}:session`;
3910
+ this.persistMirrorKey = key;
3911
+ this.persistMirrorRefreshKey = `${key}:refresh`;
3912
+ this.refreshLockName = buildRefreshLockName(
3913
+ this.baseUrl,
3914
+ publishableKey,
3915
+ key
3916
+ );
3917
+ this.syncFromPersistedStorage();
3918
+ }
3756
3919
  } else {
3757
3920
  this.token = options?.token ?? null;
3758
3921
  this.refreshTokenValue = options?.refreshToken ?? null;
@@ -3780,66 +3943,299 @@ var CustomerAuth = class {
3780
3943
  body: JSON.stringify(data)
3781
3944
  }
3782
3945
  );
3783
- this.setToken(result.token);
3784
- if (result.refreshToken) this.setRefreshToken(result.refreshToken);
3946
+ if (result.refreshToken) this.setSession(result.token, result.refreshToken);
3947
+ else this.setToken(result.token);
3785
3948
  return result;
3786
3949
  }
3787
3950
  /**
3788
3951
  * Refresh the current token. Uses a refresh token when available, otherwise
3789
3952
  * falls back to the legacy bearer-token compatibility path.
3953
+ *
3954
+ * Refresh tokens are single-use, so a persisted session shared by several
3955
+ * tabs or SDK instances must rotate at most once: concurrent rotations of the
3956
+ * same token are replay from the server's point of view and revoke the whole
3957
+ * family. Persisted browser sessions therefore serialize rotation across
3958
+ * contexts and re-read the canonical persisted credentials inside the lock.
3790
3959
  */
3791
3960
  async refreshToken() {
3961
+ this.syncFromPersistedStorage();
3792
3962
  if (!this.refreshTokenValue && !this.token) {
3793
3963
  throw new ApiError("Not authenticated", 401);
3794
3964
  }
3795
3965
  if (this.refreshPromise) return this.refreshPromise;
3796
- this.refreshPromise = this._doRefreshToken();
3966
+ const intended = this.currentFence();
3967
+ this.refreshPromise = this.rotateAcrossContexts(intended);
3797
3968
  try {
3798
3969
  return await this.refreshPromise;
3799
3970
  } finally {
3800
3971
  this.refreshPromise = null;
3801
3972
  }
3802
3973
  }
3803
- async _doRefreshToken() {
3804
- const init = this.refreshTokenValue ? {
3974
+ /**
3975
+ * Re-read the canonical persisted session. In persisted mode the shared
3976
+ * record — not this instance's memory — is the source of truth, so another
3977
+ * context's rotation, login, or logout is observed before the next credential
3978
+ * use. Change callbacks are deliberately not invoked: this is a read.
3979
+ */
3980
+ syncFromPersistedStorage() {
3981
+ const canonical = this.readCanonicalSession();
3982
+ if (canonical === STORAGE_UNUSABLE) {
3983
+ this.disablePersistence();
3984
+ return;
3985
+ }
3986
+ if (!canonical) return;
3987
+ this.sessionRev = canonical.record.rev;
3988
+ this.token = canonical.record.token;
3989
+ this.refreshTokenValue = canonical.record.refreshToken;
3990
+ }
3991
+ /** `null` when this instance does not persist. */
3992
+ readCanonicalSession() {
3993
+ if (!this.persistRecordKey || !this.persistMirrorKey || !this.persistMirrorRefreshKey) {
3994
+ return null;
3995
+ }
3996
+ return readSessionRecord(
3997
+ this.persistRecordKey,
3998
+ this.persistMirrorKey,
3999
+ this.persistMirrorRefreshKey
4000
+ );
4001
+ }
4002
+ /**
4003
+ * Publish a change to canonical storage.
4004
+ *
4005
+ * The canonical pair is re-read immediately before the single record write so
4006
+ * that a field this call does not change is taken from that read rather than
4007
+ * from this instance's possibly stale copy. That merge is BEST-EFFORT: it
4008
+ * removes the stale counterpart an instance would otherwise carry, but it is
4009
+ * not a compare-and-swap. Web Storage offers none, and the synchronous public
4010
+ * mutators cannot await the refresh lease, so a commit that lands between
4011
+ * this read and the store operation is lost by ordering — including the
4012
+ * counterpart just read, which is then republished stale. The window is one
4013
+ * store operation wide and the server remains authoritative; see
4014
+ * `CUST-AUTH-033` for the stated limit.
4015
+ *
4016
+ * Returns `false` only when `requireLiveSession` refused a write because the
4017
+ * canonical session had already been cleared.
4018
+ */
4019
+ commitPersistedSession(change, options) {
4020
+ const recordKey = this.persistRecordKey;
4021
+ const mirrorKey = this.persistMirrorKey;
4022
+ const mirrorRefreshKey = this.persistMirrorRefreshKey;
4023
+ const canonical = this.readCanonicalSession();
4024
+ if (canonical === null || !recordKey || !mirrorKey || !mirrorRefreshKey) {
4025
+ return true;
4026
+ }
4027
+ if (canonical === STORAGE_UNUSABLE) {
4028
+ this.disablePersistence();
4029
+ return true;
4030
+ }
4031
+ const current = canonical.record;
4032
+ if (options?.requireLiveSession && !current.token && !current.refreshToken) {
4033
+ return false;
4034
+ }
4035
+ const next = {
4036
+ v: SESSION_RECORD_VERSION,
4037
+ rev: current.rev + 1,
4038
+ token: "token" in change ? change.token ?? null : current.token,
4039
+ refreshToken: "refreshToken" in change ? change.refreshToken ?? null : current.refreshToken
4040
+ };
4041
+ if (
4042
+ // Only a state that is genuinely persisted can already say what this
4043
+ // write would say. An absent record reads as an empty pair, and treating
4044
+ // that as a no-op would drop the very tombstone that stops a later
4045
+ // migration from resurrecting the session out of the earlier layout.
4046
+ canonical.stored && next.token === current.token && next.refreshToken === current.refreshToken
4047
+ ) {
4048
+ this.sessionRev = current.rev;
4049
+ this.token = current.token;
4050
+ this.refreshTokenValue = current.refreshToken;
4051
+ return true;
4052
+ }
4053
+ try {
4054
+ localStorage.setItem(recordKey, JSON.stringify(next));
4055
+ } catch {
4056
+ this.disablePersistence();
4057
+ return true;
4058
+ }
4059
+ this.sessionRev = next.rev;
4060
+ this.token = next.token;
4061
+ this.refreshTokenValue = next.refreshToken;
4062
+ try {
4063
+ localStorage.removeItem(mirrorRefreshKey);
4064
+ } catch {
4065
+ return true;
4066
+ }
4067
+ try {
4068
+ if (next.token) localStorage.setItem(mirrorKey, next.token);
4069
+ else localStorage.removeItem(mirrorKey);
4070
+ } catch {
4071
+ }
4072
+ return true;
4073
+ }
4074
+ /**
4075
+ * Storage rejected a write or a read, so it is not a canonical store for this
4076
+ * instance. Fall back to the memory-only session and take no lease: there is
4077
+ * no shared state left to coordinate. Nothing is purged — the record commit
4078
+ * is atomic, so no inconsistent state was published, and another context's
4079
+ * valid session must not be destroyed by this instance's local failure.
4080
+ */
4081
+ disablePersistence() {
4082
+ this.persistRecordKey = null;
4083
+ this.persistMirrorKey = null;
4084
+ this.persistMirrorRefreshKey = null;
4085
+ this.refreshLockName = null;
4086
+ }
4087
+ /**
4088
+ * Compare the canonical record with the fence this call captured before it
4089
+ * left. Every persisted decision — rotate, converge, or fail closed — goes
4090
+ * through this one comparison. The revision catches a logout, a fresh login,
4091
+ * or a manual setter even when token values coincide; the value comparison
4092
+ * additionally catches a mirror-only writer that cannot bump a revision.
4093
+ */
4094
+ classifyCanonicalState(intended) {
4095
+ if (!this.persistRecordKey) return "current";
4096
+ this.syncFromPersistedStorage();
4097
+ if (!this.persistRecordKey) return "current";
4098
+ if (!this.token && !this.refreshTokenValue) return "cleared";
4099
+ if (intended.refreshToken !== null) {
4100
+ return this.refreshTokenValue === intended.refreshToken ? "current" : "superseded";
4101
+ }
4102
+ return this.token === intended.token && !this.refreshTokenValue ? "current" : "superseded";
4103
+ }
4104
+ /** The canonical persisted pair, as a refresh result. */
4105
+ canonicalPair(token) {
4106
+ return {
4107
+ token,
4108
+ ...this.refreshTokenValue ? { refreshToken: this.refreshTokenValue } : {}
4109
+ };
4110
+ }
4111
+ /** Current credentials plus the revision they were observed at. */
4112
+ currentFence() {
4113
+ return { token: this.token, refreshToken: this.refreshTokenValue };
4114
+ }
4115
+ /**
4116
+ * Clear an access credential a 401 just proved unusable — but only while it
4117
+ * is still the canonical one. A rotation committed by another context while
4118
+ * the request was in flight is newer than this 401, so it must survive; the
4119
+ * instance adopts it instead. The refresh entry is never touched here: a
4120
+ * rejected access token says nothing about the refresh family.
4121
+ */
4122
+ invalidateAccessToken(spentToken) {
4123
+ this.syncFromPersistedStorage();
4124
+ if (this.token !== spentToken) return;
4125
+ this.setToken(null);
4126
+ }
4127
+ /** Commit both credentials in one canonical write. */
4128
+ setSession(token, refreshToken, options) {
4129
+ this.token = token;
4130
+ this.refreshTokenValue = refreshToken;
4131
+ const committed = this.commitPersistedSession(
4132
+ { token, refreshToken },
4133
+ options
4134
+ );
4135
+ if (!committed) return false;
4136
+ this.onTokenChange?.(this.token);
4137
+ this.onRefreshTokenChange?.(this.refreshTokenValue);
4138
+ return true;
4139
+ }
4140
+ /**
4141
+ * Serialize rotation against every other context sharing the same storage
4142
+ * key and API/tenant identity. Coordination is best-effort: when it is
4143
+ * unavailable or times out the rotation still happens, so server-side reuse
4144
+ * detection is never bypassed by a client that failed to coordinate.
4145
+ */
4146
+ async rotateAcrossContexts(intended) {
4147
+ const lockName = this.refreshLockName;
4148
+ const requestLock = lockName ? getRefreshLockRequester() : null;
4149
+ if (!lockName || !requestLock) {
4150
+ return this.rotateWithCanonicalState(intended);
4151
+ }
4152
+ const controller = new AbortController();
4153
+ const timer = setTimeout(() => controller.abort(), REFRESH_LOCK_TIMEOUT);
4154
+ let entered = false;
4155
+ try {
4156
+ return await requestLock(
4157
+ lockName,
4158
+ { signal: controller.signal },
4159
+ async () => {
4160
+ entered = true;
4161
+ return this.rotateWithCanonicalState(intended);
4162
+ }
4163
+ );
4164
+ } catch (error) {
4165
+ if (entered) throw error;
4166
+ return this.rotateWithCanonicalState(intended);
4167
+ } finally {
4168
+ clearTimeout(timer);
4169
+ }
4170
+ }
4171
+ /**
4172
+ * Decide, against freshly re-read canonical state, whether this context still
4173
+ * owns the rotation.
4174
+ */
4175
+ async rotateWithCanonicalState(intended) {
4176
+ let fence = intended;
4177
+ for (let attempt = 0; attempt < 2; attempt += 1) {
4178
+ const state = this.classifyCanonicalState(fence);
4179
+ if (state === "cleared") throw new ApiError("Not authenticated", 401);
4180
+ if (state === "current") return this._doRefreshToken(fence);
4181
+ if (this.token) return this.canonicalPair(this.token);
4182
+ fence = this.currentFence();
4183
+ }
4184
+ throw new ApiError("Not authenticated", 401);
4185
+ }
4186
+ async _doRefreshToken(intended) {
4187
+ const init = intended.refreshToken ? {
3805
4188
  method: "POST",
3806
- body: JSON.stringify({ refreshToken: this.refreshTokenValue })
4189
+ body: JSON.stringify({ refreshToken: intended.refreshToken })
3807
4190
  } : {
3808
4191
  method: "POST",
3809
- headers: { Authorization: `Bearer ${this.token}` }
4192
+ headers: { Authorization: `Bearer ${intended.token}` }
3810
4193
  };
3811
4194
  const result = await this.requestJson(
3812
4195
  "/api/customers/refresh",
3813
4196
  init
3814
4197
  );
3815
- this.setToken(result.token);
3816
- if (result.refreshToken) this.setRefreshToken(result.refreshToken);
3817
- return result;
4198
+ const state = this.classifyCanonicalState(intended);
4199
+ if (state === "cleared") throw new ApiError("Not authenticated", 401);
4200
+ if (state === "superseded") {
4201
+ if (this.token) return this.canonicalPair(this.token);
4202
+ throw new ApiError("Not authenticated", 401);
4203
+ }
4204
+ const replacedAccessToken = this.token !== null && this.token !== intended.token ? this.token : null;
4205
+ const nextToken = replacedAccessToken ?? result.token;
4206
+ const nextRefresh = result.refreshToken ?? null;
4207
+ if (!this.setSession(nextToken, nextRefresh, { requireLiveSession: true })) {
4208
+ throw new ApiError("Not authenticated", 401);
4209
+ }
4210
+ return {
4211
+ token: nextToken,
4212
+ ...nextRefresh ? { refreshToken: nextRefresh } : {}
4213
+ };
3818
4214
  }
3819
4215
  /**
3820
4216
  * Clear the stored token
3821
4217
  */
3822
4218
  logout() {
3823
- this.setToken(null);
3824
- this.setRefreshToken(null);
4219
+ this.setSession(null, null);
3825
4220
  }
3826
4221
  /**
3827
4222
  * Get the current authenticated customer's profile
3828
4223
  */
3829
4224
  async me() {
3830
- if (!this.token) return null;
4225
+ const token = this.getToken();
4226
+ if (!token) return null;
3831
4227
  try {
3832
4228
  const data = await this.requestJson(
3833
4229
  "/api/customers/me",
3834
4230
  {
3835
4231
  method: "GET",
3836
- headers: { Authorization: `Bearer ${this.token}` }
4232
+ headers: { Authorization: `Bearer ${token}` }
3837
4233
  }
3838
4234
  );
3839
4235
  return data.customer ?? null;
3840
4236
  } catch (error) {
3841
4237
  if (error instanceof SDKError && error.status === 401) {
3842
- this.setToken(null);
4238
+ this.invalidateAccessToken(token);
3843
4239
  return null;
3844
4240
  }
3845
4241
  throw error;
@@ -3867,12 +4263,13 @@ var CustomerAuth = class {
3867
4263
  * Update the authenticated customer's profile (name, phone, marketingConsent)
3868
4264
  */
3869
4265
  async updateProfile(data) {
3870
- if (!this.token) throw new ApiError("Not authenticated", 401);
4266
+ const token = this.getToken();
4267
+ if (!token) throw new ApiError("Not authenticated", 401);
3871
4268
  const result = await this.requestJson(
3872
4269
  "/api/customers/me",
3873
4270
  {
3874
4271
  method: "PATCH",
3875
- headers: { Authorization: `Bearer ${this.token}` },
4272
+ headers: { Authorization: `Bearer ${token}` },
3876
4273
  body: JSON.stringify(data)
3877
4274
  }
3878
4275
  );
@@ -3882,10 +4279,11 @@ var CustomerAuth = class {
3882
4279
  * Change the password of the currently authenticated customer
3883
4280
  */
3884
4281
  async changePassword(currentPassword, newPassword) {
3885
- if (!this.token) throw new ApiError("Not authenticated", 401);
4282
+ const token = this.getToken();
4283
+ if (!token) throw new ApiError("Not authenticated", 401);
3886
4284
  await this.requestJson("/api/customers/change-password", {
3887
4285
  method: "POST",
3888
- headers: { Authorization: `Bearer ${this.token}` },
4286
+ headers: { Authorization: `Bearer ${token}` },
3889
4287
  body: JSON.stringify({ currentPassword, newPassword })
3890
4288
  });
3891
4289
  }
@@ -3893,7 +4291,8 @@ var CustomerAuth = class {
3893
4291
  * Get the authenticated customer's orders with pagination and optional status filter
3894
4292
  */
3895
4293
  async getMyOrders(options) {
3896
- if (!this.token) throw new ApiError("Not authenticated", 401);
4294
+ const token = this.getToken();
4295
+ if (!token) throw new ApiError("Not authenticated", 401);
3897
4296
  const params = new URLSearchParams();
3898
4297
  if (options?.page) params.set("page", String(options.page));
3899
4298
  if (options?.limit) params.set("limit", String(options.limit));
@@ -3915,21 +4314,27 @@ var CustomerAuth = class {
3915
4314
  `/api/customers/me/orders${qs ? `?${qs}` : ""}`,
3916
4315
  {
3917
4316
  method: "GET",
3918
- headers: { Authorization: `Bearer ${this.token}` }
4317
+ headers: { Authorization: `Bearer ${token}` }
3919
4318
  }
3920
4319
  );
3921
4320
  return validatePublicOrderList(result);
3922
4321
  }
3923
4322
  /**
3924
- * Get the current token (or null if not authenticated)
4323
+ * Get the current token (or null if not authenticated).
4324
+ *
4325
+ * In persisted mode this re-reads shared storage first, so a rotation or
4326
+ * logout performed by another tab is observed before the token is used.
3925
4327
  */
3926
4328
  getToken() {
4329
+ this.syncFromPersistedStorage();
3927
4330
  return this.token;
3928
4331
  }
3929
4332
  /**
3930
- * Get the current refresh token (or null if unavailable)
4333
+ * Get the current refresh token (or null if unavailable). Persisted mode
4334
+ * re-reads shared storage first, like {@link CustomerAuth.getToken}.
3931
4335
  */
3932
4336
  getRefreshToken() {
4337
+ this.syncFromPersistedStorage();
3933
4338
  return this.refreshTokenValue;
3934
4339
  }
3935
4340
  /**
@@ -3937,6 +4342,7 @@ var CustomerAuth = class {
3937
4342
  */
3938
4343
  setToken(token) {
3939
4344
  this.token = token;
4345
+ this.commitPersistedSession({ token });
3940
4346
  this.onTokenChange?.(token);
3941
4347
  }
3942
4348
  /**
@@ -3944,13 +4350,14 @@ var CustomerAuth = class {
3944
4350
  */
3945
4351
  setRefreshToken(refreshToken) {
3946
4352
  this.refreshTokenValue = refreshToken;
4353
+ this.commitPersistedSession({ refreshToken });
3947
4354
  this.onRefreshTokenChange?.(refreshToken);
3948
4355
  }
3949
4356
  /**
3950
4357
  * Check if the customer is currently authenticated
3951
4358
  */
3952
4359
  isAuthenticated() {
3953
- return this.token !== null;
4360
+ return this.getToken() !== null;
3954
4361
  }
3955
4362
  /**
3956
4363
  * Internal: make a request with timeout and error handling.
@@ -4154,8 +4561,8 @@ var CartApi = class extends CustomerScopedApi {
4154
4561
  endpoint(key) {
4155
4562
  return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
4156
4563
  }
4157
- execute(endpoint2, body, idempotencyKey) {
4158
- return this.requestEndpoint(endpoint2, body, {
4564
+ execute(endpoint, body, idempotencyKey) {
4565
+ return this.requestEndpoint(endpoint, body, {
4159
4566
  ...idempotencyKey && {
4160
4567
  headers: { "X-Idempotency-Key": idempotencyKey }
4161
4568
  }
@@ -4172,26 +4579,26 @@ var CartApi = class extends CustomerScopedApi {
4172
4579
  );
4173
4580
  }
4174
4581
  mine(params = {}) {
4175
- const endpoint2 = this.endpoint("mine");
4176
- return this.execute(endpoint2, params).then(
4582
+ const endpoint = this.endpoint("mine");
4583
+ return this.execute(endpoint, params).then(
4177
4584
  (value) => validateCartMineResult(value)
4178
4585
  );
4179
4586
  }
4180
4587
  merge(params) {
4181
4588
  const { idempotencyKey, ...body } = params;
4182
4589
  assertCommerceIdempotencyKey(idempotencyKey);
4183
- const endpoint2 = this.endpoint("merge");
4184
- return this.execute(endpoint2, body, idempotencyKey).then(
4590
+ const endpoint = this.endpoint("merge");
4591
+ return this.execute(endpoint, body, idempotencyKey).then(
4185
4592
  (value) => validateCartMergeResult(value)
4186
4593
  );
4187
4594
  }
4188
4595
  addItem(params) {
4189
4596
  return this.mutate(this.endpoint("addItem"), params);
4190
4597
  }
4191
- mutate(endpoint2, params) {
4598
+ mutate(endpoint, params) {
4192
4599
  const { idempotencyKey, ...body } = params;
4193
4600
  assertCommerceIdempotencyKey(idempotencyKey);
4194
- return this.execute(endpoint2, body, idempotencyKey).then(
4601
+ return this.execute(endpoint, body, idempotencyKey).then(
4195
4602
  (value) => validateCartMutationResult(value)
4196
4603
  );
4197
4604
  }
@@ -4217,8 +4624,8 @@ var CheckoutApi = class extends CustomerScopedApi {
4217
4624
  constructor(options) {
4218
4625
  super("CheckoutApi", { ...options, requiresCredential: false });
4219
4626
  }
4220
- post(endpoint2, body, idempotencyKey) {
4221
- return this.requestEndpoint(endpoint2, body, {
4627
+ post(endpoint, body, idempotencyKey) {
4628
+ return this.requestEndpoint(endpoint, body, {
4222
4629
  ...idempotencyKey && {
4223
4630
  headers: { "X-Idempotency-Key": idempotencyKey }
4224
4631
  }
@@ -4285,15 +4692,23 @@ var PaymentSessionApi = class extends CustomerScopedApi {
4285
4692
  super("PaymentSessionApi", { ...options, requiresCredential: false });
4286
4693
  this.serverTransport = Boolean(options.secretKey);
4287
4694
  }
4288
- post(endpoint2, body, idempotencyKey) {
4289
- return this.requestEndpoint(endpoint2, body, {
4290
- ...idempotencyKey && {
4291
- headers: { "X-Idempotency-Key": idempotencyKey }
4695
+ post(endpoint, body, idempotencyKey, negotiateStandardActionCapabilities = false) {
4696
+ const headers = {
4697
+ ...idempotencyKey && { "X-Idempotency-Key": idempotencyKey },
4698
+ ...negotiateStandardActionCapabilities && {
4699
+ Accept: PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE
4292
4700
  }
4701
+ };
4702
+ return this.requestEndpoint(endpoint, body, {
4703
+ ...Object.keys(headers).length > 0 && { headers }
4293
4704
  });
4294
4705
  }
4295
- async paymentSession(result, expectedProvider) {
4296
- return validatePublicPaymentSession(await result, expectedProvider);
4706
+ async paymentSession(result, expectedProvider, operation2) {
4707
+ return validatePublicPaymentSession(
4708
+ await result,
4709
+ expectedProvider,
4710
+ operation2
4711
+ );
4297
4712
  }
4298
4713
  create(params) {
4299
4714
  const { idempotencyKey, ...body } = params;
@@ -4314,41 +4729,44 @@ var PaymentSessionApi = class extends CustomerScopedApi {
4314
4729
  this.post(
4315
4730
  this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
4316
4731
  body,
4317
- idempotencyKey
4732
+ idempotencyKey,
4733
+ body.providerOptions.profile === "standard_v2"
4318
4734
  ),
4319
4735
  "portone"
4320
4736
  );
4321
4737
  }
4322
4738
  retrieve(params) {
4323
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4739
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4324
4740
  return this.paymentSession(
4325
- this.post(endpoint2, params),
4741
+ this.post(endpoint, params),
4326
4742
  "toss"
4327
4743
  );
4328
4744
  }
4329
4745
  retrievePortOne(params) {
4330
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4746
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4331
4747
  return this.paymentSession(
4332
- this.post(endpoint2, params),
4748
+ this.post(endpoint, params, void 0, true),
4333
4749
  "portone"
4334
4750
  );
4335
4751
  }
4336
4752
  cancel(params) {
4337
4753
  const { idempotencyKey, ...body } = params;
4338
4754
  assertCommerceIdempotencyKey(idempotencyKey);
4339
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4755
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4340
4756
  return this.paymentSession(
4341
- this.post(endpoint2, body, idempotencyKey),
4342
- "toss"
4757
+ this.post(endpoint, body, idempotencyKey),
4758
+ "toss",
4759
+ "cancel"
4343
4760
  );
4344
4761
  }
4345
4762
  cancelPortOne(params) {
4346
4763
  const { idempotencyKey, ...body } = params;
4347
4764
  assertCommerceIdempotencyKey(idempotencyKey);
4348
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4765
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4349
4766
  return this.paymentSession(
4350
- this.post(endpoint2, body, idempotencyKey),
4351
- "portone"
4767
+ this.post(endpoint, body, idempotencyKey),
4768
+ "portone",
4769
+ "cancel"
4352
4770
  );
4353
4771
  }
4354
4772
  confirm(params) {
@@ -5488,8 +5906,8 @@ function withProductListingCards(response, options) {
5488
5906
 
5489
5907
  // src/core/commerce/commerce-client.ts
5490
5908
  var BrowserCommerceApi = class extends CustomerScopedApi {
5491
- requestEndpoint(endpoint2, body, options) {
5492
- return super.requestEndpoint(endpoint2, body, options);
5909
+ requestEndpoint(endpoint, body, options) {
5910
+ return super.requestEndpoint(endpoint, body, options);
5493
5911
  }
5494
5912
  };
5495
5913
  var CommerceClient = class {
@@ -5689,11 +6107,11 @@ var EventsClient = class {
5689
6107
  { useCustomerAuth: false }
5690
6108
  );
5691
6109
  }
5692
- async execute(endpoint2, method, body, options = {}) {
6110
+ async execute(endpoint, method, body, options = {}) {
5693
6111
  const useCustomerAuth = options.useCustomerAuth === true;
5694
6112
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
5695
6113
  try {
5696
- const response = await httpFetch(endpoint2, {
6114
+ const response = await httpFetch(endpoint, {
5697
6115
  method,
5698
6116
  apiUrl: this.apiUrl,
5699
6117
  publishableKey: this.publishableKey,
@@ -5702,7 +6120,7 @@ var EventsClient = class {
5702
6120
  ...body !== void 0 && { body: JSON.stringify(body) }
5703
6121
  });
5704
6122
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
5705
- return parseApiResponse(response, endpoint2);
6123
+ return parseApiResponse(response, endpoint);
5706
6124
  } catch (err) {
5707
6125
  const id = err instanceof SDKError ? err.requestId ?? null : null;
5708
6126
  this.onRequestId?.(id);