@01.software/sdk 0.48.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.md +157 -1
  2. package/MIGRATION.md +56 -0
  3. package/README.md +276 -49
  4. package/dist/client.cjs +375 -161
  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 +375 -161
  9. package/dist/client.js.map +1 -1
  10. package/dist/{collection-client-CBup9yOx.d.cts → collection-client-CWAeuzV4.d.cts} +6 -4
  11. package/dist/{collection-client-D3ExJU-7.d.ts → collection-client-hYvVfHIm.d.ts} +6 -4
  12. package/dist/{const-k9gHylYa.d.ts → const-D8LixhAJ.d.cts} +5 -5
  13. package/dist/{const-BXEi1Kix.d.cts → const-JD8obaKg.d.ts} +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 +64 -15
  27. package/dist/errors.cjs.map +1 -1
  28. package/dist/errors.d.cts +13 -4
  29. package/dist/errors.d.ts +13 -4
  30. package/dist/errors.js +64 -15
  31. package/dist/errors.js.map +1 -1
  32. package/dist/{index-BCM9CTL7.d.cts → index-B0Hjh3Ey.d.ts} +72 -10
  33. package/dist/{index-CHGGkcLj.d.ts → index-Bu0kCc6o.d.cts} +72 -10
  34. package/dist/index.cjs +470 -429
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +9 -67
  37. package/dist/index.d.ts +9 -67
  38. package/dist/index.js +470 -429
  39. package/dist/index.js.map +1 -1
  40. package/dist/{payload-types-B6AZQcB7.d.cts → payload-types-BOsckg8B.d.cts} +396 -57
  41. package/dist/{payload-types-B6AZQcB7.d.ts → payload-types-BOsckg8B.d.ts} +396 -57
  42. package/dist/query.cjs +115 -70
  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 +115 -70
  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 +591 -186
  51. package/dist/server.cjs.map +1 -1
  52. package/dist/server.d.cts +8 -7
  53. package/dist/server.d.ts +8 -7
  54. package/dist/server.js +591 -186
  55. package/dist/server.js.map +1 -1
  56. package/dist/storefront-cache.cjs +22 -0
  57. package/dist/storefront-cache.cjs.map +1 -1
  58. package/dist/storefront-cache.js +22 -0
  59. package/dist/storefront-cache.js.map +1 -1
  60. package/dist/{types-ByD2zii1.d.ts → types-5ZlcAFuU.d.ts} +2 -2
  61. package/dist/{types-8us-_C-Q.d.cts → types-B14sEt1z.d.cts} +2 -2
  62. package/dist/{types-CM2je9Kw.d.cts → types-Bj8j7VHU.d.ts} +107 -26
  63. package/dist/{types-DbA5V3mt.d.ts → types-CM5qiR2k.d.cts} +107 -26
  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 +124 -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 +124 -80
  73. package/dist/webhook.js.map +1 -1
  74. package/package.json +27 -5
package/dist/index.js CHANGED
@@ -2,6 +2,24 @@
2
2
  import { stringify } from "qs-esm";
3
3
 
4
4
  // src/core/errors.ts
5
+ var SDK_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError");
6
+ var SDK_ERROR_TYPE_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError.type");
7
+ function defineSDKErrorBrand(error) {
8
+ Object.defineProperty(error, SDK_ERROR_BRAND, {
9
+ value: true,
10
+ enumerable: false,
11
+ configurable: false,
12
+ writable: false
13
+ });
14
+ }
15
+ function defineSDKErrorType(error, type) {
16
+ Object.defineProperty(error, SDK_ERROR_TYPE_BRAND, {
17
+ value: type,
18
+ enumerable: false,
19
+ configurable: false,
20
+ writable: false
21
+ });
22
+ }
5
23
  var SDKError = class extends Error {
6
24
  constructor(code, message, status, details, userMessage, suggestion, requestId) {
7
25
  super(message);
@@ -12,6 +30,7 @@ var SDKError = class extends Error {
12
30
  this.userMessage = userMessage;
13
31
  this.suggestion = suggestion;
14
32
  this.requestId = requestId;
33
+ defineSDKErrorBrand(this);
15
34
  if (Error.captureStackTrace) {
16
35
  Error.captureStackTrace(this, new.target);
17
36
  }
@@ -32,6 +51,7 @@ var SDKError = class extends Error {
32
51
  ...this.kind !== void 0 && { kind: this.kind },
33
52
  ...this.reason !== void 0 && { reason: this.reason },
34
53
  ...this.rawReason !== void 0 && { rawReason: this.rawReason },
54
+ ...this.apiReason !== void 0 && { apiReason: this.apiReason },
35
55
  ...this.retryable !== void 0 && { retryable: this.retryable },
36
56
  ...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
37
57
  };
@@ -77,6 +97,7 @@ var COMMERCE_ERROR_CODES = [
77
97
  "payment_session_not_cancelable",
78
98
  "payment_session_conflict",
79
99
  "provider_identity_mismatch",
100
+ "managed_refund_attestation_forbidden",
80
101
  "payment_method_unavailable",
81
102
  "provider_unavailable",
82
103
  "lock_timeout",
@@ -205,8 +226,16 @@ function enhanceCommerceError(error, body, headerRequestId) {
205
226
  });
206
227
  return error;
207
228
  }
229
+ function enhanceNonCommerceError(error, reason) {
230
+ if (typeof reason === "string") Object.assign(error, { apiReason: reason });
231
+ return error;
232
+ }
233
+ function getSDKErrorReason(error) {
234
+ if (error.kind !== "commerce") return error.apiReason;
235
+ return error.reason === "unknown_commerce_error" ? error.rawReason : error.reason;
236
+ }
208
237
  function isCommerceSDKError(error) {
209
- if (!(error instanceof SDKError) || error.kind !== "commerce") return false;
238
+ if (!isSDKError(error) || error.kind !== "commerce") return false;
210
239
  if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
211
240
  return false;
212
241
  }
@@ -216,12 +245,14 @@ var NetworkError = class extends SDKError {
216
245
  constructor(message, status, details, userMessage, suggestion) {
217
246
  super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
218
247
  this.name = "NetworkError";
248
+ defineSDKErrorType(this, "NetworkError");
219
249
  }
220
250
  };
221
251
  var ValidationError = class extends SDKError {
222
252
  constructor(message, details, userMessage, suggestion, status = 400) {
223
253
  super("VALIDATION_ERROR", message, status, details, userMessage, suggestion);
224
254
  this.name = "ValidationError";
255
+ defineSDKErrorType(this, "ValidationError");
225
256
  }
226
257
  };
227
258
  var ApiError = class extends SDKError {
@@ -236,24 +267,28 @@ var ApiError = class extends SDKError {
236
267
  requestId
237
268
  );
238
269
  this.name = "ApiError";
270
+ defineSDKErrorType(this, "ApiError");
239
271
  }
240
272
  };
241
273
  var ConfigError = class extends SDKError {
242
274
  constructor(message, details, userMessage, suggestion) {
243
275
  super("CONFIG_ERROR", message, void 0, details, userMessage, suggestion);
244
276
  this.name = "ConfigError";
277
+ defineSDKErrorType(this, "ConfigError");
245
278
  }
246
279
  };
247
280
  var TimeoutError = class extends SDKError {
248
281
  constructor(message = "Request timed out.", details, userMessage, suggestion) {
249
282
  super("TIMEOUT_ERROR", message, 408, details, userMessage, suggestion);
250
283
  this.name = "TimeoutError";
284
+ defineSDKErrorType(this, "TimeoutError");
251
285
  }
252
286
  };
253
287
  var GoneError = class extends SDKError {
254
288
  constructor(message = "The requested resource is no longer available.", details, userMessage, suggestion) {
255
289
  super("GONE_ERROR", message, 410, details, userMessage, suggestion);
256
290
  this.name = "GoneError";
291
+ defineSDKErrorType(this, "GoneError");
257
292
  }
258
293
  };
259
294
  var ServiceUnavailableError = class extends SDKError {
@@ -268,6 +303,7 @@ var ServiceUnavailableError = class extends SDKError {
268
303
  );
269
304
  this.name = "ServiceUnavailableError";
270
305
  this.retryAfter = retryAfter;
306
+ defineSDKErrorType(this, "ServiceUnavailableError");
271
307
  }
272
308
  };
273
309
  var UsageLimitError = class extends SDKError {
@@ -275,6 +311,7 @@ var UsageLimitError = class extends SDKError {
275
311
  super("USAGE_LIMIT_ERROR", message, 429, details, userMessage, suggestion);
276
312
  this.name = "UsageLimitError";
277
313
  this.usage = usage;
314
+ defineSDKErrorType(this, "UsageLimitError");
278
315
  }
279
316
  toJSON() {
280
317
  return {
@@ -295,6 +332,7 @@ var AuthError = class extends SDKError {
295
332
  requestId
296
333
  );
297
334
  this.name = "AuthError";
335
+ defineSDKErrorType(this, "AuthError");
298
336
  }
299
337
  };
300
338
  var PermissionError = class extends SDKError {
@@ -309,6 +347,7 @@ var PermissionError = class extends SDKError {
309
347
  requestId
310
348
  );
311
349
  this.name = "PermissionError";
350
+ defineSDKErrorType(this, "PermissionError");
312
351
  }
313
352
  };
314
353
  var NotFoundError = class extends SDKError {
@@ -323,12 +362,14 @@ var NotFoundError = class extends SDKError {
323
362
  requestId
324
363
  );
325
364
  this.name = "NotFoundError";
365
+ defineSDKErrorType(this, "NotFoundError");
326
366
  }
327
367
  };
328
368
  var ConflictError = class extends SDKError {
329
369
  constructor(message, details, userMessage, suggestion, requestId) {
330
370
  super("conflict", message, 409, details, userMessage, suggestion, requestId);
331
371
  this.name = "ConflictError";
372
+ defineSDKErrorType(this, "ConflictError");
332
373
  }
333
374
  };
334
375
  var RateLimitError = class extends SDKError {
@@ -344,52 +385,63 @@ var RateLimitError = class extends SDKError {
344
385
  );
345
386
  this.name = "RateLimitError";
346
387
  this.retryAfter = retryAfter;
388
+ defineSDKErrorType(this, "RateLimitError");
347
389
  }
348
390
  };
391
+ function hasBrandedSDKErrorShape(error) {
392
+ if (error === null || typeof error !== "object") return false;
393
+ const candidate = error;
394
+ return candidate[SDK_ERROR_BRAND] === true && typeof candidate.name === "string" && typeof candidate.code === "string" && typeof candidate.message === "string" && (candidate.status === void 0 || typeof candidate.status === "number") && (candidate.userMessage === void 0 || typeof candidate.userMessage === "string") && (candidate.suggestion === void 0 || typeof candidate.suggestion === "string") && (candidate.requestId === void 0 || typeof candidate.requestId === "string") && (candidate.kind === void 0 || candidate.kind === "commerce") && (candidate.reason === void 0 || typeof candidate.reason === "string") && (candidate.rawReason === void 0 || typeof candidate.rawReason === "string") && (candidate.apiReason === void 0 || typeof candidate.apiReason === "string") && (candidate.retryable === void 0 || typeof candidate.retryable === "boolean") && (candidate.retryAfter === void 0 || typeof candidate.retryAfter === "number") && typeof candidate.getUserMessage === "function" && typeof candidate.toJSON === "function";
395
+ }
396
+ function hasSDKErrorType(error, type) {
397
+ return hasBrandedSDKErrorShape(error) && error[SDK_ERROR_TYPE_BRAND] === type;
398
+ }
349
399
  function isSDKError(error) {
350
- return error instanceof SDKError;
400
+ return error instanceof SDKError || hasBrandedSDKErrorShape(error);
351
401
  }
352
402
  function isNetworkError(error) {
353
- return error instanceof NetworkError;
403
+ return error instanceof NetworkError || hasSDKErrorType(error, "NetworkError");
354
404
  }
355
405
  function isValidationError(error) {
356
- if (error instanceof ValidationError) return true;
406
+ if (error instanceof ValidationError || hasSDKErrorType(error, "ValidationError")) {
407
+ return true;
408
+ }
357
409
  if (error == null || typeof error !== "object") return false;
358
410
  const candidate = error;
359
411
  return candidate.name === "ValidationError" && candidate.code === "VALIDATION_ERROR" && typeof candidate.message === "string" && typeof candidate.getUserMessage === "function" && typeof candidate.toJSON === "function";
360
412
  }
361
413
  function isApiError(error) {
362
- return error instanceof ApiError;
414
+ return error instanceof ApiError || hasSDKErrorType(error, "ApiError");
363
415
  }
364
416
  function isConfigError(error) {
365
- return error instanceof ConfigError;
417
+ return error instanceof ConfigError || hasSDKErrorType(error, "ConfigError");
366
418
  }
367
419
  function isTimeoutError(error) {
368
- return error instanceof TimeoutError;
420
+ return error instanceof TimeoutError || hasSDKErrorType(error, "TimeoutError");
369
421
  }
370
422
  function isGoneError(error) {
371
- return error instanceof GoneError;
423
+ return error instanceof GoneError || hasSDKErrorType(error, "GoneError");
372
424
  }
373
425
  function isServiceUnavailableError(error) {
374
- return error instanceof ServiceUnavailableError;
426
+ return error instanceof ServiceUnavailableError || hasSDKErrorType(error, "ServiceUnavailableError");
375
427
  }
376
428
  function isUsageLimitError(error) {
377
- return error instanceof UsageLimitError;
429
+ return error instanceof UsageLimitError || hasSDKErrorType(error, "UsageLimitError");
378
430
  }
379
431
  function isAuthError(error) {
380
- return error instanceof AuthError;
432
+ return error instanceof AuthError || hasSDKErrorType(error, "AuthError");
381
433
  }
382
434
  function isPermissionError(error) {
383
- return error instanceof PermissionError;
435
+ return error instanceof PermissionError || hasSDKErrorType(error, "PermissionError");
384
436
  }
385
437
  function isNotFoundError(error) {
386
- return error instanceof NotFoundError;
438
+ return error instanceof NotFoundError || hasSDKErrorType(error, "NotFoundError");
387
439
  }
388
440
  function isConflictError(error) {
389
- return error instanceof ConflictError;
441
+ return error instanceof ConflictError || hasSDKErrorType(error, "ConflictError");
390
442
  }
391
443
  function isRateLimitError(error) {
392
- return error instanceof RateLimitError;
444
+ return error instanceof RateLimitError || hasSDKErrorType(error, "RateLimitError");
393
445
  }
394
446
  var createNetworkError = (message, status, details, userMessage, suggestion) => new NetworkError(message, status, details, userMessage, suggestion);
395
447
  var createValidationError = (message, details, userMessage, suggestion, status) => new ValidationError(message, details, userMessage, suggestion, status);
@@ -588,11 +640,11 @@ function parseRetryAfter(response) {
588
640
  permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
589
641
  };
590
642
  }
591
- function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
643
+ function mapResponseToError(status, parsed, details, requestId, retryAfter, canonicalCommerceError) {
592
644
  const errorDetails = {
593
645
  ...details,
594
646
  ...parsed.errors && { errors: parsed.errors },
595
- ...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
647
+ ...!canonicalCommerceError && parsed.body && { body: parsed.body }
596
648
  };
597
649
  const suggestion = getParsedErrorSuggestion(status, parsed);
598
650
  const finalize = (error) => {
@@ -600,7 +652,7 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, erro
600
652
  if (retryAfter !== void 0) {
601
653
  Object.assign(withRequestId, { retryAfter });
602
654
  }
603
- return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
655
+ return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
604
656
  };
605
657
  if (status === 400 || status === 422) {
606
658
  return finalize(
@@ -706,6 +758,7 @@ async function httpFetch(url, options) {
706
758
  retry,
707
759
  onUnauthorized,
708
760
  errorFamily,
761
+ typedCommerceErrorReasons,
709
762
  ...requestInit
710
763
  } = options || {};
711
764
  const baseUrl = resolveApiUrl(apiUrl);
@@ -759,7 +812,8 @@ async function httpFetch(url, options) {
759
812
  });
760
813
  if (!response.ok) {
761
814
  const parsed = await parseErrorBody(response);
762
- const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
815
+ const canonicalCommerceError = errorFamily === "commerce" || typeof parsed.reason === "string" && typedCommerceErrorReasons?.includes(parsed.reason) === true;
816
+ const commerceEnvelope = canonicalCommerceError ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
763
817
  if (isUsageLimitExceededResponse(response)) {
764
818
  const limit = parseInt(
765
819
  response.headers.get("X-Usage-Limit") || "0",
@@ -787,7 +841,7 @@ async function httpFetch(url, options) {
787
841
  ),
788
842
  requestId
789
843
  );
790
- throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
844
+ throw canonicalCommerceError ? enhanceCommerceError(usageError, parsed.body, requestId) : enhanceNonCommerceError(usageError, parsed.reason);
791
845
  }
792
846
  if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
793
847
  hasRetried401 = true;
@@ -812,7 +866,7 @@ async function httpFetch(url, options) {
812
866
  details,
813
867
  requestId,
814
868
  retryAfter.seconds,
815
- errorFamily
869
+ canonicalCommerceError
816
870
  );
817
871
  const method2 = (requestInit.method || "GET").toUpperCase();
818
872
  const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
@@ -990,15 +1044,15 @@ var HttpClient = class {
990
1044
  throw err;
991
1045
  }
992
1046
  }
993
- buildUrl(endpoint2, options) {
994
- if (!options) return endpoint2;
1047
+ buildUrl(endpoint, options) {
1048
+ if (!options) return endpoint;
995
1049
  const { fallbackLocale, ...rest } = options;
996
1050
  const queryOptions = fallbackLocale === void 0 ? rest : {
997
1051
  ...rest,
998
1052
  "fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
999
1053
  };
1000
1054
  const queryString = stringify(queryOptions, { addQueryPrefix: true });
1001
- return queryString ? `${endpoint2}${queryString}` : endpoint2;
1055
+ return queryString ? `${endpoint}${queryString}` : endpoint;
1002
1056
  }
1003
1057
  assertJsonResponse(response) {
1004
1058
  const contentType = response.headers.get("content-type");
@@ -1147,39 +1201,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
1147
1201
  from(collection) {
1148
1202
  return new ReadOnlyCollectionQueryBuilder(this, collection);
1149
1203
  }
1150
- async requestFind(endpoint2, options) {
1151
- const url = this.buildUrl(endpoint2, options);
1204
+ async requestFind(endpoint, options) {
1205
+ const url = this.buildUrl(endpoint, options);
1152
1206
  const response = await this.fetchWithTracking(url, {
1153
1207
  ...this.defaultOptions,
1154
1208
  method: "GET"
1155
1209
  });
1156
1210
  return this.parseFindResponse(response);
1157
1211
  }
1158
- async requestFindEndpoint(endpoint2, data) {
1159
- const response = await this.fetchWithTracking(endpoint2, {
1212
+ async requestFindEndpoint(endpoint, data) {
1213
+ const response = await this.fetchWithTracking(endpoint, {
1160
1214
  ...this.defaultOptions,
1161
1215
  method: "POST",
1162
1216
  body: data ? JSON.stringify(data) : void 0
1163
1217
  });
1164
1218
  return this.parseFindResponse(response);
1165
1219
  }
1166
- async requestFindEndpointGet(endpoint2) {
1167
- const response = await this.fetchWithTracking(endpoint2, {
1220
+ async requestFindEndpointGet(endpoint) {
1221
+ const response = await this.fetchWithTracking(endpoint, {
1168
1222
  ...this.defaultOptions,
1169
1223
  method: "GET"
1170
1224
  });
1171
1225
  return this.parseFindResponse(response);
1172
1226
  }
1173
- async requestFindById(endpoint2, options) {
1174
- const url = this.buildUrl(endpoint2, options);
1227
+ async requestFindById(endpoint, options) {
1228
+ const url = this.buildUrl(endpoint, options);
1175
1229
  const response = await this.fetchWithTracking(url, {
1176
1230
  ...this.defaultOptions,
1177
1231
  method: "GET"
1178
1232
  });
1179
1233
  return this.parseDocumentResponse(response);
1180
1234
  }
1181
- async requestCount(endpoint2, options) {
1182
- const url = this.buildUrl(endpoint2, options);
1235
+ async requestCount(endpoint, options) {
1236
+ const url = this.buildUrl(endpoint, options);
1183
1237
  const response = await this.fetchWithTracking(url, {
1184
1238
  ...this.defaultOptions,
1185
1239
  method: "GET"
@@ -1189,7 +1243,7 @@ var ReadOnlyCollectionClient = class extends HttpClient {
1189
1243
  };
1190
1244
 
1191
1245
  // src/core/api/parse-response.ts
1192
- async function parseApiResponse(response, endpoint2, options = {}) {
1246
+ async function parseApiResponse(response, endpoint, options = {}) {
1193
1247
  if (response.status === 204 || response.headers.get("content-length") === "0") {
1194
1248
  return void 0;
1195
1249
  }
@@ -1198,7 +1252,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
1198
1252
  parsed = await response.json();
1199
1253
  } catch {
1200
1254
  throw createApiError(
1201
- `Invalid JSON response from ${endpoint2}`,
1255
+ `Invalid JSON response from ${endpoint}`,
1202
1256
  response.status,
1203
1257
  void 0,
1204
1258
  "Server returned an invalid response.",
@@ -1241,13 +1295,14 @@ async function parseApiResponse(response, endpoint2, options = {}) {
1241
1295
  }
1242
1296
  const withRequestId = attachRequestId(error, requestId);
1243
1297
  if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
1244
- throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
1298
+ throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : enhanceNonCommerceError(withRequestId, reason);
1245
1299
  }
1246
1300
  return data;
1247
1301
  }
1248
1302
 
1249
1303
  // ../../internal/http-contracts/src/index.ts
1250
1304
  var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
1305
+ var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
1251
1306
  var operation = (collection, method, path, errorFamily) => Object.freeze({
1252
1307
  [operationBrand]: true,
1253
1308
  collection,
@@ -1256,6 +1311,10 @@ var operation = (collection, method, path, errorFamily) => Object.freeze({
1256
1311
  ...errorFamily && { errorFamily }
1257
1312
  });
1258
1313
  var strictCommerceOperation = (collection, method, path) => operation(collection, method, path, "commerce");
1314
+ var selectiveCommerceOperation = (collection, method, path, typedCommerceErrorReasons) => Object.freeze({
1315
+ ...operation(collection, method, path),
1316
+ typedCommerceErrorReasons: Object.freeze([...typedCommerceErrorReasons])
1317
+ });
1259
1318
  var COMMERCE_ENDPOINT_OPERATIONS = {
1260
1319
  products: {
1261
1320
  detail: operation("products", "get", "/detail"),
@@ -1287,7 +1346,12 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
1287
1346
  confirmPayment: operation("orders", "post", "/confirm-payment"),
1288
1347
  byPayment: operation("orders", "get", "/by-payment"),
1289
1348
  cancel: operation("orders", "post", "/cancel"),
1290
- resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
1349
+ resolveCancelRefund: selectiveCommerceOperation(
1350
+ "orders",
1351
+ "post",
1352
+ "/resolve-cancel-refund",
1353
+ ["managed_refund_attestation_forbidden"]
1354
+ ),
1291
1355
  checkout: strictCommerceOperation("orders", "post", "/checkout"),
1292
1356
  createFulfillment: operation("orders", "post", "/create-fulfillment"),
1293
1357
  updateFulfillment: operation("orders", "post", "/update-fulfillment")
@@ -1358,6 +1422,16 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
1358
1422
  "payment-sessions",
1359
1423
  "post",
1360
1424
  "/server/confirm"
1425
+ ),
1426
+ findPortOne: strictCommerceOperation(
1427
+ "payment-sessions",
1428
+ "post",
1429
+ "/server/portone/find"
1430
+ ),
1431
+ reconcilePortOne: strictCommerceOperation(
1432
+ "payment-sessions",
1433
+ "post",
1434
+ "/server/portone/reconcile"
1361
1435
  )
1362
1436
  },
1363
1437
  custom: {
@@ -1377,12 +1451,26 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
1377
1451
  validate: operation("discounts", "post", "/validate")
1378
1452
  }
1379
1453
  };
1454
+ var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
1455
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.create,
1456
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.retrieve,
1457
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.create,
1458
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.retrieve
1459
+ ]);
1380
1460
  var MEMBERSHIP_ENDPOINT_OPERATIONS = {
1381
1461
  subscribe: operation(null, "post", "/memberships/subscribe"),
1382
1462
  cancel: operation(null, "post", "/memberships/:id/cancel"),
1383
1463
  me: operation(null, "get", "/memberships/me")
1384
1464
  };
1465
+ var EMBEDDED_ADMIN_ENDPOINT_OPERATIONS = {
1466
+ show: operation("tenants", "get", "/embedded-admin-app"),
1467
+ configure: operation("tenants", "patch", "/embedded-admin-app"),
1468
+ disable: operation("tenants", "delete", "/embedded-admin-app")
1469
+ };
1385
1470
  var EVENTS_ENDPOINT_OPERATIONS = {
1471
+ events: {
1472
+ convertSchedule: operation("events", "post", "/:id/schedule")
1473
+ },
1386
1474
  occurrences: {
1387
1475
  range: operation("event-occurrences", "get", "/range"),
1388
1476
  admissionAvailability: operation(
@@ -1423,46 +1511,51 @@ function resolveOperationMethod(descriptor) {
1423
1511
  }
1424
1512
 
1425
1513
  // src/core/api/endpoints.ts
1426
- var endpoint = (method, path) => ({ method, path });
1427
1514
  var sharedEndpoint = (descriptor) => descriptor;
1428
- function resolveOperationMethod2(descriptor) {
1429
- return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
1430
- }
1431
1515
  function resolveOperationErrorFamily(descriptor) {
1432
- return "collection" in descriptor ? descriptor.errorFamily : void 0;
1433
- }
1434
- function resolveOperationPath2(descriptor, options) {
1435
- if ("collection" in descriptor) {
1436
- return resolveOperationPath(descriptor, options);
1437
- }
1438
- const query = options?.query?.toString().replace(/^\?/, "");
1439
- return query ? `${descriptor.path}?${query}` : descriptor.path;
1516
+ return descriptor.errorFamily;
1440
1517
  }
1441
1518
  var COMMERCE_ENDPOINTS = {
1442
1519
  products: {
1443
- detail: endpoint("GET", "/api/products/detail"),
1444
- detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
1445
- listingGroups: endpoint("GET", "/api/products/listing-groups"),
1446
- listingGroupsCatalog: endpoint(
1447
- "GET",
1448
- "/api/products/listing-groups/catalog"
1520
+ detail: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.detail),
1521
+ detailCatalog: sharedEndpoint(
1522
+ COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog
1523
+ ),
1524
+ listingGroups: sharedEndpoint(
1525
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups
1526
+ ),
1527
+ listingGroupsCatalog: sharedEndpoint(
1528
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog
1529
+ ),
1530
+ // The manifest keeps the GET read and the POST body-query apart; this
1531
+ // semantic name has always resolved to the GET one.
1532
+ listingGroupsQuery: sharedEndpoint(
1533
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet
1534
+ ),
1535
+ listingGroupsQueryCatalog: sharedEndpoint(
1536
+ COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog
1537
+ ),
1538
+ stockCheck: sharedEndpoint(
1539
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck
1449
1540
  ),
1450
- listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
1451
- listingGroupsQueryCatalog: endpoint(
1452
- "GET",
1453
- "/api/products/listing-groups/query/catalog"
1541
+ stockSnapshot: sharedEndpoint(
1542
+ COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot
1454
1543
  ),
1455
- stockCheck: endpoint("POST", "/api/products/stock-check"),
1456
- stockSnapshot: endpoint("GET", "/api/products/stock"),
1457
- upsert: endpoint("POST", "/api/products/upsert")
1544
+ upsert: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.upsert)
1458
1545
  },
1459
1546
  orders: {
1460
- update: endpoint("POST", "/api/orders/update"),
1461
- byPayment: endpoint("GET", "/api/orders/by-payment"),
1462
- cancel: endpoint("POST", "/api/orders/cancel"),
1463
- resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
1464
- createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
1465
- updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
1547
+ update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.update),
1548
+ byPayment: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.byPayment),
1549
+ cancel: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.cancel),
1550
+ resolveCancelRefund: sharedEndpoint(
1551
+ COMMERCE_ENDPOINT_OPERATIONS.orders.resolveCancelRefund
1552
+ ),
1553
+ createFulfillment: sharedEndpoint(
1554
+ COMMERCE_ENDPOINT_OPERATIONS.orders.createFulfillment
1555
+ ),
1556
+ updateFulfillment: sharedEndpoint(
1557
+ COMMERCE_ENDPOINT_OPERATIONS.orders.updateFulfillment
1558
+ )
1466
1559
  },
1467
1560
  checkouts: {
1468
1561
  create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.checkout),
@@ -1474,18 +1567,21 @@ var COMMERCE_ENDPOINTS = {
1474
1567
  }
1475
1568
  },
1476
1569
  returns: {
1477
- create: endpoint("POST", "/api/returns/create"),
1478
- update: endpoint("POST", "/api/returns/update"),
1479
- returnRefund: endpoint("POST", "/api/returns/return-refund")
1570
+ create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.create),
1571
+ update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.update),
1572
+ returnRefund: sharedEndpoint(
1573
+ COMMERCE_ENDPOINT_OPERATIONS.returns.returnRefund
1574
+ )
1480
1575
  },
1481
1576
  fulfillmentOrders: {
1482
- prepare: endpoint(
1483
- "POST",
1484
- "/api/fulfillment-orders/prepare-fulfillment-order"
1577
+ prepare: sharedEndpoint(
1578
+ COMMERCE_ENDPOINT_OPERATIONS.fulfillmentOrders.prepare
1485
1579
  )
1486
1580
  },
1487
1581
  fulfillments: {
1488
- bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
1582
+ bulkImport: sharedEndpoint(
1583
+ COMMERCE_ENDPOINT_OPERATIONS.fulfillments.bulkImport
1584
+ )
1489
1585
  },
1490
1586
  carts: {
1491
1587
  create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
@@ -1550,42 +1646,21 @@ var COMMERCE_ENDPOINTS = {
1550
1646
  ),
1551
1647
  confirm: sharedEndpoint(
1552
1648
  COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.confirm
1649
+ ),
1650
+ findPortOne: sharedEndpoint(
1651
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.findPortOne
1652
+ ),
1653
+ reconcilePortOne: sharedEndpoint(
1654
+ COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.reconcilePortOne
1553
1655
  )
1554
1656
  }
1555
1657
  },
1556
1658
  shippingPolicies: {
1557
- calculate: endpoint("POST", "/api/shipping-policies/calculate")
1659
+ calculate: sharedEndpoint(
1660
+ COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate
1661
+ )
1558
1662
  }
1559
1663
  };
1560
- function isCommerceEndpointDescriptor(value) {
1561
- if (!value || typeof value !== "object") return false;
1562
- const candidate = value;
1563
- return typeof candidate.method === "string" && typeof candidate.path === "string";
1564
- }
1565
- function flattenEndpointPaths(value) {
1566
- if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
1567
- if (!value || typeof value !== "object") return [];
1568
- return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
1569
- }
1570
- function flattenEndpointDescriptors(value) {
1571
- if (isCommerceEndpointDescriptor(value)) return [value];
1572
- if (!value || typeof value !== "object") return [];
1573
- return Object.values(value).flatMap(
1574
- (entry) => flattenEndpointDescriptors(entry)
1575
- );
1576
- }
1577
- var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
1578
- var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
1579
- var MEMBERSHIP_ENDPOINTS = {
1580
- subscribe: "/api/memberships/subscribe",
1581
- cancel: (id) => `/api/memberships/${id}/cancel`,
1582
- me: "/api/memberships/me"
1583
- };
1584
- var MEMBERSHIP_ENDPOINT_PATHS = [
1585
- MEMBERSHIP_ENDPOINTS.subscribe,
1586
- MEMBERSHIP_ENDPOINTS.cancel(":id"),
1587
- MEMBERSHIP_ENDPOINTS.me
1588
- ];
1589
1664
 
1590
1665
  // src/core/api/customer-scoped-api.ts
1591
1666
  var CustomerScopedTransport = class {
@@ -1606,10 +1681,10 @@ var CustomerScopedTransport = class {
1606
1681
  this.onUnauthorized = options.onUnauthorized;
1607
1682
  this.onRequestId = options.onRequestId;
1608
1683
  }
1609
- async request(endpoint2, options) {
1684
+ async request(endpoint, options) {
1610
1685
  const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
1611
1686
  try {
1612
- const response = await httpFetch(endpoint2, {
1687
+ const response = await httpFetch(endpoint, {
1613
1688
  method: options.method,
1614
1689
  apiUrl: this.apiUrl,
1615
1690
  publishableKey: this.publishableKey,
@@ -1623,7 +1698,7 @@ var CustomerScopedTransport = class {
1623
1698
  ...options.errorFamily && { errorFamily: options.errorFamily }
1624
1699
  });
1625
1700
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
1626
- return parseApiResponse(response, endpoint2, {
1701
+ return parseApiResponse(response, endpoint, {
1627
1702
  errorFamily: options.errorFamily
1628
1703
  });
1629
1704
  } catch (err) {
@@ -1637,12 +1712,12 @@ var CustomerScopedApi = class {
1637
1712
  constructor(apiName, options) {
1638
1713
  this.transport = new CustomerScopedTransport(apiName, options);
1639
1714
  }
1640
- requestEndpoint(endpoint2, body, options) {
1641
- return this.transport.request(resolveOperationPath2(endpoint2, options), {
1642
- method: resolveOperationMethod2(endpoint2),
1715
+ requestEndpoint(endpoint, body, options) {
1716
+ return this.transport.request(resolveOperationPath(endpoint, options), {
1717
+ method: resolveOperationMethod(endpoint),
1643
1718
  body,
1644
1719
  headers: options?.headers,
1645
- errorFamily: resolveOperationErrorFamily(endpoint2)
1720
+ errorFamily: resolveOperationErrorFamily(endpoint)
1646
1721
  });
1647
1722
  }
1648
1723
  };
@@ -1650,8 +1725,8 @@ var RawCustomerScopedApi = class {
1650
1725
  constructor(apiName, options) {
1651
1726
  this.transport = new CustomerScopedTransport(apiName, options);
1652
1727
  }
1653
- request(endpoint2, options) {
1654
- return this.transport.request(endpoint2, options);
1728
+ request(endpoint, options) {
1729
+ return this.transport.request(endpoint, options);
1655
1730
  }
1656
1731
  };
1657
1732
 
@@ -1665,13 +1740,7 @@ function unwrapPayloadDoc(value) {
1665
1740
  return value;
1666
1741
  }
1667
1742
  function hasCanonicalNotFoundReason(error) {
1668
- const details = error.details;
1669
- if (typeof details !== "object" || details === null) return false;
1670
- if ("reason" in details && details.reason === "not_found") return true;
1671
- if (!("body" in details) || typeof details.body !== "object" || details.body === null) {
1672
- return false;
1673
- }
1674
- return "reason" in details.body && details.body.reason === "not_found";
1743
+ return getSDKErrorReason(error) === "not_found";
1675
1744
  }
1676
1745
  var CommunityClient = class extends RawCustomerScopedApi {
1677
1746
  constructor(options) {
@@ -1732,11 +1801,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
1732
1801
  if (params.page !== void 0) urlParams.set("page", String(params.page));
1733
1802
  return `/api/comments/public?${urlParams.toString()}`;
1734
1803
  }
1735
- async execute(endpoint2, method, body) {
1736
- return this.request(endpoint2, { method, body });
1804
+ async execute(endpoint, method, body) {
1805
+ return this.request(endpoint, { method, body });
1737
1806
  }
1738
- async executeDoc(endpoint2, method, body) {
1739
- const response = await this.execute(endpoint2, method, body);
1807
+ async executeDoc(endpoint, method, body) {
1808
+ const response = await this.execute(endpoint, method, body);
1740
1809
  return unwrapPayloadDoc(response);
1741
1810
  }
1742
1811
  createPost(params) {
@@ -2002,8 +2071,8 @@ var CommunityClient = class extends RawCustomerScopedApi {
2002
2071
 
2003
2072
  // src/core/content/content-client.ts
2004
2073
  var PublicContentApi = class extends RawCustomerScopedApi {
2005
- get(endpoint2) {
2006
- return this.request(endpoint2, { method: "GET" });
2074
+ get(endpoint) {
2075
+ return this.request(endpoint, { method: "GET" });
2007
2076
  }
2008
2077
  };
2009
2078
  function appendCommonParams(search, options, defaultSort) {
@@ -2184,6 +2253,9 @@ function nullableString(value, resource, path) {
2184
2253
  fail(resource, path, "string or null");
2185
2254
  }
2186
2255
  }
2256
+ function nullableNonEmptyString(value, resource, path) {
2257
+ if (value !== null) string(value, resource, path);
2258
+ }
2187
2259
  function cartLineQuantity(value, resource, path) {
2188
2260
  const quantity = positiveInteger(value, resource, path);
2189
2261
  if (quantity > MAX_CART_LINE_QUANTITY) {
@@ -2693,8 +2765,8 @@ function validatePublicOrderItem(value, resource, path) {
2693
2765
  validateReference(item.variant, resource, `${path}.variant`);
2694
2766
  }
2695
2767
  string(item.productTitle, resource, `${path}.productTitle`);
2696
- nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2697
- nullableString(item.sku, resource, `${path}.sku`);
2768
+ nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
2769
+ nullableNonEmptyString(item.sku, resource, `${path}.sku`);
2698
2770
  validateAdmissions(item.admissions, resource, `${path}.admissions`);
2699
2771
  const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
2700
2772
  const unitPrice = safeMinor(
@@ -2945,8 +3017,8 @@ function validateCheckoutItem(value, resource, path) {
2945
3017
  validateReference(item.product, resource, `${path}.product`);
2946
3018
  validateReference(item.variant, resource, `${path}.variant`);
2947
3019
  string(item.productTitle, resource, `${path}.productTitle`);
2948
- nullableString(item.variantTitle, resource, `${path}.variantTitle`);
2949
- nullableString(item.sku, resource, `${path}.sku`);
3020
+ nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
3021
+ nullableNonEmptyString(item.sku, resource, `${path}.sku`);
2950
3022
  validateAdmissions(item.admissions, resource, `${path}.admissions`);
2951
3023
  cartLineQuantity(item.quantity, resource, `${path}.quantity`);
2952
3024
  const unitPrice = safeMinor(
@@ -3277,9 +3349,96 @@ function validateRequiredReconciliation(value, allowed, resource, path) {
3277
3349
  function validateNextAction(value, provider, resource, path) {
3278
3350
  const action = record(value, resource, path);
3279
3351
  if (provider === "portone") {
3352
+ if (action.type === "portone_sdk") {
3353
+ const hasCancelable = "cancelable" in action;
3354
+ const hasRetryPolicy = "retryPolicy" in action;
3355
+ if (hasCancelable !== hasRetryPolicy) {
3356
+ fail(
3357
+ resource,
3358
+ path,
3359
+ "exact released action or exact negotiated capability action"
3360
+ );
3361
+ }
3362
+ exact(
3363
+ action,
3364
+ [
3365
+ "type",
3366
+ "version",
3367
+ ...hasCancelable ? ["cancelable", "retryPolicy"] : [],
3368
+ "storeId",
3369
+ "channelKey",
3370
+ "paymentId",
3371
+ "orderName",
3372
+ "totalAmount",
3373
+ "currency",
3374
+ "payMethod",
3375
+ "redirectUrl"
3376
+ ],
3377
+ [],
3378
+ resource,
3379
+ path
3380
+ );
3381
+ if (action.version !== "v2") fail(resource, `${path}.version`, "v2");
3382
+ if (hasCancelable && action.cancelable !== false)
3383
+ fail(resource, `${path}.cancelable`, "false");
3384
+ if (hasRetryPolicy && action.retryPolicy !== "same_action_only") {
3385
+ fail(resource, `${path}.retryPolicy`, "same_action_only");
3386
+ }
3387
+ for (const key of ["storeId", "channelKey"]) {
3388
+ boundedString(action[key], 255, resource, `${path}.${key}`);
3389
+ }
3390
+ const paymentId = boundedString(
3391
+ action.paymentId,
3392
+ 40,
3393
+ resource,
3394
+ `${path}.paymentId`
3395
+ );
3396
+ if (!/^[A-Za-z0-9]{6,40}$/.test(paymentId)) {
3397
+ fail(
3398
+ resource,
3399
+ `${path}.paymentId`,
3400
+ "6-40 ASCII alphanumeric characters"
3401
+ );
3402
+ }
3403
+ boundedString(
3404
+ action.orderName,
3405
+ MAX_COMMERCE_SHORT_TEXT_LENGTH,
3406
+ resource,
3407
+ `${path}.orderName`
3408
+ );
3409
+ positiveInteger(action.totalAmount, resource, `${path}.totalAmount`);
3410
+ if (action.currency !== "CURRENCY_KRW") {
3411
+ fail(resource, `${path}.currency`, "CURRENCY_KRW");
3412
+ }
3413
+ if (action.payMethod !== "CARD")
3414
+ fail(resource, `${path}.payMethod`, "CARD");
3415
+ const redirectUrl = boundedString(
3416
+ action.redirectUrl,
3417
+ 2048,
3418
+ resource,
3419
+ `${path}.redirectUrl`
3420
+ );
3421
+ try {
3422
+ const parsed = new URL(redirectUrl);
3423
+ const loopback = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
3424
+ if (!loopback && parsed.protocol !== "https:" || parsed.username || parsed.password)
3425
+ throw new Error("unsafe redirect URL");
3426
+ } catch {
3427
+ fail(
3428
+ resource,
3429
+ `${path}.redirectUrl`,
3430
+ "HTTPS or loopback URL without embedded credentials"
3431
+ );
3432
+ }
3433
+ if (!hasCancelable) {
3434
+ action.cancelable = false;
3435
+ action.retryPolicy = "same_action_only";
3436
+ }
3437
+ return;
3438
+ }
3280
3439
  exact(action, ["type", "checkoutUrl"], [], resource, path);
3281
3440
  if (action.type !== "portone_checkout") {
3282
- fail(resource, `${path}.type`, "portone_checkout");
3441
+ fail(resource, `${path}.type`, "portone_checkout | portone_sdk");
3283
3442
  }
3284
3443
  const checkoutUrl = boundedString(
3285
3444
  action.checkoutUrl,
@@ -4009,8 +4168,8 @@ var CartApi = class extends CustomerScopedApi {
4009
4168
  endpoint(key) {
4010
4169
  return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
4011
4170
  }
4012
- execute(endpoint2, body, idempotencyKey) {
4013
- return this.requestEndpoint(endpoint2, body, {
4171
+ execute(endpoint, body, idempotencyKey) {
4172
+ return this.requestEndpoint(endpoint, body, {
4014
4173
  ...idempotencyKey && {
4015
4174
  headers: { "X-Idempotency-Key": idempotencyKey }
4016
4175
  }
@@ -4027,26 +4186,26 @@ var CartApi = class extends CustomerScopedApi {
4027
4186
  );
4028
4187
  }
4029
4188
  mine(params = {}) {
4030
- const endpoint2 = this.endpoint("mine");
4031
- return this.execute(endpoint2, params).then(
4189
+ const endpoint = this.endpoint("mine");
4190
+ return this.execute(endpoint, params).then(
4032
4191
  (value) => validateCartMineResult(value)
4033
4192
  );
4034
4193
  }
4035
4194
  merge(params) {
4036
4195
  const { idempotencyKey, ...body } = params;
4037
4196
  assertCommerceIdempotencyKey(idempotencyKey);
4038
- const endpoint2 = this.endpoint("merge");
4039
- return this.execute(endpoint2, body, idempotencyKey).then(
4197
+ const endpoint = this.endpoint("merge");
4198
+ return this.execute(endpoint, body, idempotencyKey).then(
4040
4199
  (value) => validateCartMergeResult(value)
4041
4200
  );
4042
4201
  }
4043
4202
  addItem(params) {
4044
4203
  return this.mutate(this.endpoint("addItem"), params);
4045
4204
  }
4046
- mutate(endpoint2, params) {
4205
+ mutate(endpoint, params) {
4047
4206
  const { idempotencyKey, ...body } = params;
4048
4207
  assertCommerceIdempotencyKey(idempotencyKey);
4049
- return this.execute(endpoint2, body, idempotencyKey).then(
4208
+ return this.execute(endpoint, body, idempotencyKey).then(
4050
4209
  (value) => validateCartMutationResult(value)
4051
4210
  );
4052
4211
  }
@@ -4072,8 +4231,8 @@ var CheckoutApi = class extends CustomerScopedApi {
4072
4231
  constructor(options) {
4073
4232
  super("CheckoutApi", { ...options, requiresCredential: false });
4074
4233
  }
4075
- post(endpoint2, body, idempotencyKey) {
4076
- return this.requestEndpoint(endpoint2, body, {
4234
+ post(endpoint, body, idempotencyKey) {
4235
+ return this.requestEndpoint(endpoint, body, {
4077
4236
  ...idempotencyKey && {
4078
4237
  headers: { "X-Idempotency-Key": idempotencyKey }
4079
4238
  }
@@ -4140,11 +4299,15 @@ var PaymentSessionApi = class extends CustomerScopedApi {
4140
4299
  super("PaymentSessionApi", { ...options, requiresCredential: false });
4141
4300
  this.serverTransport = Boolean(options.secretKey);
4142
4301
  }
4143
- post(endpoint2, body, idempotencyKey) {
4144
- return this.requestEndpoint(endpoint2, body, {
4145
- ...idempotencyKey && {
4146
- headers: { "X-Idempotency-Key": idempotencyKey }
4302
+ post(endpoint, body, idempotencyKey, negotiateStandardActionCapabilities = false) {
4303
+ const headers = {
4304
+ ...idempotencyKey && { "X-Idempotency-Key": idempotencyKey },
4305
+ ...negotiateStandardActionCapabilities && {
4306
+ Accept: PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE
4147
4307
  }
4308
+ };
4309
+ return this.requestEndpoint(endpoint, body, {
4310
+ ...Object.keys(headers).length > 0 && { headers }
4148
4311
  });
4149
4312
  }
4150
4313
  async paymentSession(result, expectedProvider) {
@@ -4169,40 +4332,41 @@ var PaymentSessionApi = class extends CustomerScopedApi {
4169
4332
  this.post(
4170
4333
  this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
4171
4334
  body,
4172
- idempotencyKey
4335
+ idempotencyKey,
4336
+ body.providerOptions.profile === "standard_v2"
4173
4337
  ),
4174
4338
  "portone"
4175
4339
  );
4176
4340
  }
4177
4341
  retrieve(params) {
4178
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4342
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4179
4343
  return this.paymentSession(
4180
- this.post(endpoint2, params),
4344
+ this.post(endpoint, params),
4181
4345
  "toss"
4182
4346
  );
4183
4347
  }
4184
4348
  retrievePortOne(params) {
4185
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4349
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
4186
4350
  return this.paymentSession(
4187
- this.post(endpoint2, params),
4351
+ this.post(endpoint, params, void 0, true),
4188
4352
  "portone"
4189
4353
  );
4190
4354
  }
4191
4355
  cancel(params) {
4192
4356
  const { idempotencyKey, ...body } = params;
4193
4357
  assertCommerceIdempotencyKey(idempotencyKey);
4194
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4358
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4195
4359
  return this.paymentSession(
4196
- this.post(endpoint2, body, idempotencyKey),
4360
+ this.post(endpoint, body, idempotencyKey),
4197
4361
  "toss"
4198
4362
  );
4199
4363
  }
4200
4364
  cancelPortOne(params) {
4201
4365
  const { idempotencyKey, ...body } = params;
4202
4366
  assertCommerceIdempotencyKey(idempotencyKey);
4203
- const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4367
+ const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
4204
4368
  return this.paymentSession(
4205
- this.post(endpoint2, body, idempotencyKey),
4369
+ this.post(endpoint, body, idempotencyKey),
4206
4370
  "portone"
4207
4371
  );
4208
4372
  }
@@ -4281,9 +4445,9 @@ function resolveVariantImageItems(variant, poolById) {
4281
4445
  if (pooled) resolved.push(pooled);
4282
4446
  continue;
4283
4447
  }
4284
- const mediaId2 = getMediaId(entry);
4285
- if (mediaId2) {
4286
- const pooled = poolById.get(mediaId2);
4448
+ const mediaId = getMediaId(entry);
4449
+ if (mediaId) {
4450
+ const pooled = poolById.get(mediaId);
4287
4451
  if (pooled) {
4288
4452
  resolved.push(pooled);
4289
4453
  }
@@ -4474,11 +4638,11 @@ function getFirstMediaId(values) {
4474
4638
  }
4475
4639
  return null;
4476
4640
  }
4477
- function inProductMediaPool(product, mediaId2) {
4478
- if (mediaId2 == null) return null;
4641
+ function inProductMediaPool(product, mediaId) {
4642
+ if (mediaId == null) return null;
4479
4643
  const images = Array.isArray(product?.images) ? product.images : [];
4480
4644
  for (const image of images) {
4481
- if (extractEntityId(image) === mediaId2) return mediaId2;
4645
+ if (extractEntityId(image) === mediaId) return mediaId;
4482
4646
  }
4483
4647
  return null;
4484
4648
  }
@@ -5954,21 +6118,11 @@ var PRODUCT_DETAIL_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
5954
6118
  "not_published",
5955
6119
  "feature_disabled"
5956
6120
  ]);
5957
- function isRecord(value) {
5958
- return typeof value === "object" && value !== null;
5959
- }
5960
- function readProductDetailUnavailableReason(value) {
5961
- if (!isRecord(value)) return void 0;
5962
- const directReason = value.reason ?? value.code;
5963
- if (typeof directReason === "string" && PRODUCT_DETAIL_UNAVAILABLE_REASONS.has(directReason)) {
5964
- return directReason;
5965
- }
5966
- return readProductDetailUnavailableReason(value.body);
5967
- }
5968
6121
  function productDetailResultFromError(error) {
5969
6122
  if (!(error instanceof SDKError) || error.status !== 404) return void 0;
5970
- const reason = readProductDetailUnavailableReason(error.details);
5971
- if (!reason) return void 0;
6123
+ const reason = getSDKErrorReason(error);
6124
+ if (!reason || !PRODUCT_DETAIL_UNAVAILABLE_REASONS.has(reason))
6125
+ return void 0;
5972
6126
  return { found: false, reason };
5973
6127
  }
5974
6128
  var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
@@ -6069,8 +6223,8 @@ function isProductUpsertFieldValidationErrorBody(value) {
6069
6223
 
6070
6224
  // src/core/commerce/commerce-client.ts
6071
6225
  var BrowserCommerceApi = class extends CustomerScopedApi {
6072
- requestEndpoint(endpoint2, body, options) {
6073
- return super.requestEndpoint(endpoint2, body, options);
6226
+ requestEndpoint(endpoint, body, options) {
6227
+ return super.requestEndpoint(endpoint, body, options);
6074
6228
  }
6075
6229
  };
6076
6230
  var CommerceClient = class {
@@ -6270,11 +6424,11 @@ var EventsClient = class {
6270
6424
  { useCustomerAuth: false }
6271
6425
  );
6272
6426
  }
6273
- async execute(endpoint2, method, body, options = {}) {
6427
+ async execute(endpoint, method, body, options = {}) {
6274
6428
  const useCustomerAuth = options.useCustomerAuth === true;
6275
6429
  const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
6276
6430
  try {
6277
- const response = await httpFetch(endpoint2, {
6431
+ const response = await httpFetch(endpoint, {
6278
6432
  method,
6279
6433
  apiUrl: this.apiUrl,
6280
6434
  publishableKey: this.publishableKey,
@@ -6283,7 +6437,7 @@ var EventsClient = class {
6283
6437
  ...body !== void 0 && { body: JSON.stringify(body) }
6284
6438
  });
6285
6439
  this.onRequestId?.(response.headers.get("x-request-id") ?? null);
6286
- return parseApiResponse(response, endpoint2);
6440
+ return parseApiResponse(response, endpoint);
6287
6441
  } catch (err) {
6288
6442
  const id = err instanceof SDKError ? err.requestId ?? null : null;
6289
6443
  this.onRequestId?.(id);
@@ -6541,13 +6695,106 @@ function mergeProductDetailWithStock(catalog, snapshot) {
6541
6695
  };
6542
6696
  }
6543
6697
 
6698
+ // src/core/webhook/validation.ts
6699
+ function isValidWebhookEventData(data) {
6700
+ if (typeof data !== "object" || data === null) return false;
6701
+ const event = data;
6702
+ return typeof event.collection === "string" && typeof event.operation === "string" && event.operation.length > 0 && typeof event.data === "object" && event.data !== null;
6703
+ }
6704
+
6705
+ // src/core/webhook/receiver.ts
6706
+ async function verifySignature(rawBody, secret, signature, timestamp2, deliveryId) {
6707
+ const encoder = new TextEncoder();
6708
+ const signedPrefix = encoder.encode(`${timestamp2}.${deliveryId}.`);
6709
+ const signedPayload = new Uint8Array(signedPrefix.length + rawBody.length);
6710
+ signedPayload.set(signedPrefix);
6711
+ signedPayload.set(rawBody, signedPrefix.length);
6712
+ const key = await crypto.subtle.importKey(
6713
+ "raw",
6714
+ encoder.encode(secret),
6715
+ { name: "HMAC", hash: "SHA-256" },
6716
+ false,
6717
+ ["verify"]
6718
+ );
6719
+ if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
6720
+ return false;
6721
+ }
6722
+ const sigBytes = new Uint8Array(
6723
+ (signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
6724
+ );
6725
+ return crypto.subtle.verify("HMAC", key, sigBytes, signedPayload);
6726
+ }
6727
+ function timestampIsFresh(timestamp2, toleranceSeconds) {
6728
+ if (!/^\d+$/.test(timestamp2)) return false;
6729
+ const timestampMs = Number(timestamp2);
6730
+ if (!Number.isFinite(timestampMs)) return false;
6731
+ const skewMs = Math.abs(Date.now() - timestampMs);
6732
+ return skewMs <= toleranceSeconds * 1e3;
6733
+ }
6734
+ var MAX_TOLERANCE_SECONDS = 86400;
6735
+ function toleranceIsValid(toleranceSeconds) {
6736
+ return typeof toleranceSeconds === "number" && Number.isFinite(toleranceSeconds) && toleranceSeconds >= 0 && toleranceSeconds <= MAX_TOLERANCE_SECONDS;
6737
+ }
6738
+ async function processWebhookRequest(request, handler, verify) {
6739
+ try {
6740
+ const rawBody = new Uint8Array(await request.arrayBuffer());
6741
+ const verificationFailure = await verify?.(rawBody);
6742
+ if (verificationFailure) return verificationFailure;
6743
+ const body = JSON.parse(new TextDecoder().decode(rawBody));
6744
+ if (!isValidWebhookEventData(body)) {
6745
+ return new Response(
6746
+ JSON.stringify({ error: "Invalid webhook event format" }),
6747
+ { status: 400, headers: { "Content-Type": "application/json" } }
6748
+ );
6749
+ }
6750
+ await handler(body);
6751
+ return new Response(
6752
+ JSON.stringify({ success: true, message: "Webhook processed" }),
6753
+ { status: 200, headers: { "Content-Type": "application/json" } }
6754
+ );
6755
+ } catch (error) {
6756
+ console.error("Webhook processing error:", error);
6757
+ return new Response(JSON.stringify({ error: "Internal server error" }), {
6758
+ status: 500,
6759
+ headers: { "Content-Type": "application/json" }
6760
+ });
6761
+ }
6762
+ }
6763
+ async function handleSignedWebhook(request, handler, options) {
6764
+ const secret = options?.secret;
6765
+ const configuredTolerance = options?.toleranceSeconds;
6766
+ const toleranceSeconds = configuredTolerance ?? 300;
6767
+ if (typeof secret !== "string" || secret.trim().length === 0) {
6768
+ return new Response(
6769
+ JSON.stringify({ error: "Webhook signing secret is not configured" }),
6770
+ { status: 500, headers: { "Content-Type": "application/json" } }
6771
+ );
6772
+ }
6773
+ if (!toleranceIsValid(toleranceSeconds)) {
6774
+ return new Response(
6775
+ JSON.stringify({ error: "Webhook signature tolerance is not valid" }),
6776
+ { status: 500, headers: { "Content-Type": "application/json" } }
6777
+ );
6778
+ }
6779
+ return processWebhookRequest(request, handler, async (rawBody) => {
6780
+ const signature = request.headers.get("x-webhook-signature") || "";
6781
+ const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
6782
+ const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
6783
+ const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(rawBody, secret, signature, timestamp2, deliveryId);
6784
+ if (!valid) {
6785
+ return new Response(
6786
+ JSON.stringify({ error: "Invalid webhook signature" }),
6787
+ { status: 401, headers: { "Content-Type": "application/json" } }
6788
+ );
6789
+ }
6790
+ });
6791
+ }
6792
+
6544
6793
  // src/core/webhook/index.ts
6545
6794
  var ORDER_CHANGED_EVENT_TYPE = "collection.orderChanged";
6546
6795
  var COMMERCE_NOTIFICATION_EVENT_TYPE = "commerce.notification";
6547
6796
  function isValidWebhookEvent(data) {
6548
- if (typeof data !== "object" || data === null) return false;
6549
- const obj = data;
6550
- return typeof obj.collection === "string" && typeof obj.operation === "string" && obj.operation.length > 0 && typeof obj.data === "object" && obj.data !== null;
6797
+ return isValidWebhookEventData(data);
6551
6798
  }
6552
6799
  var COMMERCE_NOTIFICATION_OPERATION = "notification";
6553
6800
  var COMMERCE_NOTIFICATION_EVENTS = [
@@ -6559,13 +6806,15 @@ var COMMERCE_NOTIFICATION_EVENTS = [
6559
6806
  "returnApproved",
6560
6807
  "returnRejected",
6561
6808
  "returnCanceled",
6562
- "returnCompleted"
6809
+ "returnCompleted",
6810
+ "paymentReconciliationRequired",
6811
+ "paymentRefundRequiresAttention"
6563
6812
  ];
6564
6813
  function isStringOrNumber(value) {
6565
6814
  return typeof value === "string" || typeof value === "number";
6566
6815
  }
6567
6816
  function isWebhookOrderScope(value) {
6568
- if (!isRecord2(value)) return false;
6817
+ if (!isRecord(value)) return false;
6569
6818
  if (value.kind === "collection") {
6570
6819
  return typeof value.collection === "string";
6571
6820
  }
@@ -6575,35 +6824,42 @@ function isWebhookOrderScope(value) {
6575
6824
  return false;
6576
6825
  }
6577
6826
  function isWebhookOrderMoved(value) {
6578
- if (!isRecord2(value)) return false;
6827
+ if (!isRecord(value)) return false;
6579
6828
  return typeof value.collection === "string" && isStringOrNumber(value.id) && (value.relatedCollection === void 0 || typeof value.relatedCollection === "string") && (value.relatedId === void 0 || isStringOrNumber(value.relatedId));
6580
6829
  }
6581
6830
  function hasOptionalOrderValue(value, key) {
6582
6831
  return value[key] === void 0 || value[key] === null || typeof value[key] === "string";
6583
6832
  }
6584
6833
  function isWebhookOrderChange(value) {
6585
- if (!isRecord2(value)) return false;
6834
+ if (!isRecord(value)) return false;
6586
6835
  return value.type === "order" && value.source === "payload-orderable" && (value.orderableFieldName === void 0 || typeof value.orderableFieldName === "string") && hasOptionalOrderValue(value, "previousOrder") && hasOptionalOrderValue(value, "nextOrder") && isWebhookOrderScope(value.scope) && isWebhookOrderMoved(value.moved);
6587
6836
  }
6588
6837
  function isCommerceNotificationEventName(value) {
6589
6838
  return typeof value === "string" && COMMERCE_NOTIFICATION_EVENTS.includes(value);
6590
6839
  }
6591
6840
  function isCommerceNotificationSourceCollection(value) {
6592
- return value === "orders" || value === "fulfillments" || value === "returns";
6841
+ return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts";
6593
6842
  }
6594
6843
  function isCommerceNotificationData(value) {
6595
- if (!isRecord2(value)) return false;
6596
- if (value.source !== void 0 && (!isRecord2(value.source) || !isCommerceNotificationSourceCollection(value.source.collection) || !isStringOrNumber(value.source.id))) {
6844
+ if (!isRecord(value)) return false;
6845
+ if (value.source !== void 0 && (!isRecord(value.source) || !isCommerceNotificationSourceCollection(value.source.collection) || !isStringOrNumber(value.source.id))) {
6597
6846
  return false;
6598
6847
  }
6599
- return (value.orderId === void 0 || isStringOrNumber(value.orderId)) && (value.orderNumber === void 0 || typeof value.orderNumber === "string") && (value.status === void 0 || typeof value.status === "string") && (value.totalAmount === void 0 || typeof value.totalAmount === "number") && (value.currency === void 0 || typeof value.currency === "string") && (value.fulfillmentId === void 0 || isStringOrNumber(value.fulfillmentId)) && (value.fulfillmentStatus === void 0 || typeof value.fulfillmentStatus === "string") && (value.shippedAt === void 0 || typeof value.shippedAt === "string") && (value.returnId === void 0 || isStringOrNumber(value.returnId)) && (value.returnStatus === void 0 || typeof value.returnStatus === "string") && (value.refundAmount === void 0 || typeof value.refundAmount === "number") && (value.completedAt === void 0 || typeof value.completedAt === "string");
6848
+ return (value.orderId === void 0 || isStringOrNumber(value.orderId)) && (value.orderNumber === void 0 || typeof value.orderNumber === "string") && (value.status === void 0 || typeof value.status === "string") && (value.totalAmount === void 0 || typeof value.totalAmount === "number") && (value.currency === void 0 || typeof value.currency === "string") && (value.fulfillmentId === void 0 || isStringOrNumber(value.fulfillmentId)) && (value.fulfillmentStatus === void 0 || typeof value.fulfillmentStatus === "string") && (value.shippedAt === void 0 || typeof value.shippedAt === "string") && (value.returnId === void 0 || isStringOrNumber(value.returnId)) && (value.returnStatus === void 0 || typeof value.returnStatus === "string") && (value.refundAmount === void 0 || typeof value.refundAmount === "number") && (value.completedAt === void 0 || typeof value.completedAt === "string") && (value.paymentSessionId === void 0 || typeof value.paymentSessionId === "string") && (value.checkoutId === void 0 || typeof value.checkoutId === "string") && (value.refundAttemptId === void 0 || typeof value.refundAttemptId === "string") && (value.reason === void 0 || typeof value.reason === "string") && (value.observedAt === void 0 || typeof value.observedAt === "string") && (value.providerObject === void 0 || isRecord(value.providerObject) && typeof value.providerObject.provider === "string" && (value.providerObject.kind === "payment" || value.providerObject.kind === "refund") && typeof value.providerObject.id === "string") && (value.money === void 0 || isRecord(value.money) && Number.isSafeInteger(value.money.amountMinor) && Number(value.money.amountMinor) > 0 && typeof value.money.currency === "string");
6600
6849
  }
6601
6850
  function isCommerceNotification(value) {
6602
- if (!isRecord2(value)) return false;
6603
- return isCommerceNotificationEventName(value.event) && typeof value.intentId === "string" && value.intentId.length > 0 && typeof value.dedupeKey === "string" && value.dedupeKey.length > 0 && (value.orderId === void 0 || typeof value.orderId === "string") && (value.fulfillmentId === void 0 || typeof value.fulfillmentId === "string") && (value.returnId === void 0 || typeof value.returnId === "string");
6851
+ if (!isRecord(value)) return false;
6852
+ return isCommerceNotificationEventName(value.event) && typeof value.intentId === "string" && value.intentId.length > 0 && typeof value.dedupeKey === "string" && value.dedupeKey.length > 0 && (value.orderId === void 0 || typeof value.orderId === "string") && (value.fulfillmentId === void 0 || typeof value.fulfillmentId === "string") && (value.returnId === void 0 || typeof value.returnId === "string") && (value.paymentSessionId === void 0 || typeof value.paymentSessionId === "string") && (value.refundAttemptId === void 0 || typeof value.refundAttemptId === "string");
6853
+ }
6854
+ function isPaymentIncidentNotificationData(value, event) {
6855
+ const reconciliation = event === "paymentReconciliationRequired";
6856
+ const expectedCollection = reconciliation ? "payment-sessions" : "payment-refund-attempts";
6857
+ const expectedStatus = reconciliation ? "reconciliation_required" : "requires_attention";
6858
+ const expectedReason = reconciliation ? "orderless_capture" : "local_commit_ambiguous";
6859
+ return value.source?.collection === expectedCollection && typeof value.source.id === "string" && value.source.id.length > 0 && typeof value.paymentSessionId === "string" && value.paymentSessionId.length > 0 && isRecord(value.providerObject) && typeof value.providerObject.provider === "string" && value.providerObject.provider.length > 0 && (value.providerObject.kind === "payment" || value.providerObject.kind === "refund") && typeof value.providerObject.id === "string" && value.providerObject.id.length > 0 && isRecord(value.money) && Number.isSafeInteger(value.money.amountMinor) && Number(value.money.amountMinor) > 0 && typeof value.money.currency === "string" && value.money.currency.length > 0 && value.status === expectedStatus && value.reason === expectedReason && typeof value.observedAt === "string" && value.observedAt.length > 0 && !Number.isNaN(Date.parse(value.observedAt)) && (value.checkoutId === void 0 || typeof value.checkoutId === "string" && value.checkoutId.length > 0) && (value.orderId === void 0 || typeof value.orderId === "string" && value.orderId.length > 0) && (reconciliation ? value.source.id === value.paymentSessionId && value.providerObject.kind === "payment" && value.refundAttemptId === void 0 : typeof value.refundAttemptId === "string" && value.refundAttemptId.length > 0 && value.source.id === value.refundAttemptId);
6604
6860
  }
6605
6861
  function isWebhookCommerceNotificationChange(value) {
6606
- if (!isRecord2(value)) return false;
6862
+ if (!isRecord(value)) return false;
6607
6863
  return value.type === "notification" && value.source === "commerce-notifications" && isCommerceNotificationEventName(value.event) && isCommerceNotificationSourceCollection(value.sourceCollection) && isStringOrNumber(value.sourceId);
6608
6864
  }
6609
6865
  function matchesOptionalId(actual, expected) {
@@ -6641,6 +6897,15 @@ function isCommerceNotificationWebhookEvent(event) {
6641
6897
  if (!matchesOptionalId(change.sourceId, sourceId)) return false;
6642
6898
  }
6643
6899
  const changeSourceId = isWebhookCommerceNotificationChange(change) ? change.sourceId : void 0;
6900
+ if (notification.event === "paymentReconciliationRequired" || notification.event === "paymentRefundRequiresAttention") {
6901
+ if (!isPaymentIncidentNotificationData(data, notification.event)) {
6902
+ return false;
6903
+ }
6904
+ const incidentData = data;
6905
+ const expectedCollection = notification.event === "paymentReconciliationRequired" ? "payment-sessions" : "payment-refund-attempts";
6906
+ const notificationSourceId = notification.event === "paymentReconciliationRequired" ? notification.paymentSessionId : notification.refundAttemptId;
6907
+ return sourceCollection === expectedCollection && typeof notification.paymentSessionId === "string" && notification.paymentSessionId === incidentData.paymentSessionId && typeof notificationSourceId === "string" && notificationSourceId === incidentData.source.id && matchesOptionalId(changeSourceId, incidentData.source.id);
6908
+ }
6644
6909
  if (notification.event === "orderPaid" || notification.event === "orderCanceled" || notification.event === "orderDelivered") {
6645
6910
  return sourceCollection === "orders" && typeof notification.orderId === "string" && notification.orderId.length > 0 && matchesOptionalId(data.orderId, sourceId) && matchesOptionalId(notification.orderId, sourceId) && matchesOptionalId(data.orderId, notification.orderId) && matchesOptionalId(changeSourceId, data.orderId ?? notification.orderId);
6646
6911
  }
@@ -6685,7 +6950,7 @@ function isWebhookOperation(event, operation2) {
6685
6950
  return isValidWebhookEvent(event) && event.operation === operation2;
6686
6951
  }
6687
6952
  var CUSTOMER_PASSWORD_RESET_OPERATION = "password-reset";
6688
- function isRecord2(value) {
6953
+ function isRecord(value) {
6689
6954
  return typeof value === "object" && value !== null;
6690
6955
  }
6691
6956
  function hasString(value, key) {
@@ -6695,7 +6960,7 @@ function hasStringOrNumber(value, key) {
6695
6960
  return typeof value[key] === "string" || typeof value[key] === "number";
6696
6961
  }
6697
6962
  function isCustomerPasswordResetWebhookEvent(event) {
6698
- if (event.collection !== "customers" || event.operation !== CUSTOMER_PASSWORD_RESET_OPERATION || !isRecord2(event.data)) {
6963
+ if (event.collection !== "customers" || event.operation !== CUSTOMER_PASSWORD_RESET_OPERATION || !isRecord(event.data)) {
6699
6964
  return false;
6700
6965
  }
6701
6966
  return hasStringOrNumber(event.data, "customerId") && hasString(event.data, "email") && hasString(event.data, "name") && hasString(event.data, "resetPasswordToken") && hasString(event.data, "resetPasswordExpiresAt");
@@ -6709,80 +6974,8 @@ function createCustomerAuthWebhookHandler(handlers) {
6709
6974
  await handlers.unhandled?.(event);
6710
6975
  };
6711
6976
  }
6712
- async function verifySignature(payload, secret, signature, timestamp2, deliveryId) {
6713
- const encoder = new TextEncoder();
6714
- const key = await crypto.subtle.importKey(
6715
- "raw",
6716
- encoder.encode(secret),
6717
- { name: "HMAC", hash: "SHA-256" },
6718
- false,
6719
- ["verify"]
6720
- );
6721
- if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
6722
- return false;
6723
- }
6724
- const sigBytes = new Uint8Array(
6725
- (signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
6726
- );
6727
- return crypto.subtle.verify(
6728
- "HMAC",
6729
- key,
6730
- sigBytes,
6731
- encoder.encode(`${timestamp2}.${deliveryId}.${payload}`)
6732
- );
6733
- }
6734
- function timestampIsFresh(timestamp2, toleranceSeconds) {
6735
- if (!/^\d+$/.test(timestamp2)) return false;
6736
- const timestampMs = Number(timestamp2);
6737
- if (!Number.isFinite(timestampMs)) return false;
6738
- const skewMs = Math.abs(Date.now() - timestampMs);
6739
- return skewMs <= toleranceSeconds * 1e3;
6740
- }
6741
6977
  async function handleWebhook(request, handler, options) {
6742
- try {
6743
- const rawBody = await request.text();
6744
- if (options?.secret) {
6745
- const signature = request.headers.get("x-webhook-signature") || "";
6746
- const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
6747
- const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
6748
- const toleranceSeconds = options.toleranceSeconds ?? 300;
6749
- const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(
6750
- rawBody,
6751
- options.secret,
6752
- signature,
6753
- timestamp2,
6754
- deliveryId
6755
- );
6756
- if (!valid) {
6757
- return new Response(
6758
- JSON.stringify({ error: "Invalid webhook signature" }),
6759
- { status: 401, headers: { "Content-Type": "application/json" } }
6760
- );
6761
- }
6762
- } else {
6763
- console.warn(
6764
- "[@01.software/sdk] Webhook signature verification is disabled. Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification."
6765
- );
6766
- }
6767
- const body = JSON.parse(rawBody);
6768
- if (!isValidWebhookEvent(body)) {
6769
- return new Response(
6770
- JSON.stringify({ error: "Invalid webhook event format" }),
6771
- { status: 400, headers: { "Content-Type": "application/json" } }
6772
- );
6773
- }
6774
- await handler(body);
6775
- return new Response(
6776
- JSON.stringify({ success: true, message: "Webhook processed" }),
6777
- { status: 200, headers: { "Content-Type": "application/json" } }
6778
- );
6779
- } catch (error) {
6780
- console.error("Webhook processing error:", error);
6781
- return new Response(JSON.stringify({ error: "Internal server error" }), {
6782
- status: 500,
6783
- headers: { "Content-Type": "application/json" }
6784
- });
6785
- }
6978
+ return handleSignedWebhook(request, handler, options);
6786
6979
  }
6787
6980
  function createTypedWebhookHandler(collection, handler) {
6788
6981
  return async (event) => {
@@ -6822,6 +7015,7 @@ var INTERNAL_COLLECTIONS = [
6822
7015
  "payment-event-inbox",
6823
7016
  "payment-refund-attempts",
6824
7017
  "portone-payment-interactions",
7018
+ "commerce-payment-webhook-routes",
6825
7019
  "commerce-notification-intents",
6826
7020
  "commerce-idempotency-records",
6827
7021
  "product-collection-items",
@@ -6862,7 +7056,6 @@ var COLLECTIONS = [
6862
7056
  "brands",
6863
7057
  "customer-profiles",
6864
7058
  "customer-profile-stats",
6865
- "discounts",
6866
7059
  "shipping-policies",
6867
7060
  "shipping-zones",
6868
7061
  "documents",
@@ -6938,6 +7131,9 @@ var SERVER_ONLY_COLLECTIONS = [
6938
7131
  "cart-items",
6939
7132
  "checkouts",
6940
7133
  "checkout-items",
7134
+ // Raw discount definitions require a server credential. Browser discount
7135
+ // validation is exposed through the shaped POST /api/discounts/validate path.
7136
+ "discounts",
6941
7137
  "draft-orders",
6942
7138
  "draft-order-items",
6943
7139
  "posts",
@@ -7103,160 +7299,6 @@ var RealtimeConnection = class {
7103
7299
  }
7104
7300
  };
7105
7301
 
7106
- // src/utils/product-media.ts
7107
- function mediaPointerOptionValues(values) {
7108
- return (values ?? []).filter((value) => value != null && value !== "").map((value) => ({
7109
- swatch: {
7110
- type: "media",
7111
- mediaItemId: value
7112
- }
7113
- }));
7114
- }
7115
- function resolveProductMedia(input) {
7116
- const resolved = resolveProductSelectionMedia({
7117
- ...input,
7118
- selectedVariant: input.selectedVariant ?? (input.variantFeaturedMediaItemId ? { images: [input.variantFeaturedMediaItemId] } : null),
7119
- selectedOptionValues: input.selectedOptionValues ?? mediaPointerOptionValues(input.selectedOptionValueMediaItemIds)
7120
- });
7121
- if (resolved.source !== "none") {
7122
- return {
7123
- ...resolved,
7124
- source: resolved.source === "variant_media_selected" ? "variant_featured" : resolved.source
7125
- };
7126
- }
7127
- const display = resolveProductDisplayMedia({
7128
- productMediaPool: input.productMediaPool
7129
- });
7130
- return {
7131
- primaryImage: display.primaryImage,
7132
- images: display.images,
7133
- source: display.source
7134
- };
7135
- }
7136
-
7137
- // src/utils/product-gallery.ts
7138
- function mediaId(value) {
7139
- if (typeof value === "string" || typeof value === "number") {
7140
- return String(value);
7141
- }
7142
- if (typeof value === "object" && value !== null && "id" in value) {
7143
- const id = value.id;
7144
- if (typeof id === "string" || typeof id === "number") return String(id);
7145
- }
7146
- return null;
7147
- }
7148
- function relationshipIds(values) {
7149
- if (!Array.isArray(values)) return [];
7150
- return values.map((value) => mediaId(value)).filter((value) => Boolean(value));
7151
- }
7152
- function buildPoolById2(pool) {
7153
- const poolById = /* @__PURE__ */ new Map();
7154
- for (const item of pool) {
7155
- const id = mediaId(item);
7156
- if (id) poolById.set(id, item);
7157
- }
7158
- return poolById;
7159
- }
7160
- function mediaSetItemsInPool(mediaSet, poolById) {
7161
- const seen = /* @__PURE__ */ new Set();
7162
- const items = [];
7163
- const primaryId = mediaId(mediaSet.primaryMediaItemId);
7164
- if (primaryId) {
7165
- const primary = poolById.get(primaryId);
7166
- if (primary) {
7167
- seen.add(primaryId);
7168
- items.push(primary);
7169
- }
7170
- }
7171
- for (const itemId of relationshipIds(mediaSet.items)) {
7172
- if (seen.has(itemId)) continue;
7173
- const item = poolById.get(itemId);
7174
- if (!item) continue;
7175
- seen.add(itemId);
7176
- items.push(item);
7177
- }
7178
- return items;
7179
- }
7180
- function resolveLegacyMediaSet(input) {
7181
- if (!Array.isArray(input.mediaSets)) return null;
7182
- const pool = input.productMediaPool ?? input.pool ?? [];
7183
- const poolById = buildPoolById2(pool);
7184
- const selectedVariantId = mediaId(input.selectedVariantId);
7185
- if (selectedVariantId) {
7186
- const exactSet = input.mediaSets.find(
7187
- (set) => set.matchType === "exact-variant" && relationshipIds(set.variantIds).includes(selectedVariantId)
7188
- );
7189
- if (exactSet) {
7190
- const images = mediaSetItemsInPool(exactSet, poolById);
7191
- if (images.length > 0) {
7192
- return {
7193
- primaryImage: images[0] ?? null,
7194
- images,
7195
- source: "exact_variant_set"
7196
- };
7197
- }
7198
- }
7199
- }
7200
- const selectedOptionValueIds = new Set(
7201
- relationshipIds(input.selectedOptionValueIds)
7202
- );
7203
- const optionSetMatches = input.mediaSets.filter((set) => set.matchType === "option-values").map((set) => {
7204
- const optionValueIds = relationshipIds(set.optionValueIds);
7205
- if (optionValueIds.length === 0) return null;
7206
- if (!optionValueIds.every((id) => selectedOptionValueIds.has(id))) {
7207
- return null;
7208
- }
7209
- const images = mediaSetItemsInPool(set, poolById);
7210
- if (images.length === 0) return null;
7211
- return { optionValueCount: optionValueIds.length, images };
7212
- }).filter(
7213
- (match) => Boolean(match)
7214
- ).sort((a, b) => b.optionValueCount - a.optionValueCount);
7215
- if (optionSetMatches.length > 0) {
7216
- const images = optionSetMatches[0].images;
7217
- return {
7218
- primaryImage: images[0] ?? null,
7219
- images,
7220
- source: "option_value_set"
7221
- };
7222
- }
7223
- const defaultSet = input.mediaSets.find((set) => set.matchType === "default");
7224
- if (defaultSet) {
7225
- const images = mediaSetItemsInPool(defaultSet, poolById);
7226
- if (images.length > 0) {
7227
- return {
7228
- primaryImage: images[0] ?? null,
7229
- images,
7230
- source: "default_set"
7231
- };
7232
- }
7233
- }
7234
- return {
7235
- primaryImage: null,
7236
- images: [],
7237
- source: "none"
7238
- };
7239
- }
7240
- function resolveProductGallery(input) {
7241
- const selectedVariantId = mediaId(input.selectedVariantId);
7242
- const selectedOptionValueIds = relationshipIds(input.selectedOptionValueIds);
7243
- const selection = resolveProductSelectionMedia({
7244
- ...input,
7245
- productMediaPool: input.productMediaPool ?? input.pool ?? null,
7246
- selectedVariant: input.selectedVariant ?? (selectedVariantId ? { id: selectedVariantId } : null),
7247
- selectedOptionValues: input.selectedOptionValues ?? selectedOptionValueIds.map((id) => ({ id }))
7248
- });
7249
- if (selection.source !== "none") {
7250
- return selection;
7251
- }
7252
- const legacyResolved = resolveLegacyMediaSet(input);
7253
- if (legacyResolved && legacyResolved.source !== "none") return legacyResolved;
7254
- return resolveProductDisplayMedia({
7255
- productMediaPool: input.productMediaPool ?? input.pool ?? null,
7256
- featuredImage: input.featuredImage
7257
- });
7258
- }
7259
-
7260
7302
  // src/utils/image.ts
7261
7303
  var IMAGE_SIZES = [200, 400, 800, 1200, 1600];
7262
7304
  function imageSizeCandidates(sizes) {
@@ -7388,7 +7430,7 @@ function createAnalytics(config) {
7388
7430
  }, destroy() {
7389
7431
  } };
7390
7432
  }
7391
- const endpoint2 = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
7433
+ const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
7392
7434
  const respectDnt = config.respectDnt !== false;
7393
7435
  function isDntActive() {
7394
7436
  if (!respectDnt) return false;
@@ -7429,10 +7471,10 @@ function createAnalytics(config) {
7429
7471
  try {
7430
7472
  if (typeof navigator.sendBeacon === "function") {
7431
7473
  const blob = new Blob([body], { type: "text/plain" });
7432
- const sent = navigator.sendBeacon(endpoint2, blob);
7474
+ const sent = navigator.sendBeacon(endpoint, blob);
7433
7475
  if (sent) return;
7434
7476
  }
7435
- fetch(endpoint2, {
7477
+ fetch(endpoint, {
7436
7478
  method: "POST",
7437
7479
  keepalive: true,
7438
7480
  headers: { "Content-Type": "application/json" },
@@ -7648,6 +7690,7 @@ export {
7648
7690
  getImageSrcSet,
7649
7691
  getImageUrl,
7650
7692
  getProductSelectionImages,
7693
+ getSDKErrorReason,
7651
7694
  getSelectedValueByOptionId,
7652
7695
  getVariantAvailableForSale,
7653
7696
  getVariantAvailableStock,
@@ -7688,8 +7731,6 @@ export {
7688
7731
  projectProductToListingShape,
7689
7732
  resolveFeaturedImagePointer,
7690
7733
  resolveProductDisplayMedia,
7691
- resolveProductGallery,
7692
- resolveProductMedia,
7693
7734
  resolveProductSelection,
7694
7735
  resolveProductSelectionFromMatrix,
7695
7736
  resolveProductSelectionMedia,