@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.
- package/CHANGELOG.md +157 -1
- package/MIGRATION.md +56 -0
- package/README.md +276 -49
- package/dist/client.cjs +375 -161
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +7 -6
- package/dist/client.d.ts +7 -6
- package/dist/client.js +375 -161
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-CBup9yOx.d.cts → collection-client-CWAeuzV4.d.cts} +6 -4
- package/dist/{collection-client-D3ExJU-7.d.ts → collection-client-hYvVfHIm.d.ts} +6 -4
- package/dist/{const-k9gHylYa.d.ts → const-D8LixhAJ.d.cts} +5 -5
- package/dist/{const-BXEi1Kix.d.cts → const-JD8obaKg.d.ts} +5 -5
- package/dist/embedded-admin/server.cjs +306 -0
- package/dist/embedded-admin/server.cjs.map +1 -0
- package/dist/embedded-admin/server.d.cts +33 -0
- package/dist/embedded-admin/server.d.ts +33 -0
- package/dist/embedded-admin/server.js +288 -0
- package/dist/embedded-admin/server.js.map +1 -0
- package/dist/embedded-admin.cjs +400 -0
- package/dist/embedded-admin.cjs.map +1 -0
- package/dist/embedded-admin.d.cts +61 -0
- package/dist/embedded-admin.d.ts +61 -0
- package/dist/embedded-admin.js +377 -0
- package/dist/embedded-admin.js.map +1 -0
- package/dist/errors.cjs +64 -15
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +13 -4
- package/dist/errors.d.ts +13 -4
- package/dist/errors.js +64 -15
- package/dist/errors.js.map +1 -1
- package/dist/{index-BCM9CTL7.d.cts → index-B0Hjh3Ey.d.ts} +72 -10
- package/dist/{index-CHGGkcLj.d.ts → index-Bu0kCc6o.d.cts} +72 -10
- package/dist/index.cjs +470 -429
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -67
- package/dist/index.d.ts +9 -67
- package/dist/index.js +470 -429
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-B6AZQcB7.d.cts → payload-types-BOsckg8B.d.cts} +396 -57
- package/dist/{payload-types-B6AZQcB7.d.ts → payload-types-BOsckg8B.d.ts} +396 -57
- package/dist/query.cjs +115 -70
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +5 -5
- package/dist/query.d.ts +5 -5
- package/dist/query.js +115 -70
- package/dist/query.js.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/server.cjs +591 -186
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +8 -7
- package/dist/server.d.ts +8 -7
- package/dist/server.js +591 -186
- package/dist/server.js.map +1 -1
- package/dist/storefront-cache.cjs +22 -0
- package/dist/storefront-cache.cjs.map +1 -1
- package/dist/storefront-cache.js +22 -0
- package/dist/storefront-cache.js.map +1 -1
- package/dist/{types-ByD2zii1.d.ts → types-5ZlcAFuU.d.ts} +2 -2
- package/dist/{types-8us-_C-Q.d.cts → types-B14sEt1z.d.cts} +2 -2
- package/dist/{types-CM2je9Kw.d.cts → types-Bj8j7VHU.d.ts} +107 -26
- package/dist/{types-DbA5V3mt.d.ts → types-CM5qiR2k.d.cts} +107 -26
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.d.cts +1 -1
- package/dist/ui/video.d.ts +1 -1
- package/dist/webhook.cjs +124 -80
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +21 -5
- package/dist/webhook.d.ts +21 -5
- package/dist/webhook.js +124 -80
- package/dist/webhook.js.map +1 -1
- package/package.json +27 -5
package/dist/index.cjs
CHANGED
|
@@ -89,6 +89,7 @@ __export(src_exports, {
|
|
|
89
89
|
getImageSrcSet: () => getImageSrcSet,
|
|
90
90
|
getImageUrl: () => getImageUrl,
|
|
91
91
|
getProductSelectionImages: () => getProductSelectionImages,
|
|
92
|
+
getSDKErrorReason: () => getSDKErrorReason,
|
|
92
93
|
getSelectedValueByOptionId: () => getSelectedValueByOptionId,
|
|
93
94
|
getVariantAvailableForSale: () => getVariantAvailableForSale,
|
|
94
95
|
getVariantAvailableStock: () => getVariantAvailableStock,
|
|
@@ -129,8 +130,6 @@ __export(src_exports, {
|
|
|
129
130
|
projectProductToListingShape: () => projectProductToListingShape,
|
|
130
131
|
resolveFeaturedImagePointer: () => resolveFeaturedImagePointer,
|
|
131
132
|
resolveProductDisplayMedia: () => resolveProductDisplayMedia,
|
|
132
|
-
resolveProductGallery: () => resolveProductGallery,
|
|
133
|
-
resolveProductMedia: () => resolveProductMedia,
|
|
134
133
|
resolveProductSelection: () => resolveProductSelection,
|
|
135
134
|
resolveProductSelectionFromMatrix: () => resolveProductSelectionFromMatrix,
|
|
136
135
|
resolveProductSelectionMedia: () => resolveProductSelectionMedia,
|
|
@@ -147,6 +146,24 @@ module.exports = __toCommonJS(src_exports);
|
|
|
147
146
|
var import_qs_esm = require("qs-esm");
|
|
148
147
|
|
|
149
148
|
// src/core/errors.ts
|
|
149
|
+
var SDK_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError");
|
|
150
|
+
var SDK_ERROR_TYPE_BRAND = /* @__PURE__ */ Symbol.for("@01.software/sdk/SDKError.type");
|
|
151
|
+
function defineSDKErrorBrand(error) {
|
|
152
|
+
Object.defineProperty(error, SDK_ERROR_BRAND, {
|
|
153
|
+
value: true,
|
|
154
|
+
enumerable: false,
|
|
155
|
+
configurable: false,
|
|
156
|
+
writable: false
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function defineSDKErrorType(error, type) {
|
|
160
|
+
Object.defineProperty(error, SDK_ERROR_TYPE_BRAND, {
|
|
161
|
+
value: type,
|
|
162
|
+
enumerable: false,
|
|
163
|
+
configurable: false,
|
|
164
|
+
writable: false
|
|
165
|
+
});
|
|
166
|
+
}
|
|
150
167
|
var SDKError = class extends Error {
|
|
151
168
|
constructor(code, message, status, details, userMessage, suggestion, requestId) {
|
|
152
169
|
super(message);
|
|
@@ -157,6 +174,7 @@ var SDKError = class extends Error {
|
|
|
157
174
|
this.userMessage = userMessage;
|
|
158
175
|
this.suggestion = suggestion;
|
|
159
176
|
this.requestId = requestId;
|
|
177
|
+
defineSDKErrorBrand(this);
|
|
160
178
|
if (Error.captureStackTrace) {
|
|
161
179
|
Error.captureStackTrace(this, new.target);
|
|
162
180
|
}
|
|
@@ -177,6 +195,7 @@ var SDKError = class extends Error {
|
|
|
177
195
|
...this.kind !== void 0 && { kind: this.kind },
|
|
178
196
|
...this.reason !== void 0 && { reason: this.reason },
|
|
179
197
|
...this.rawReason !== void 0 && { rawReason: this.rawReason },
|
|
198
|
+
...this.apiReason !== void 0 && { apiReason: this.apiReason },
|
|
180
199
|
...this.retryable !== void 0 && { retryable: this.retryable },
|
|
181
200
|
...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
|
|
182
201
|
};
|
|
@@ -222,6 +241,7 @@ var COMMERCE_ERROR_CODES = [
|
|
|
222
241
|
"payment_session_not_cancelable",
|
|
223
242
|
"payment_session_conflict",
|
|
224
243
|
"provider_identity_mismatch",
|
|
244
|
+
"managed_refund_attestation_forbidden",
|
|
225
245
|
"payment_method_unavailable",
|
|
226
246
|
"provider_unavailable",
|
|
227
247
|
"lock_timeout",
|
|
@@ -350,8 +370,16 @@ function enhanceCommerceError(error, body, headerRequestId) {
|
|
|
350
370
|
});
|
|
351
371
|
return error;
|
|
352
372
|
}
|
|
373
|
+
function enhanceNonCommerceError(error, reason) {
|
|
374
|
+
if (typeof reason === "string") Object.assign(error, { apiReason: reason });
|
|
375
|
+
return error;
|
|
376
|
+
}
|
|
377
|
+
function getSDKErrorReason(error) {
|
|
378
|
+
if (error.kind !== "commerce") return error.apiReason;
|
|
379
|
+
return error.reason === "unknown_commerce_error" ? error.rawReason : error.reason;
|
|
380
|
+
}
|
|
353
381
|
function isCommerceSDKError(error) {
|
|
354
|
-
if (!(error
|
|
382
|
+
if (!isSDKError(error) || error.kind !== "commerce") return false;
|
|
355
383
|
if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
|
|
356
384
|
return false;
|
|
357
385
|
}
|
|
@@ -361,12 +389,14 @@ var NetworkError = class extends SDKError {
|
|
|
361
389
|
constructor(message, status, details, userMessage, suggestion) {
|
|
362
390
|
super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
|
|
363
391
|
this.name = "NetworkError";
|
|
392
|
+
defineSDKErrorType(this, "NetworkError");
|
|
364
393
|
}
|
|
365
394
|
};
|
|
366
395
|
var ValidationError = class extends SDKError {
|
|
367
396
|
constructor(message, details, userMessage, suggestion, status = 400) {
|
|
368
397
|
super("VALIDATION_ERROR", message, status, details, userMessage, suggestion);
|
|
369
398
|
this.name = "ValidationError";
|
|
399
|
+
defineSDKErrorType(this, "ValidationError");
|
|
370
400
|
}
|
|
371
401
|
};
|
|
372
402
|
var ApiError = class extends SDKError {
|
|
@@ -381,24 +411,28 @@ var ApiError = class extends SDKError {
|
|
|
381
411
|
requestId
|
|
382
412
|
);
|
|
383
413
|
this.name = "ApiError";
|
|
414
|
+
defineSDKErrorType(this, "ApiError");
|
|
384
415
|
}
|
|
385
416
|
};
|
|
386
417
|
var ConfigError = class extends SDKError {
|
|
387
418
|
constructor(message, details, userMessage, suggestion) {
|
|
388
419
|
super("CONFIG_ERROR", message, void 0, details, userMessage, suggestion);
|
|
389
420
|
this.name = "ConfigError";
|
|
421
|
+
defineSDKErrorType(this, "ConfigError");
|
|
390
422
|
}
|
|
391
423
|
};
|
|
392
424
|
var TimeoutError = class extends SDKError {
|
|
393
425
|
constructor(message = "Request timed out.", details, userMessage, suggestion) {
|
|
394
426
|
super("TIMEOUT_ERROR", message, 408, details, userMessage, suggestion);
|
|
395
427
|
this.name = "TimeoutError";
|
|
428
|
+
defineSDKErrorType(this, "TimeoutError");
|
|
396
429
|
}
|
|
397
430
|
};
|
|
398
431
|
var GoneError = class extends SDKError {
|
|
399
432
|
constructor(message = "The requested resource is no longer available.", details, userMessage, suggestion) {
|
|
400
433
|
super("GONE_ERROR", message, 410, details, userMessage, suggestion);
|
|
401
434
|
this.name = "GoneError";
|
|
435
|
+
defineSDKErrorType(this, "GoneError");
|
|
402
436
|
}
|
|
403
437
|
};
|
|
404
438
|
var ServiceUnavailableError = class extends SDKError {
|
|
@@ -413,6 +447,7 @@ var ServiceUnavailableError = class extends SDKError {
|
|
|
413
447
|
);
|
|
414
448
|
this.name = "ServiceUnavailableError";
|
|
415
449
|
this.retryAfter = retryAfter;
|
|
450
|
+
defineSDKErrorType(this, "ServiceUnavailableError");
|
|
416
451
|
}
|
|
417
452
|
};
|
|
418
453
|
var UsageLimitError = class extends SDKError {
|
|
@@ -420,6 +455,7 @@ var UsageLimitError = class extends SDKError {
|
|
|
420
455
|
super("USAGE_LIMIT_ERROR", message, 429, details, userMessage, suggestion);
|
|
421
456
|
this.name = "UsageLimitError";
|
|
422
457
|
this.usage = usage;
|
|
458
|
+
defineSDKErrorType(this, "UsageLimitError");
|
|
423
459
|
}
|
|
424
460
|
toJSON() {
|
|
425
461
|
return {
|
|
@@ -440,6 +476,7 @@ var AuthError = class extends SDKError {
|
|
|
440
476
|
requestId
|
|
441
477
|
);
|
|
442
478
|
this.name = "AuthError";
|
|
479
|
+
defineSDKErrorType(this, "AuthError");
|
|
443
480
|
}
|
|
444
481
|
};
|
|
445
482
|
var PermissionError = class extends SDKError {
|
|
@@ -454,6 +491,7 @@ var PermissionError = class extends SDKError {
|
|
|
454
491
|
requestId
|
|
455
492
|
);
|
|
456
493
|
this.name = "PermissionError";
|
|
494
|
+
defineSDKErrorType(this, "PermissionError");
|
|
457
495
|
}
|
|
458
496
|
};
|
|
459
497
|
var NotFoundError = class extends SDKError {
|
|
@@ -468,12 +506,14 @@ var NotFoundError = class extends SDKError {
|
|
|
468
506
|
requestId
|
|
469
507
|
);
|
|
470
508
|
this.name = "NotFoundError";
|
|
509
|
+
defineSDKErrorType(this, "NotFoundError");
|
|
471
510
|
}
|
|
472
511
|
};
|
|
473
512
|
var ConflictError = class extends SDKError {
|
|
474
513
|
constructor(message, details, userMessage, suggestion, requestId) {
|
|
475
514
|
super("conflict", message, 409, details, userMessage, suggestion, requestId);
|
|
476
515
|
this.name = "ConflictError";
|
|
516
|
+
defineSDKErrorType(this, "ConflictError");
|
|
477
517
|
}
|
|
478
518
|
};
|
|
479
519
|
var RateLimitError = class extends SDKError {
|
|
@@ -489,52 +529,63 @@ var RateLimitError = class extends SDKError {
|
|
|
489
529
|
);
|
|
490
530
|
this.name = "RateLimitError";
|
|
491
531
|
this.retryAfter = retryAfter;
|
|
532
|
+
defineSDKErrorType(this, "RateLimitError");
|
|
492
533
|
}
|
|
493
534
|
};
|
|
535
|
+
function hasBrandedSDKErrorShape(error) {
|
|
536
|
+
if (error === null || typeof error !== "object") return false;
|
|
537
|
+
const candidate = error;
|
|
538
|
+
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";
|
|
539
|
+
}
|
|
540
|
+
function hasSDKErrorType(error, type) {
|
|
541
|
+
return hasBrandedSDKErrorShape(error) && error[SDK_ERROR_TYPE_BRAND] === type;
|
|
542
|
+
}
|
|
494
543
|
function isSDKError(error) {
|
|
495
|
-
return error instanceof SDKError;
|
|
544
|
+
return error instanceof SDKError || hasBrandedSDKErrorShape(error);
|
|
496
545
|
}
|
|
497
546
|
function isNetworkError(error) {
|
|
498
|
-
return error instanceof NetworkError;
|
|
547
|
+
return error instanceof NetworkError || hasSDKErrorType(error, "NetworkError");
|
|
499
548
|
}
|
|
500
549
|
function isValidationError(error) {
|
|
501
|
-
if (error instanceof ValidationError)
|
|
550
|
+
if (error instanceof ValidationError || hasSDKErrorType(error, "ValidationError")) {
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
502
553
|
if (error == null || typeof error !== "object") return false;
|
|
503
554
|
const candidate = error;
|
|
504
555
|
return candidate.name === "ValidationError" && candidate.code === "VALIDATION_ERROR" && typeof candidate.message === "string" && typeof candidate.getUserMessage === "function" && typeof candidate.toJSON === "function";
|
|
505
556
|
}
|
|
506
557
|
function isApiError(error) {
|
|
507
|
-
return error instanceof ApiError;
|
|
558
|
+
return error instanceof ApiError || hasSDKErrorType(error, "ApiError");
|
|
508
559
|
}
|
|
509
560
|
function isConfigError(error) {
|
|
510
|
-
return error instanceof ConfigError;
|
|
561
|
+
return error instanceof ConfigError || hasSDKErrorType(error, "ConfigError");
|
|
511
562
|
}
|
|
512
563
|
function isTimeoutError(error) {
|
|
513
|
-
return error instanceof TimeoutError;
|
|
564
|
+
return error instanceof TimeoutError || hasSDKErrorType(error, "TimeoutError");
|
|
514
565
|
}
|
|
515
566
|
function isGoneError(error) {
|
|
516
|
-
return error instanceof GoneError;
|
|
567
|
+
return error instanceof GoneError || hasSDKErrorType(error, "GoneError");
|
|
517
568
|
}
|
|
518
569
|
function isServiceUnavailableError(error) {
|
|
519
|
-
return error instanceof ServiceUnavailableError;
|
|
570
|
+
return error instanceof ServiceUnavailableError || hasSDKErrorType(error, "ServiceUnavailableError");
|
|
520
571
|
}
|
|
521
572
|
function isUsageLimitError(error) {
|
|
522
|
-
return error instanceof UsageLimitError;
|
|
573
|
+
return error instanceof UsageLimitError || hasSDKErrorType(error, "UsageLimitError");
|
|
523
574
|
}
|
|
524
575
|
function isAuthError(error) {
|
|
525
|
-
return error instanceof AuthError;
|
|
576
|
+
return error instanceof AuthError || hasSDKErrorType(error, "AuthError");
|
|
526
577
|
}
|
|
527
578
|
function isPermissionError(error) {
|
|
528
|
-
return error instanceof PermissionError;
|
|
579
|
+
return error instanceof PermissionError || hasSDKErrorType(error, "PermissionError");
|
|
529
580
|
}
|
|
530
581
|
function isNotFoundError(error) {
|
|
531
|
-
return error instanceof NotFoundError;
|
|
582
|
+
return error instanceof NotFoundError || hasSDKErrorType(error, "NotFoundError");
|
|
532
583
|
}
|
|
533
584
|
function isConflictError(error) {
|
|
534
|
-
return error instanceof ConflictError;
|
|
585
|
+
return error instanceof ConflictError || hasSDKErrorType(error, "ConflictError");
|
|
535
586
|
}
|
|
536
587
|
function isRateLimitError(error) {
|
|
537
|
-
return error instanceof RateLimitError;
|
|
588
|
+
return error instanceof RateLimitError || hasSDKErrorType(error, "RateLimitError");
|
|
538
589
|
}
|
|
539
590
|
var createNetworkError = (message, status, details, userMessage, suggestion) => new NetworkError(message, status, details, userMessage, suggestion);
|
|
540
591
|
var createValidationError = (message, details, userMessage, suggestion, status) => new ValidationError(message, details, userMessage, suggestion, status);
|
|
@@ -733,11 +784,11 @@ function parseRetryAfter(response) {
|
|
|
733
784
|
permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
|
|
734
785
|
};
|
|
735
786
|
}
|
|
736
|
-
function mapResponseToError(status, parsed, details, requestId, retryAfter,
|
|
787
|
+
function mapResponseToError(status, parsed, details, requestId, retryAfter, canonicalCommerceError) {
|
|
737
788
|
const errorDetails = {
|
|
738
789
|
...details,
|
|
739
790
|
...parsed.errors && { errors: parsed.errors },
|
|
740
|
-
|
|
791
|
+
...!canonicalCommerceError && parsed.body && { body: parsed.body }
|
|
741
792
|
};
|
|
742
793
|
const suggestion = getParsedErrorSuggestion(status, parsed);
|
|
743
794
|
const finalize = (error) => {
|
|
@@ -745,7 +796,7 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, erro
|
|
|
745
796
|
if (retryAfter !== void 0) {
|
|
746
797
|
Object.assign(withRequestId, { retryAfter });
|
|
747
798
|
}
|
|
748
|
-
return
|
|
799
|
+
return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
|
|
749
800
|
};
|
|
750
801
|
if (status === 400 || status === 422) {
|
|
751
802
|
return finalize(
|
|
@@ -851,6 +902,7 @@ async function httpFetch(url, options) {
|
|
|
851
902
|
retry,
|
|
852
903
|
onUnauthorized,
|
|
853
904
|
errorFamily,
|
|
905
|
+
typedCommerceErrorReasons,
|
|
854
906
|
...requestInit
|
|
855
907
|
} = options || {};
|
|
856
908
|
const baseUrl = resolveApiUrl(apiUrl);
|
|
@@ -904,7 +956,8 @@ async function httpFetch(url, options) {
|
|
|
904
956
|
});
|
|
905
957
|
if (!response.ok) {
|
|
906
958
|
const parsed = await parseErrorBody(response);
|
|
907
|
-
const
|
|
959
|
+
const canonicalCommerceError = errorFamily === "commerce" || typeof parsed.reason === "string" && typedCommerceErrorReasons?.includes(parsed.reason) === true;
|
|
960
|
+
const commerceEnvelope = canonicalCommerceError ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
|
|
908
961
|
if (isUsageLimitExceededResponse(response)) {
|
|
909
962
|
const limit = parseInt(
|
|
910
963
|
response.headers.get("X-Usage-Limit") || "0",
|
|
@@ -932,7 +985,7 @@ async function httpFetch(url, options) {
|
|
|
932
985
|
),
|
|
933
986
|
requestId
|
|
934
987
|
);
|
|
935
|
-
throw
|
|
988
|
+
throw canonicalCommerceError ? enhanceCommerceError(usageError, parsed.body, requestId) : enhanceNonCommerceError(usageError, parsed.reason);
|
|
936
989
|
}
|
|
937
990
|
if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
|
|
938
991
|
hasRetried401 = true;
|
|
@@ -957,7 +1010,7 @@ async function httpFetch(url, options) {
|
|
|
957
1010
|
details,
|
|
958
1011
|
requestId,
|
|
959
1012
|
retryAfter.seconds,
|
|
960
|
-
|
|
1013
|
+
canonicalCommerceError
|
|
961
1014
|
);
|
|
962
1015
|
const method2 = (requestInit.method || "GET").toUpperCase();
|
|
963
1016
|
const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
|
|
@@ -1135,15 +1188,15 @@ var HttpClient = class {
|
|
|
1135
1188
|
throw err;
|
|
1136
1189
|
}
|
|
1137
1190
|
}
|
|
1138
|
-
buildUrl(
|
|
1139
|
-
if (!options) return
|
|
1191
|
+
buildUrl(endpoint, options) {
|
|
1192
|
+
if (!options) return endpoint;
|
|
1140
1193
|
const { fallbackLocale, ...rest } = options;
|
|
1141
1194
|
const queryOptions = fallbackLocale === void 0 ? rest : {
|
|
1142
1195
|
...rest,
|
|
1143
1196
|
"fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
|
|
1144
1197
|
};
|
|
1145
1198
|
const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
|
|
1146
|
-
return queryString ? `${
|
|
1199
|
+
return queryString ? `${endpoint}${queryString}` : endpoint;
|
|
1147
1200
|
}
|
|
1148
1201
|
assertJsonResponse(response) {
|
|
1149
1202
|
const contentType = response.headers.get("content-type");
|
|
@@ -1292,39 +1345,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1292
1345
|
from(collection) {
|
|
1293
1346
|
return new ReadOnlyCollectionQueryBuilder(this, collection);
|
|
1294
1347
|
}
|
|
1295
|
-
async requestFind(
|
|
1296
|
-
const url = this.buildUrl(
|
|
1348
|
+
async requestFind(endpoint, options) {
|
|
1349
|
+
const url = this.buildUrl(endpoint, options);
|
|
1297
1350
|
const response = await this.fetchWithTracking(url, {
|
|
1298
1351
|
...this.defaultOptions,
|
|
1299
1352
|
method: "GET"
|
|
1300
1353
|
});
|
|
1301
1354
|
return this.parseFindResponse(response);
|
|
1302
1355
|
}
|
|
1303
|
-
async requestFindEndpoint(
|
|
1304
|
-
const response = await this.fetchWithTracking(
|
|
1356
|
+
async requestFindEndpoint(endpoint, data) {
|
|
1357
|
+
const response = await this.fetchWithTracking(endpoint, {
|
|
1305
1358
|
...this.defaultOptions,
|
|
1306
1359
|
method: "POST",
|
|
1307
1360
|
body: data ? JSON.stringify(data) : void 0
|
|
1308
1361
|
});
|
|
1309
1362
|
return this.parseFindResponse(response);
|
|
1310
1363
|
}
|
|
1311
|
-
async requestFindEndpointGet(
|
|
1312
|
-
const response = await this.fetchWithTracking(
|
|
1364
|
+
async requestFindEndpointGet(endpoint) {
|
|
1365
|
+
const response = await this.fetchWithTracking(endpoint, {
|
|
1313
1366
|
...this.defaultOptions,
|
|
1314
1367
|
method: "GET"
|
|
1315
1368
|
});
|
|
1316
1369
|
return this.parseFindResponse(response);
|
|
1317
1370
|
}
|
|
1318
|
-
async requestFindById(
|
|
1319
|
-
const url = this.buildUrl(
|
|
1371
|
+
async requestFindById(endpoint, options) {
|
|
1372
|
+
const url = this.buildUrl(endpoint, options);
|
|
1320
1373
|
const response = await this.fetchWithTracking(url, {
|
|
1321
1374
|
...this.defaultOptions,
|
|
1322
1375
|
method: "GET"
|
|
1323
1376
|
});
|
|
1324
1377
|
return this.parseDocumentResponse(response);
|
|
1325
1378
|
}
|
|
1326
|
-
async requestCount(
|
|
1327
|
-
const url = this.buildUrl(
|
|
1379
|
+
async requestCount(endpoint, options) {
|
|
1380
|
+
const url = this.buildUrl(endpoint, options);
|
|
1328
1381
|
const response = await this.fetchWithTracking(url, {
|
|
1329
1382
|
...this.defaultOptions,
|
|
1330
1383
|
method: "GET"
|
|
@@ -1334,7 +1387,7 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1334
1387
|
};
|
|
1335
1388
|
|
|
1336
1389
|
// src/core/api/parse-response.ts
|
|
1337
|
-
async function parseApiResponse(response,
|
|
1390
|
+
async function parseApiResponse(response, endpoint, options = {}) {
|
|
1338
1391
|
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
1339
1392
|
return void 0;
|
|
1340
1393
|
}
|
|
@@ -1343,7 +1396,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
|
|
|
1343
1396
|
parsed = await response.json();
|
|
1344
1397
|
} catch {
|
|
1345
1398
|
throw createApiError(
|
|
1346
|
-
`Invalid JSON response from ${
|
|
1399
|
+
`Invalid JSON response from ${endpoint}`,
|
|
1347
1400
|
response.status,
|
|
1348
1401
|
void 0,
|
|
1349
1402
|
"Server returned an invalid response.",
|
|
@@ -1386,13 +1439,14 @@ async function parseApiResponse(response, endpoint2, options = {}) {
|
|
|
1386
1439
|
}
|
|
1387
1440
|
const withRequestId = attachRequestId(error, requestId);
|
|
1388
1441
|
if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
|
|
1389
|
-
throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
|
|
1442
|
+
throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : enhanceNonCommerceError(withRequestId, reason);
|
|
1390
1443
|
}
|
|
1391
1444
|
return data;
|
|
1392
1445
|
}
|
|
1393
1446
|
|
|
1394
1447
|
// ../../internal/http-contracts/src/index.ts
|
|
1395
1448
|
var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
|
|
1449
|
+
var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
|
|
1396
1450
|
var operation = (collection, method, path, errorFamily) => Object.freeze({
|
|
1397
1451
|
[operationBrand]: true,
|
|
1398
1452
|
collection,
|
|
@@ -1401,6 +1455,10 @@ var operation = (collection, method, path, errorFamily) => Object.freeze({
|
|
|
1401
1455
|
...errorFamily && { errorFamily }
|
|
1402
1456
|
});
|
|
1403
1457
|
var strictCommerceOperation = (collection, method, path) => operation(collection, method, path, "commerce");
|
|
1458
|
+
var selectiveCommerceOperation = (collection, method, path, typedCommerceErrorReasons) => Object.freeze({
|
|
1459
|
+
...operation(collection, method, path),
|
|
1460
|
+
typedCommerceErrorReasons: Object.freeze([...typedCommerceErrorReasons])
|
|
1461
|
+
});
|
|
1404
1462
|
var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
1405
1463
|
products: {
|
|
1406
1464
|
detail: operation("products", "get", "/detail"),
|
|
@@ -1432,7 +1490,12 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1432
1490
|
confirmPayment: operation("orders", "post", "/confirm-payment"),
|
|
1433
1491
|
byPayment: operation("orders", "get", "/by-payment"),
|
|
1434
1492
|
cancel: operation("orders", "post", "/cancel"),
|
|
1435
|
-
resolveCancelRefund:
|
|
1493
|
+
resolveCancelRefund: selectiveCommerceOperation(
|
|
1494
|
+
"orders",
|
|
1495
|
+
"post",
|
|
1496
|
+
"/resolve-cancel-refund",
|
|
1497
|
+
["managed_refund_attestation_forbidden"]
|
|
1498
|
+
),
|
|
1436
1499
|
checkout: strictCommerceOperation("orders", "post", "/checkout"),
|
|
1437
1500
|
createFulfillment: operation("orders", "post", "/create-fulfillment"),
|
|
1438
1501
|
updateFulfillment: operation("orders", "post", "/update-fulfillment")
|
|
@@ -1503,6 +1566,16 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1503
1566
|
"payment-sessions",
|
|
1504
1567
|
"post",
|
|
1505
1568
|
"/server/confirm"
|
|
1569
|
+
),
|
|
1570
|
+
findPortOne: strictCommerceOperation(
|
|
1571
|
+
"payment-sessions",
|
|
1572
|
+
"post",
|
|
1573
|
+
"/server/portone/find"
|
|
1574
|
+
),
|
|
1575
|
+
reconcilePortOne: strictCommerceOperation(
|
|
1576
|
+
"payment-sessions",
|
|
1577
|
+
"post",
|
|
1578
|
+
"/server/portone/reconcile"
|
|
1506
1579
|
)
|
|
1507
1580
|
},
|
|
1508
1581
|
custom: {
|
|
@@ -1522,12 +1595,26 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1522
1595
|
validate: operation("discounts", "post", "/validate")
|
|
1523
1596
|
}
|
|
1524
1597
|
};
|
|
1598
|
+
var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
|
|
1599
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.create,
|
|
1600
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.retrieve,
|
|
1601
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.create,
|
|
1602
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.retrieve
|
|
1603
|
+
]);
|
|
1525
1604
|
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
1526
1605
|
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
1527
1606
|
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
1528
1607
|
me: operation(null, "get", "/memberships/me")
|
|
1529
1608
|
};
|
|
1609
|
+
var EMBEDDED_ADMIN_ENDPOINT_OPERATIONS = {
|
|
1610
|
+
show: operation("tenants", "get", "/embedded-admin-app"),
|
|
1611
|
+
configure: operation("tenants", "patch", "/embedded-admin-app"),
|
|
1612
|
+
disable: operation("tenants", "delete", "/embedded-admin-app")
|
|
1613
|
+
};
|
|
1530
1614
|
var EVENTS_ENDPOINT_OPERATIONS = {
|
|
1615
|
+
events: {
|
|
1616
|
+
convertSchedule: operation("events", "post", "/:id/schedule")
|
|
1617
|
+
},
|
|
1531
1618
|
occurrences: {
|
|
1532
1619
|
range: operation("event-occurrences", "get", "/range"),
|
|
1533
1620
|
admissionAvailability: operation(
|
|
@@ -1568,46 +1655,51 @@ function resolveOperationMethod(descriptor) {
|
|
|
1568
1655
|
}
|
|
1569
1656
|
|
|
1570
1657
|
// src/core/api/endpoints.ts
|
|
1571
|
-
var endpoint = (method, path) => ({ method, path });
|
|
1572
1658
|
var sharedEndpoint = (descriptor) => descriptor;
|
|
1573
|
-
function resolveOperationMethod2(descriptor) {
|
|
1574
|
-
return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
|
|
1575
|
-
}
|
|
1576
1659
|
function resolveOperationErrorFamily(descriptor) {
|
|
1577
|
-
return
|
|
1578
|
-
}
|
|
1579
|
-
function resolveOperationPath2(descriptor, options) {
|
|
1580
|
-
if ("collection" in descriptor) {
|
|
1581
|
-
return resolveOperationPath(descriptor, options);
|
|
1582
|
-
}
|
|
1583
|
-
const query = options?.query?.toString().replace(/^\?/, "");
|
|
1584
|
-
return query ? `${descriptor.path}?${query}` : descriptor.path;
|
|
1660
|
+
return descriptor.errorFamily;
|
|
1585
1661
|
}
|
|
1586
1662
|
var COMMERCE_ENDPOINTS = {
|
|
1587
1663
|
products: {
|
|
1588
|
-
detail:
|
|
1589
|
-
detailCatalog:
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1664
|
+
detail: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.detail),
|
|
1665
|
+
detailCatalog: sharedEndpoint(
|
|
1666
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog
|
|
1667
|
+
),
|
|
1668
|
+
listingGroups: sharedEndpoint(
|
|
1669
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups
|
|
1670
|
+
),
|
|
1671
|
+
listingGroupsCatalog: sharedEndpoint(
|
|
1672
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog
|
|
1673
|
+
),
|
|
1674
|
+
// The manifest keeps the GET read and the POST body-query apart; this
|
|
1675
|
+
// semantic name has always resolved to the GET one.
|
|
1676
|
+
listingGroupsQuery: sharedEndpoint(
|
|
1677
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet
|
|
1678
|
+
),
|
|
1679
|
+
listingGroupsQueryCatalog: sharedEndpoint(
|
|
1680
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog
|
|
1681
|
+
),
|
|
1682
|
+
stockCheck: sharedEndpoint(
|
|
1683
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck
|
|
1594
1684
|
),
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
"GET",
|
|
1598
|
-
"/api/products/listing-groups/query/catalog"
|
|
1685
|
+
stockSnapshot: sharedEndpoint(
|
|
1686
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot
|
|
1599
1687
|
),
|
|
1600
|
-
|
|
1601
|
-
stockSnapshot: endpoint("GET", "/api/products/stock"),
|
|
1602
|
-
upsert: endpoint("POST", "/api/products/upsert")
|
|
1688
|
+
upsert: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.upsert)
|
|
1603
1689
|
},
|
|
1604
1690
|
orders: {
|
|
1605
|
-
update:
|
|
1606
|
-
byPayment:
|
|
1607
|
-
cancel:
|
|
1608
|
-
resolveCancelRefund:
|
|
1609
|
-
|
|
1610
|
-
|
|
1691
|
+
update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.update),
|
|
1692
|
+
byPayment: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.byPayment),
|
|
1693
|
+
cancel: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.cancel),
|
|
1694
|
+
resolveCancelRefund: sharedEndpoint(
|
|
1695
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.resolveCancelRefund
|
|
1696
|
+
),
|
|
1697
|
+
createFulfillment: sharedEndpoint(
|
|
1698
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.createFulfillment
|
|
1699
|
+
),
|
|
1700
|
+
updateFulfillment: sharedEndpoint(
|
|
1701
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.updateFulfillment
|
|
1702
|
+
)
|
|
1611
1703
|
},
|
|
1612
1704
|
checkouts: {
|
|
1613
1705
|
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.checkout),
|
|
@@ -1619,18 +1711,21 @@ var COMMERCE_ENDPOINTS = {
|
|
|
1619
1711
|
}
|
|
1620
1712
|
},
|
|
1621
1713
|
returns: {
|
|
1622
|
-
create:
|
|
1623
|
-
update:
|
|
1624
|
-
returnRefund:
|
|
1714
|
+
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.create),
|
|
1715
|
+
update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.update),
|
|
1716
|
+
returnRefund: sharedEndpoint(
|
|
1717
|
+
COMMERCE_ENDPOINT_OPERATIONS.returns.returnRefund
|
|
1718
|
+
)
|
|
1625
1719
|
},
|
|
1626
1720
|
fulfillmentOrders: {
|
|
1627
|
-
prepare:
|
|
1628
|
-
|
|
1629
|
-
"/api/fulfillment-orders/prepare-fulfillment-order"
|
|
1721
|
+
prepare: sharedEndpoint(
|
|
1722
|
+
COMMERCE_ENDPOINT_OPERATIONS.fulfillmentOrders.prepare
|
|
1630
1723
|
)
|
|
1631
1724
|
},
|
|
1632
1725
|
fulfillments: {
|
|
1633
|
-
bulkImport:
|
|
1726
|
+
bulkImport: sharedEndpoint(
|
|
1727
|
+
COMMERCE_ENDPOINT_OPERATIONS.fulfillments.bulkImport
|
|
1728
|
+
)
|
|
1634
1729
|
},
|
|
1635
1730
|
carts: {
|
|
1636
1731
|
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
|
|
@@ -1695,42 +1790,21 @@ var COMMERCE_ENDPOINTS = {
|
|
|
1695
1790
|
),
|
|
1696
1791
|
confirm: sharedEndpoint(
|
|
1697
1792
|
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.confirm
|
|
1793
|
+
),
|
|
1794
|
+
findPortOne: sharedEndpoint(
|
|
1795
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.findPortOne
|
|
1796
|
+
),
|
|
1797
|
+
reconcilePortOne: sharedEndpoint(
|
|
1798
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.reconcilePortOne
|
|
1698
1799
|
)
|
|
1699
1800
|
}
|
|
1700
1801
|
},
|
|
1701
1802
|
shippingPolicies: {
|
|
1702
|
-
calculate:
|
|
1803
|
+
calculate: sharedEndpoint(
|
|
1804
|
+
COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate
|
|
1805
|
+
)
|
|
1703
1806
|
}
|
|
1704
1807
|
};
|
|
1705
|
-
function isCommerceEndpointDescriptor(value) {
|
|
1706
|
-
if (!value || typeof value !== "object") return false;
|
|
1707
|
-
const candidate = value;
|
|
1708
|
-
return typeof candidate.method === "string" && typeof candidate.path === "string";
|
|
1709
|
-
}
|
|
1710
|
-
function flattenEndpointPaths(value) {
|
|
1711
|
-
if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
|
|
1712
|
-
if (!value || typeof value !== "object") return [];
|
|
1713
|
-
return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
|
|
1714
|
-
}
|
|
1715
|
-
function flattenEndpointDescriptors(value) {
|
|
1716
|
-
if (isCommerceEndpointDescriptor(value)) return [value];
|
|
1717
|
-
if (!value || typeof value !== "object") return [];
|
|
1718
|
-
return Object.values(value).flatMap(
|
|
1719
|
-
(entry) => flattenEndpointDescriptors(entry)
|
|
1720
|
-
);
|
|
1721
|
-
}
|
|
1722
|
-
var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
|
|
1723
|
-
var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
|
|
1724
|
-
var MEMBERSHIP_ENDPOINTS = {
|
|
1725
|
-
subscribe: "/api/memberships/subscribe",
|
|
1726
|
-
cancel: (id) => `/api/memberships/${id}/cancel`,
|
|
1727
|
-
me: "/api/memberships/me"
|
|
1728
|
-
};
|
|
1729
|
-
var MEMBERSHIP_ENDPOINT_PATHS = [
|
|
1730
|
-
MEMBERSHIP_ENDPOINTS.subscribe,
|
|
1731
|
-
MEMBERSHIP_ENDPOINTS.cancel(":id"),
|
|
1732
|
-
MEMBERSHIP_ENDPOINTS.me
|
|
1733
|
-
];
|
|
1734
1808
|
|
|
1735
1809
|
// src/core/api/customer-scoped-api.ts
|
|
1736
1810
|
var CustomerScopedTransport = class {
|
|
@@ -1751,10 +1825,10 @@ var CustomerScopedTransport = class {
|
|
|
1751
1825
|
this.onUnauthorized = options.onUnauthorized;
|
|
1752
1826
|
this.onRequestId = options.onRequestId;
|
|
1753
1827
|
}
|
|
1754
|
-
async request(
|
|
1828
|
+
async request(endpoint, options) {
|
|
1755
1829
|
const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
|
|
1756
1830
|
try {
|
|
1757
|
-
const response = await httpFetch(
|
|
1831
|
+
const response = await httpFetch(endpoint, {
|
|
1758
1832
|
method: options.method,
|
|
1759
1833
|
apiUrl: this.apiUrl,
|
|
1760
1834
|
publishableKey: this.publishableKey,
|
|
@@ -1768,7 +1842,7 @@ var CustomerScopedTransport = class {
|
|
|
1768
1842
|
...options.errorFamily && { errorFamily: options.errorFamily }
|
|
1769
1843
|
});
|
|
1770
1844
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
1771
|
-
return parseApiResponse(response,
|
|
1845
|
+
return parseApiResponse(response, endpoint, {
|
|
1772
1846
|
errorFamily: options.errorFamily
|
|
1773
1847
|
});
|
|
1774
1848
|
} catch (err) {
|
|
@@ -1782,12 +1856,12 @@ var CustomerScopedApi = class {
|
|
|
1782
1856
|
constructor(apiName, options) {
|
|
1783
1857
|
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1784
1858
|
}
|
|
1785
|
-
requestEndpoint(
|
|
1786
|
-
return this.transport.request(
|
|
1787
|
-
method:
|
|
1859
|
+
requestEndpoint(endpoint, body, options) {
|
|
1860
|
+
return this.transport.request(resolveOperationPath(endpoint, options), {
|
|
1861
|
+
method: resolveOperationMethod(endpoint),
|
|
1788
1862
|
body,
|
|
1789
1863
|
headers: options?.headers,
|
|
1790
|
-
errorFamily: resolveOperationErrorFamily(
|
|
1864
|
+
errorFamily: resolveOperationErrorFamily(endpoint)
|
|
1791
1865
|
});
|
|
1792
1866
|
}
|
|
1793
1867
|
};
|
|
@@ -1795,8 +1869,8 @@ var RawCustomerScopedApi = class {
|
|
|
1795
1869
|
constructor(apiName, options) {
|
|
1796
1870
|
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1797
1871
|
}
|
|
1798
|
-
request(
|
|
1799
|
-
return this.transport.request(
|
|
1872
|
+
request(endpoint, options) {
|
|
1873
|
+
return this.transport.request(endpoint, options);
|
|
1800
1874
|
}
|
|
1801
1875
|
};
|
|
1802
1876
|
|
|
@@ -1810,13 +1884,7 @@ function unwrapPayloadDoc(value) {
|
|
|
1810
1884
|
return value;
|
|
1811
1885
|
}
|
|
1812
1886
|
function hasCanonicalNotFoundReason(error) {
|
|
1813
|
-
|
|
1814
|
-
if (typeof details !== "object" || details === null) return false;
|
|
1815
|
-
if ("reason" in details && details.reason === "not_found") return true;
|
|
1816
|
-
if (!("body" in details) || typeof details.body !== "object" || details.body === null) {
|
|
1817
|
-
return false;
|
|
1818
|
-
}
|
|
1819
|
-
return "reason" in details.body && details.body.reason === "not_found";
|
|
1887
|
+
return getSDKErrorReason(error) === "not_found";
|
|
1820
1888
|
}
|
|
1821
1889
|
var CommunityClient = class extends RawCustomerScopedApi {
|
|
1822
1890
|
constructor(options) {
|
|
@@ -1877,11 +1945,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
1877
1945
|
if (params.page !== void 0) urlParams.set("page", String(params.page));
|
|
1878
1946
|
return `/api/comments/public?${urlParams.toString()}`;
|
|
1879
1947
|
}
|
|
1880
|
-
async execute(
|
|
1881
|
-
return this.request(
|
|
1948
|
+
async execute(endpoint, method, body) {
|
|
1949
|
+
return this.request(endpoint, { method, body });
|
|
1882
1950
|
}
|
|
1883
|
-
async executeDoc(
|
|
1884
|
-
const response = await this.execute(
|
|
1951
|
+
async executeDoc(endpoint, method, body) {
|
|
1952
|
+
const response = await this.execute(endpoint, method, body);
|
|
1885
1953
|
return unwrapPayloadDoc(response);
|
|
1886
1954
|
}
|
|
1887
1955
|
createPost(params) {
|
|
@@ -2147,8 +2215,8 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
2147
2215
|
|
|
2148
2216
|
// src/core/content/content-client.ts
|
|
2149
2217
|
var PublicContentApi = class extends RawCustomerScopedApi {
|
|
2150
|
-
get(
|
|
2151
|
-
return this.request(
|
|
2218
|
+
get(endpoint) {
|
|
2219
|
+
return this.request(endpoint, { method: "GET" });
|
|
2152
2220
|
}
|
|
2153
2221
|
};
|
|
2154
2222
|
function appendCommonParams(search, options, defaultSort) {
|
|
@@ -2329,6 +2397,9 @@ function nullableString(value, resource, path) {
|
|
|
2329
2397
|
fail(resource, path, "string or null");
|
|
2330
2398
|
}
|
|
2331
2399
|
}
|
|
2400
|
+
function nullableNonEmptyString(value, resource, path) {
|
|
2401
|
+
if (value !== null) string(value, resource, path);
|
|
2402
|
+
}
|
|
2332
2403
|
function cartLineQuantity(value, resource, path) {
|
|
2333
2404
|
const quantity = positiveInteger(value, resource, path);
|
|
2334
2405
|
if (quantity > MAX_CART_LINE_QUANTITY) {
|
|
@@ -2838,8 +2909,8 @@ function validatePublicOrderItem(value, resource, path) {
|
|
|
2838
2909
|
validateReference(item.variant, resource, `${path}.variant`);
|
|
2839
2910
|
}
|
|
2840
2911
|
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2841
|
-
|
|
2842
|
-
|
|
2912
|
+
nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
2913
|
+
nullableNonEmptyString(item.sku, resource, `${path}.sku`);
|
|
2843
2914
|
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2844
2915
|
const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
|
|
2845
2916
|
const unitPrice = safeMinor(
|
|
@@ -3090,8 +3161,8 @@ function validateCheckoutItem(value, resource, path) {
|
|
|
3090
3161
|
validateReference(item.product, resource, `${path}.product`);
|
|
3091
3162
|
validateReference(item.variant, resource, `${path}.variant`);
|
|
3092
3163
|
string(item.productTitle, resource, `${path}.productTitle`);
|
|
3093
|
-
|
|
3094
|
-
|
|
3164
|
+
nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
3165
|
+
nullableNonEmptyString(item.sku, resource, `${path}.sku`);
|
|
3095
3166
|
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
3096
3167
|
cartLineQuantity(item.quantity, resource, `${path}.quantity`);
|
|
3097
3168
|
const unitPrice = safeMinor(
|
|
@@ -3422,9 +3493,96 @@ function validateRequiredReconciliation(value, allowed, resource, path) {
|
|
|
3422
3493
|
function validateNextAction(value, provider, resource, path) {
|
|
3423
3494
|
const action = record(value, resource, path);
|
|
3424
3495
|
if (provider === "portone") {
|
|
3496
|
+
if (action.type === "portone_sdk") {
|
|
3497
|
+
const hasCancelable = "cancelable" in action;
|
|
3498
|
+
const hasRetryPolicy = "retryPolicy" in action;
|
|
3499
|
+
if (hasCancelable !== hasRetryPolicy) {
|
|
3500
|
+
fail(
|
|
3501
|
+
resource,
|
|
3502
|
+
path,
|
|
3503
|
+
"exact released action or exact negotiated capability action"
|
|
3504
|
+
);
|
|
3505
|
+
}
|
|
3506
|
+
exact(
|
|
3507
|
+
action,
|
|
3508
|
+
[
|
|
3509
|
+
"type",
|
|
3510
|
+
"version",
|
|
3511
|
+
...hasCancelable ? ["cancelable", "retryPolicy"] : [],
|
|
3512
|
+
"storeId",
|
|
3513
|
+
"channelKey",
|
|
3514
|
+
"paymentId",
|
|
3515
|
+
"orderName",
|
|
3516
|
+
"totalAmount",
|
|
3517
|
+
"currency",
|
|
3518
|
+
"payMethod",
|
|
3519
|
+
"redirectUrl"
|
|
3520
|
+
],
|
|
3521
|
+
[],
|
|
3522
|
+
resource,
|
|
3523
|
+
path
|
|
3524
|
+
);
|
|
3525
|
+
if (action.version !== "v2") fail(resource, `${path}.version`, "v2");
|
|
3526
|
+
if (hasCancelable && action.cancelable !== false)
|
|
3527
|
+
fail(resource, `${path}.cancelable`, "false");
|
|
3528
|
+
if (hasRetryPolicy && action.retryPolicy !== "same_action_only") {
|
|
3529
|
+
fail(resource, `${path}.retryPolicy`, "same_action_only");
|
|
3530
|
+
}
|
|
3531
|
+
for (const key of ["storeId", "channelKey"]) {
|
|
3532
|
+
boundedString(action[key], 255, resource, `${path}.${key}`);
|
|
3533
|
+
}
|
|
3534
|
+
const paymentId = boundedString(
|
|
3535
|
+
action.paymentId,
|
|
3536
|
+
40,
|
|
3537
|
+
resource,
|
|
3538
|
+
`${path}.paymentId`
|
|
3539
|
+
);
|
|
3540
|
+
if (!/^[A-Za-z0-9]{6,40}$/.test(paymentId)) {
|
|
3541
|
+
fail(
|
|
3542
|
+
resource,
|
|
3543
|
+
`${path}.paymentId`,
|
|
3544
|
+
"6-40 ASCII alphanumeric characters"
|
|
3545
|
+
);
|
|
3546
|
+
}
|
|
3547
|
+
boundedString(
|
|
3548
|
+
action.orderName,
|
|
3549
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
3550
|
+
resource,
|
|
3551
|
+
`${path}.orderName`
|
|
3552
|
+
);
|
|
3553
|
+
positiveInteger(action.totalAmount, resource, `${path}.totalAmount`);
|
|
3554
|
+
if (action.currency !== "CURRENCY_KRW") {
|
|
3555
|
+
fail(resource, `${path}.currency`, "CURRENCY_KRW");
|
|
3556
|
+
}
|
|
3557
|
+
if (action.payMethod !== "CARD")
|
|
3558
|
+
fail(resource, `${path}.payMethod`, "CARD");
|
|
3559
|
+
const redirectUrl = boundedString(
|
|
3560
|
+
action.redirectUrl,
|
|
3561
|
+
2048,
|
|
3562
|
+
resource,
|
|
3563
|
+
`${path}.redirectUrl`
|
|
3564
|
+
);
|
|
3565
|
+
try {
|
|
3566
|
+
const parsed = new URL(redirectUrl);
|
|
3567
|
+
const loopback = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
|
|
3568
|
+
if (!loopback && parsed.protocol !== "https:" || parsed.username || parsed.password)
|
|
3569
|
+
throw new Error("unsafe redirect URL");
|
|
3570
|
+
} catch {
|
|
3571
|
+
fail(
|
|
3572
|
+
resource,
|
|
3573
|
+
`${path}.redirectUrl`,
|
|
3574
|
+
"HTTPS or loopback URL without embedded credentials"
|
|
3575
|
+
);
|
|
3576
|
+
}
|
|
3577
|
+
if (!hasCancelable) {
|
|
3578
|
+
action.cancelable = false;
|
|
3579
|
+
action.retryPolicy = "same_action_only";
|
|
3580
|
+
}
|
|
3581
|
+
return;
|
|
3582
|
+
}
|
|
3425
3583
|
exact(action, ["type", "checkoutUrl"], [], resource, path);
|
|
3426
3584
|
if (action.type !== "portone_checkout") {
|
|
3427
|
-
fail(resource, `${path}.type`, "portone_checkout");
|
|
3585
|
+
fail(resource, `${path}.type`, "portone_checkout | portone_sdk");
|
|
3428
3586
|
}
|
|
3429
3587
|
const checkoutUrl = boundedString(
|
|
3430
3588
|
action.checkoutUrl,
|
|
@@ -4154,8 +4312,8 @@ var CartApi = class extends CustomerScopedApi {
|
|
|
4154
4312
|
endpoint(key) {
|
|
4155
4313
|
return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
|
|
4156
4314
|
}
|
|
4157
|
-
execute(
|
|
4158
|
-
return this.requestEndpoint(
|
|
4315
|
+
execute(endpoint, body, idempotencyKey) {
|
|
4316
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4159
4317
|
...idempotencyKey && {
|
|
4160
4318
|
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4161
4319
|
}
|
|
@@ -4172,26 +4330,26 @@ var CartApi = class extends CustomerScopedApi {
|
|
|
4172
4330
|
);
|
|
4173
4331
|
}
|
|
4174
4332
|
mine(params = {}) {
|
|
4175
|
-
const
|
|
4176
|
-
return this.execute(
|
|
4333
|
+
const endpoint = this.endpoint("mine");
|
|
4334
|
+
return this.execute(endpoint, params).then(
|
|
4177
4335
|
(value) => validateCartMineResult(value)
|
|
4178
4336
|
);
|
|
4179
4337
|
}
|
|
4180
4338
|
merge(params) {
|
|
4181
4339
|
const { idempotencyKey, ...body } = params;
|
|
4182
4340
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4183
|
-
const
|
|
4184
|
-
return this.execute(
|
|
4341
|
+
const endpoint = this.endpoint("merge");
|
|
4342
|
+
return this.execute(endpoint, body, idempotencyKey).then(
|
|
4185
4343
|
(value) => validateCartMergeResult(value)
|
|
4186
4344
|
);
|
|
4187
4345
|
}
|
|
4188
4346
|
addItem(params) {
|
|
4189
4347
|
return this.mutate(this.endpoint("addItem"), params);
|
|
4190
4348
|
}
|
|
4191
|
-
mutate(
|
|
4349
|
+
mutate(endpoint, params) {
|
|
4192
4350
|
const { idempotencyKey, ...body } = params;
|
|
4193
4351
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4194
|
-
return this.execute(
|
|
4352
|
+
return this.execute(endpoint, body, idempotencyKey).then(
|
|
4195
4353
|
(value) => validateCartMutationResult(value)
|
|
4196
4354
|
);
|
|
4197
4355
|
}
|
|
@@ -4217,8 +4375,8 @@ var CheckoutApi = class extends CustomerScopedApi {
|
|
|
4217
4375
|
constructor(options) {
|
|
4218
4376
|
super("CheckoutApi", { ...options, requiresCredential: false });
|
|
4219
4377
|
}
|
|
4220
|
-
post(
|
|
4221
|
-
return this.requestEndpoint(
|
|
4378
|
+
post(endpoint, body, idempotencyKey) {
|
|
4379
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4222
4380
|
...idempotencyKey && {
|
|
4223
4381
|
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4224
4382
|
}
|
|
@@ -4285,11 +4443,15 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4285
4443
|
super("PaymentSessionApi", { ...options, requiresCredential: false });
|
|
4286
4444
|
this.serverTransport = Boolean(options.secretKey);
|
|
4287
4445
|
}
|
|
4288
|
-
post(
|
|
4289
|
-
|
|
4290
|
-
...idempotencyKey && {
|
|
4291
|
-
|
|
4446
|
+
post(endpoint, body, idempotencyKey, negotiateStandardActionCapabilities = false) {
|
|
4447
|
+
const headers = {
|
|
4448
|
+
...idempotencyKey && { "X-Idempotency-Key": idempotencyKey },
|
|
4449
|
+
...negotiateStandardActionCapabilities && {
|
|
4450
|
+
Accept: PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE
|
|
4292
4451
|
}
|
|
4452
|
+
};
|
|
4453
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4454
|
+
...Object.keys(headers).length > 0 && { headers }
|
|
4293
4455
|
});
|
|
4294
4456
|
}
|
|
4295
4457
|
async paymentSession(result, expectedProvider) {
|
|
@@ -4314,40 +4476,41 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4314
4476
|
this.post(
|
|
4315
4477
|
this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
|
|
4316
4478
|
body,
|
|
4317
|
-
idempotencyKey
|
|
4479
|
+
idempotencyKey,
|
|
4480
|
+
body.providerOptions.profile === "standard_v2"
|
|
4318
4481
|
),
|
|
4319
4482
|
"portone"
|
|
4320
4483
|
);
|
|
4321
4484
|
}
|
|
4322
4485
|
retrieve(params) {
|
|
4323
|
-
const
|
|
4486
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
4324
4487
|
return this.paymentSession(
|
|
4325
|
-
this.post(
|
|
4488
|
+
this.post(endpoint, params),
|
|
4326
4489
|
"toss"
|
|
4327
4490
|
);
|
|
4328
4491
|
}
|
|
4329
4492
|
retrievePortOne(params) {
|
|
4330
|
-
const
|
|
4493
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
4331
4494
|
return this.paymentSession(
|
|
4332
|
-
this.post(
|
|
4495
|
+
this.post(endpoint, params, void 0, true),
|
|
4333
4496
|
"portone"
|
|
4334
4497
|
);
|
|
4335
4498
|
}
|
|
4336
4499
|
cancel(params) {
|
|
4337
4500
|
const { idempotencyKey, ...body } = params;
|
|
4338
4501
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4339
|
-
const
|
|
4502
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4340
4503
|
return this.paymentSession(
|
|
4341
|
-
this.post(
|
|
4504
|
+
this.post(endpoint, body, idempotencyKey),
|
|
4342
4505
|
"toss"
|
|
4343
4506
|
);
|
|
4344
4507
|
}
|
|
4345
4508
|
cancelPortOne(params) {
|
|
4346
4509
|
const { idempotencyKey, ...body } = params;
|
|
4347
4510
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4348
|
-
const
|
|
4511
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4349
4512
|
return this.paymentSession(
|
|
4350
|
-
this.post(
|
|
4513
|
+
this.post(endpoint, body, idempotencyKey),
|
|
4351
4514
|
"portone"
|
|
4352
4515
|
);
|
|
4353
4516
|
}
|
|
@@ -4426,9 +4589,9 @@ function resolveVariantImageItems(variant, poolById) {
|
|
|
4426
4589
|
if (pooled) resolved.push(pooled);
|
|
4427
4590
|
continue;
|
|
4428
4591
|
}
|
|
4429
|
-
const
|
|
4430
|
-
if (
|
|
4431
|
-
const pooled = poolById.get(
|
|
4592
|
+
const mediaId = getMediaId(entry);
|
|
4593
|
+
if (mediaId) {
|
|
4594
|
+
const pooled = poolById.get(mediaId);
|
|
4432
4595
|
if (pooled) {
|
|
4433
4596
|
resolved.push(pooled);
|
|
4434
4597
|
}
|
|
@@ -4619,11 +4782,11 @@ function getFirstMediaId(values) {
|
|
|
4619
4782
|
}
|
|
4620
4783
|
return null;
|
|
4621
4784
|
}
|
|
4622
|
-
function inProductMediaPool(product,
|
|
4623
|
-
if (
|
|
4785
|
+
function inProductMediaPool(product, mediaId) {
|
|
4786
|
+
if (mediaId == null) return null;
|
|
4624
4787
|
const images = Array.isArray(product?.images) ? product.images : [];
|
|
4625
4788
|
for (const image of images) {
|
|
4626
|
-
if (extractEntityId(image) ===
|
|
4789
|
+
if (extractEntityId(image) === mediaId) return mediaId;
|
|
4627
4790
|
}
|
|
4628
4791
|
return null;
|
|
4629
4792
|
}
|
|
@@ -6099,21 +6262,11 @@ var PRODUCT_DETAIL_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
|
|
|
6099
6262
|
"not_published",
|
|
6100
6263
|
"feature_disabled"
|
|
6101
6264
|
]);
|
|
6102
|
-
function isRecord(value) {
|
|
6103
|
-
return typeof value === "object" && value !== null;
|
|
6104
|
-
}
|
|
6105
|
-
function readProductDetailUnavailableReason(value) {
|
|
6106
|
-
if (!isRecord(value)) return void 0;
|
|
6107
|
-
const directReason = value.reason ?? value.code;
|
|
6108
|
-
if (typeof directReason === "string" && PRODUCT_DETAIL_UNAVAILABLE_REASONS.has(directReason)) {
|
|
6109
|
-
return directReason;
|
|
6110
|
-
}
|
|
6111
|
-
return readProductDetailUnavailableReason(value.body);
|
|
6112
|
-
}
|
|
6113
6265
|
function productDetailResultFromError(error) {
|
|
6114
6266
|
if (!(error instanceof SDKError) || error.status !== 404) return void 0;
|
|
6115
|
-
const reason =
|
|
6116
|
-
if (!reason
|
|
6267
|
+
const reason = getSDKErrorReason(error);
|
|
6268
|
+
if (!reason || !PRODUCT_DETAIL_UNAVAILABLE_REASONS.has(reason))
|
|
6269
|
+
return void 0;
|
|
6117
6270
|
return { found: false, reason };
|
|
6118
6271
|
}
|
|
6119
6272
|
var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
|
|
@@ -6214,8 +6367,8 @@ function isProductUpsertFieldValidationErrorBody(value) {
|
|
|
6214
6367
|
|
|
6215
6368
|
// src/core/commerce/commerce-client.ts
|
|
6216
6369
|
var BrowserCommerceApi = class extends CustomerScopedApi {
|
|
6217
|
-
requestEndpoint(
|
|
6218
|
-
return super.requestEndpoint(
|
|
6370
|
+
requestEndpoint(endpoint, body, options) {
|
|
6371
|
+
return super.requestEndpoint(endpoint, body, options);
|
|
6219
6372
|
}
|
|
6220
6373
|
};
|
|
6221
6374
|
var CommerceClient = class {
|
|
@@ -6415,11 +6568,11 @@ var EventsClient = class {
|
|
|
6415
6568
|
{ useCustomerAuth: false }
|
|
6416
6569
|
);
|
|
6417
6570
|
}
|
|
6418
|
-
async execute(
|
|
6571
|
+
async execute(endpoint, method, body, options = {}) {
|
|
6419
6572
|
const useCustomerAuth = options.useCustomerAuth === true;
|
|
6420
6573
|
const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
|
|
6421
6574
|
try {
|
|
6422
|
-
const response = await httpFetch(
|
|
6575
|
+
const response = await httpFetch(endpoint, {
|
|
6423
6576
|
method,
|
|
6424
6577
|
apiUrl: this.apiUrl,
|
|
6425
6578
|
publishableKey: this.publishableKey,
|
|
@@ -6428,7 +6581,7 @@ var EventsClient = class {
|
|
|
6428
6581
|
...body !== void 0 && { body: JSON.stringify(body) }
|
|
6429
6582
|
});
|
|
6430
6583
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
6431
|
-
return parseApiResponse(response,
|
|
6584
|
+
return parseApiResponse(response, endpoint);
|
|
6432
6585
|
} catch (err) {
|
|
6433
6586
|
const id = err instanceof SDKError ? err.requestId ?? null : null;
|
|
6434
6587
|
this.onRequestId?.(id);
|
|
@@ -6686,13 +6839,106 @@ function mergeProductDetailWithStock(catalog, snapshot) {
|
|
|
6686
6839
|
};
|
|
6687
6840
|
}
|
|
6688
6841
|
|
|
6842
|
+
// src/core/webhook/validation.ts
|
|
6843
|
+
function isValidWebhookEventData(data) {
|
|
6844
|
+
if (typeof data !== "object" || data === null) return false;
|
|
6845
|
+
const event = data;
|
|
6846
|
+
return typeof event.collection === "string" && typeof event.operation === "string" && event.operation.length > 0 && typeof event.data === "object" && event.data !== null;
|
|
6847
|
+
}
|
|
6848
|
+
|
|
6849
|
+
// src/core/webhook/receiver.ts
|
|
6850
|
+
async function verifySignature(rawBody, secret, signature, timestamp2, deliveryId) {
|
|
6851
|
+
const encoder = new TextEncoder();
|
|
6852
|
+
const signedPrefix = encoder.encode(`${timestamp2}.${deliveryId}.`);
|
|
6853
|
+
const signedPayload = new Uint8Array(signedPrefix.length + rawBody.length);
|
|
6854
|
+
signedPayload.set(signedPrefix);
|
|
6855
|
+
signedPayload.set(rawBody, signedPrefix.length);
|
|
6856
|
+
const key = await crypto.subtle.importKey(
|
|
6857
|
+
"raw",
|
|
6858
|
+
encoder.encode(secret),
|
|
6859
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
6860
|
+
false,
|
|
6861
|
+
["verify"]
|
|
6862
|
+
);
|
|
6863
|
+
if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
|
|
6864
|
+
return false;
|
|
6865
|
+
}
|
|
6866
|
+
const sigBytes = new Uint8Array(
|
|
6867
|
+
(signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
|
|
6868
|
+
);
|
|
6869
|
+
return crypto.subtle.verify("HMAC", key, sigBytes, signedPayload);
|
|
6870
|
+
}
|
|
6871
|
+
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6872
|
+
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6873
|
+
const timestampMs = Number(timestamp2);
|
|
6874
|
+
if (!Number.isFinite(timestampMs)) return false;
|
|
6875
|
+
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
6876
|
+
return skewMs <= toleranceSeconds * 1e3;
|
|
6877
|
+
}
|
|
6878
|
+
var MAX_TOLERANCE_SECONDS = 86400;
|
|
6879
|
+
function toleranceIsValid(toleranceSeconds) {
|
|
6880
|
+
return typeof toleranceSeconds === "number" && Number.isFinite(toleranceSeconds) && toleranceSeconds >= 0 && toleranceSeconds <= MAX_TOLERANCE_SECONDS;
|
|
6881
|
+
}
|
|
6882
|
+
async function processWebhookRequest(request, handler, verify) {
|
|
6883
|
+
try {
|
|
6884
|
+
const rawBody = new Uint8Array(await request.arrayBuffer());
|
|
6885
|
+
const verificationFailure = await verify?.(rawBody);
|
|
6886
|
+
if (verificationFailure) return verificationFailure;
|
|
6887
|
+
const body = JSON.parse(new TextDecoder().decode(rawBody));
|
|
6888
|
+
if (!isValidWebhookEventData(body)) {
|
|
6889
|
+
return new Response(
|
|
6890
|
+
JSON.stringify({ error: "Invalid webhook event format" }),
|
|
6891
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
6892
|
+
);
|
|
6893
|
+
}
|
|
6894
|
+
await handler(body);
|
|
6895
|
+
return new Response(
|
|
6896
|
+
JSON.stringify({ success: true, message: "Webhook processed" }),
|
|
6897
|
+
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
6898
|
+
);
|
|
6899
|
+
} catch (error) {
|
|
6900
|
+
console.error("Webhook processing error:", error);
|
|
6901
|
+
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
6902
|
+
status: 500,
|
|
6903
|
+
headers: { "Content-Type": "application/json" }
|
|
6904
|
+
});
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
async function handleSignedWebhook(request, handler, options) {
|
|
6908
|
+
const secret = options?.secret;
|
|
6909
|
+
const configuredTolerance = options?.toleranceSeconds;
|
|
6910
|
+
const toleranceSeconds = configuredTolerance ?? 300;
|
|
6911
|
+
if (typeof secret !== "string" || secret.trim().length === 0) {
|
|
6912
|
+
return new Response(
|
|
6913
|
+
JSON.stringify({ error: "Webhook signing secret is not configured" }),
|
|
6914
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
6915
|
+
);
|
|
6916
|
+
}
|
|
6917
|
+
if (!toleranceIsValid(toleranceSeconds)) {
|
|
6918
|
+
return new Response(
|
|
6919
|
+
JSON.stringify({ error: "Webhook signature tolerance is not valid" }),
|
|
6920
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
6921
|
+
);
|
|
6922
|
+
}
|
|
6923
|
+
return processWebhookRequest(request, handler, async (rawBody) => {
|
|
6924
|
+
const signature = request.headers.get("x-webhook-signature") || "";
|
|
6925
|
+
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
6926
|
+
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
6927
|
+
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(rawBody, secret, signature, timestamp2, deliveryId);
|
|
6928
|
+
if (!valid) {
|
|
6929
|
+
return new Response(
|
|
6930
|
+
JSON.stringify({ error: "Invalid webhook signature" }),
|
|
6931
|
+
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
6932
|
+
);
|
|
6933
|
+
}
|
|
6934
|
+
});
|
|
6935
|
+
}
|
|
6936
|
+
|
|
6689
6937
|
// src/core/webhook/index.ts
|
|
6690
6938
|
var ORDER_CHANGED_EVENT_TYPE = "collection.orderChanged";
|
|
6691
6939
|
var COMMERCE_NOTIFICATION_EVENT_TYPE = "commerce.notification";
|
|
6692
6940
|
function isValidWebhookEvent(data) {
|
|
6693
|
-
|
|
6694
|
-
const obj = data;
|
|
6695
|
-
return typeof obj.collection === "string" && typeof obj.operation === "string" && obj.operation.length > 0 && typeof obj.data === "object" && obj.data !== null;
|
|
6941
|
+
return isValidWebhookEventData(data);
|
|
6696
6942
|
}
|
|
6697
6943
|
var COMMERCE_NOTIFICATION_OPERATION = "notification";
|
|
6698
6944
|
var COMMERCE_NOTIFICATION_EVENTS = [
|
|
@@ -6704,13 +6950,15 @@ var COMMERCE_NOTIFICATION_EVENTS = [
|
|
|
6704
6950
|
"returnApproved",
|
|
6705
6951
|
"returnRejected",
|
|
6706
6952
|
"returnCanceled",
|
|
6707
|
-
"returnCompleted"
|
|
6953
|
+
"returnCompleted",
|
|
6954
|
+
"paymentReconciliationRequired",
|
|
6955
|
+
"paymentRefundRequiresAttention"
|
|
6708
6956
|
];
|
|
6709
6957
|
function isStringOrNumber(value) {
|
|
6710
6958
|
return typeof value === "string" || typeof value === "number";
|
|
6711
6959
|
}
|
|
6712
6960
|
function isWebhookOrderScope(value) {
|
|
6713
|
-
if (!
|
|
6961
|
+
if (!isRecord(value)) return false;
|
|
6714
6962
|
if (value.kind === "collection") {
|
|
6715
6963
|
return typeof value.collection === "string";
|
|
6716
6964
|
}
|
|
@@ -6720,35 +6968,42 @@ function isWebhookOrderScope(value) {
|
|
|
6720
6968
|
return false;
|
|
6721
6969
|
}
|
|
6722
6970
|
function isWebhookOrderMoved(value) {
|
|
6723
|
-
if (!
|
|
6971
|
+
if (!isRecord(value)) return false;
|
|
6724
6972
|
return typeof value.collection === "string" && isStringOrNumber(value.id) && (value.relatedCollection === void 0 || typeof value.relatedCollection === "string") && (value.relatedId === void 0 || isStringOrNumber(value.relatedId));
|
|
6725
6973
|
}
|
|
6726
6974
|
function hasOptionalOrderValue(value, key) {
|
|
6727
6975
|
return value[key] === void 0 || value[key] === null || typeof value[key] === "string";
|
|
6728
6976
|
}
|
|
6729
6977
|
function isWebhookOrderChange(value) {
|
|
6730
|
-
if (!
|
|
6978
|
+
if (!isRecord(value)) return false;
|
|
6731
6979
|
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);
|
|
6732
6980
|
}
|
|
6733
6981
|
function isCommerceNotificationEventName(value) {
|
|
6734
6982
|
return typeof value === "string" && COMMERCE_NOTIFICATION_EVENTS.includes(value);
|
|
6735
6983
|
}
|
|
6736
6984
|
function isCommerceNotificationSourceCollection(value) {
|
|
6737
|
-
return value === "orders" || value === "fulfillments" || value === "returns";
|
|
6985
|
+
return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts";
|
|
6738
6986
|
}
|
|
6739
6987
|
function isCommerceNotificationData(value) {
|
|
6740
|
-
if (!
|
|
6741
|
-
if (value.source !== void 0 && (!
|
|
6988
|
+
if (!isRecord(value)) return false;
|
|
6989
|
+
if (value.source !== void 0 && (!isRecord(value.source) || !isCommerceNotificationSourceCollection(value.source.collection) || !isStringOrNumber(value.source.id))) {
|
|
6742
6990
|
return false;
|
|
6743
6991
|
}
|
|
6744
|
-
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");
|
|
6992
|
+
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");
|
|
6745
6993
|
}
|
|
6746
6994
|
function isCommerceNotification(value) {
|
|
6747
|
-
if (!
|
|
6748
|
-
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");
|
|
6995
|
+
if (!isRecord(value)) return false;
|
|
6996
|
+
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");
|
|
6997
|
+
}
|
|
6998
|
+
function isPaymentIncidentNotificationData(value, event) {
|
|
6999
|
+
const reconciliation = event === "paymentReconciliationRequired";
|
|
7000
|
+
const expectedCollection = reconciliation ? "payment-sessions" : "payment-refund-attempts";
|
|
7001
|
+
const expectedStatus = reconciliation ? "reconciliation_required" : "requires_attention";
|
|
7002
|
+
const expectedReason = reconciliation ? "orderless_capture" : "local_commit_ambiguous";
|
|
7003
|
+
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);
|
|
6749
7004
|
}
|
|
6750
7005
|
function isWebhookCommerceNotificationChange(value) {
|
|
6751
|
-
if (!
|
|
7006
|
+
if (!isRecord(value)) return false;
|
|
6752
7007
|
return value.type === "notification" && value.source === "commerce-notifications" && isCommerceNotificationEventName(value.event) && isCommerceNotificationSourceCollection(value.sourceCollection) && isStringOrNumber(value.sourceId);
|
|
6753
7008
|
}
|
|
6754
7009
|
function matchesOptionalId(actual, expected) {
|
|
@@ -6786,6 +7041,15 @@ function isCommerceNotificationWebhookEvent(event) {
|
|
|
6786
7041
|
if (!matchesOptionalId(change.sourceId, sourceId)) return false;
|
|
6787
7042
|
}
|
|
6788
7043
|
const changeSourceId = isWebhookCommerceNotificationChange(change) ? change.sourceId : void 0;
|
|
7044
|
+
if (notification.event === "paymentReconciliationRequired" || notification.event === "paymentRefundRequiresAttention") {
|
|
7045
|
+
if (!isPaymentIncidentNotificationData(data, notification.event)) {
|
|
7046
|
+
return false;
|
|
7047
|
+
}
|
|
7048
|
+
const incidentData = data;
|
|
7049
|
+
const expectedCollection = notification.event === "paymentReconciliationRequired" ? "payment-sessions" : "payment-refund-attempts";
|
|
7050
|
+
const notificationSourceId = notification.event === "paymentReconciliationRequired" ? notification.paymentSessionId : notification.refundAttemptId;
|
|
7051
|
+
return sourceCollection === expectedCollection && typeof notification.paymentSessionId === "string" && notification.paymentSessionId === incidentData.paymentSessionId && typeof notificationSourceId === "string" && notificationSourceId === incidentData.source.id && matchesOptionalId(changeSourceId, incidentData.source.id);
|
|
7052
|
+
}
|
|
6789
7053
|
if (notification.event === "orderPaid" || notification.event === "orderCanceled" || notification.event === "orderDelivered") {
|
|
6790
7054
|
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);
|
|
6791
7055
|
}
|
|
@@ -6830,7 +7094,7 @@ function isWebhookOperation(event, operation2) {
|
|
|
6830
7094
|
return isValidWebhookEvent(event) && event.operation === operation2;
|
|
6831
7095
|
}
|
|
6832
7096
|
var CUSTOMER_PASSWORD_RESET_OPERATION = "password-reset";
|
|
6833
|
-
function
|
|
7097
|
+
function isRecord(value) {
|
|
6834
7098
|
return typeof value === "object" && value !== null;
|
|
6835
7099
|
}
|
|
6836
7100
|
function hasString(value, key) {
|
|
@@ -6840,7 +7104,7 @@ function hasStringOrNumber(value, key) {
|
|
|
6840
7104
|
return typeof value[key] === "string" || typeof value[key] === "number";
|
|
6841
7105
|
}
|
|
6842
7106
|
function isCustomerPasswordResetWebhookEvent(event) {
|
|
6843
|
-
if (event.collection !== "customers" || event.operation !== CUSTOMER_PASSWORD_RESET_OPERATION || !
|
|
7107
|
+
if (event.collection !== "customers" || event.operation !== CUSTOMER_PASSWORD_RESET_OPERATION || !isRecord(event.data)) {
|
|
6844
7108
|
return false;
|
|
6845
7109
|
}
|
|
6846
7110
|
return hasStringOrNumber(event.data, "customerId") && hasString(event.data, "email") && hasString(event.data, "name") && hasString(event.data, "resetPasswordToken") && hasString(event.data, "resetPasswordExpiresAt");
|
|
@@ -6854,80 +7118,8 @@ function createCustomerAuthWebhookHandler(handlers) {
|
|
|
6854
7118
|
await handlers.unhandled?.(event);
|
|
6855
7119
|
};
|
|
6856
7120
|
}
|
|
6857
|
-
async function verifySignature(payload, secret, signature, timestamp2, deliveryId) {
|
|
6858
|
-
const encoder = new TextEncoder();
|
|
6859
|
-
const key = await crypto.subtle.importKey(
|
|
6860
|
-
"raw",
|
|
6861
|
-
encoder.encode(secret),
|
|
6862
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
6863
|
-
false,
|
|
6864
|
-
["verify"]
|
|
6865
|
-
);
|
|
6866
|
-
if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
|
|
6867
|
-
return false;
|
|
6868
|
-
}
|
|
6869
|
-
const sigBytes = new Uint8Array(
|
|
6870
|
-
(signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
|
|
6871
|
-
);
|
|
6872
|
-
return crypto.subtle.verify(
|
|
6873
|
-
"HMAC",
|
|
6874
|
-
key,
|
|
6875
|
-
sigBytes,
|
|
6876
|
-
encoder.encode(`${timestamp2}.${deliveryId}.${payload}`)
|
|
6877
|
-
);
|
|
6878
|
-
}
|
|
6879
|
-
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6880
|
-
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6881
|
-
const timestampMs = Number(timestamp2);
|
|
6882
|
-
if (!Number.isFinite(timestampMs)) return false;
|
|
6883
|
-
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
6884
|
-
return skewMs <= toleranceSeconds * 1e3;
|
|
6885
|
-
}
|
|
6886
7121
|
async function handleWebhook(request, handler, options) {
|
|
6887
|
-
|
|
6888
|
-
const rawBody = await request.text();
|
|
6889
|
-
if (options?.secret) {
|
|
6890
|
-
const signature = request.headers.get("x-webhook-signature") || "";
|
|
6891
|
-
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
6892
|
-
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
6893
|
-
const toleranceSeconds = options.toleranceSeconds ?? 300;
|
|
6894
|
-
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(
|
|
6895
|
-
rawBody,
|
|
6896
|
-
options.secret,
|
|
6897
|
-
signature,
|
|
6898
|
-
timestamp2,
|
|
6899
|
-
deliveryId
|
|
6900
|
-
);
|
|
6901
|
-
if (!valid) {
|
|
6902
|
-
return new Response(
|
|
6903
|
-
JSON.stringify({ error: "Invalid webhook signature" }),
|
|
6904
|
-
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
6905
|
-
);
|
|
6906
|
-
}
|
|
6907
|
-
} else {
|
|
6908
|
-
console.warn(
|
|
6909
|
-
"[@01.software/sdk] Webhook signature verification is disabled. Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification."
|
|
6910
|
-
);
|
|
6911
|
-
}
|
|
6912
|
-
const body = JSON.parse(rawBody);
|
|
6913
|
-
if (!isValidWebhookEvent(body)) {
|
|
6914
|
-
return new Response(
|
|
6915
|
-
JSON.stringify({ error: "Invalid webhook event format" }),
|
|
6916
|
-
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
6917
|
-
);
|
|
6918
|
-
}
|
|
6919
|
-
await handler(body);
|
|
6920
|
-
return new Response(
|
|
6921
|
-
JSON.stringify({ success: true, message: "Webhook processed" }),
|
|
6922
|
-
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
6923
|
-
);
|
|
6924
|
-
} catch (error) {
|
|
6925
|
-
console.error("Webhook processing error:", error);
|
|
6926
|
-
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
6927
|
-
status: 500,
|
|
6928
|
-
headers: { "Content-Type": "application/json" }
|
|
6929
|
-
});
|
|
6930
|
-
}
|
|
7122
|
+
return handleSignedWebhook(request, handler, options);
|
|
6931
7123
|
}
|
|
6932
7124
|
function createTypedWebhookHandler(collection, handler) {
|
|
6933
7125
|
return async (event) => {
|
|
@@ -6967,6 +7159,7 @@ var INTERNAL_COLLECTIONS = [
|
|
|
6967
7159
|
"payment-event-inbox",
|
|
6968
7160
|
"payment-refund-attempts",
|
|
6969
7161
|
"portone-payment-interactions",
|
|
7162
|
+
"commerce-payment-webhook-routes",
|
|
6970
7163
|
"commerce-notification-intents",
|
|
6971
7164
|
"commerce-idempotency-records",
|
|
6972
7165
|
"product-collection-items",
|
|
@@ -7007,7 +7200,6 @@ var COLLECTIONS = [
|
|
|
7007
7200
|
"brands",
|
|
7008
7201
|
"customer-profiles",
|
|
7009
7202
|
"customer-profile-stats",
|
|
7010
|
-
"discounts",
|
|
7011
7203
|
"shipping-policies",
|
|
7012
7204
|
"shipping-zones",
|
|
7013
7205
|
"documents",
|
|
@@ -7083,6 +7275,9 @@ var SERVER_ONLY_COLLECTIONS = [
|
|
|
7083
7275
|
"cart-items",
|
|
7084
7276
|
"checkouts",
|
|
7085
7277
|
"checkout-items",
|
|
7278
|
+
// Raw discount definitions require a server credential. Browser discount
|
|
7279
|
+
// validation is exposed through the shaped POST /api/discounts/validate path.
|
|
7280
|
+
"discounts",
|
|
7086
7281
|
"draft-orders",
|
|
7087
7282
|
"draft-order-items",
|
|
7088
7283
|
"posts",
|
|
@@ -7248,160 +7443,6 @@ var RealtimeConnection = class {
|
|
|
7248
7443
|
}
|
|
7249
7444
|
};
|
|
7250
7445
|
|
|
7251
|
-
// src/utils/product-media.ts
|
|
7252
|
-
function mediaPointerOptionValues(values) {
|
|
7253
|
-
return (values ?? []).filter((value) => value != null && value !== "").map((value) => ({
|
|
7254
|
-
swatch: {
|
|
7255
|
-
type: "media",
|
|
7256
|
-
mediaItemId: value
|
|
7257
|
-
}
|
|
7258
|
-
}));
|
|
7259
|
-
}
|
|
7260
|
-
function resolveProductMedia(input) {
|
|
7261
|
-
const resolved = resolveProductSelectionMedia({
|
|
7262
|
-
...input,
|
|
7263
|
-
selectedVariant: input.selectedVariant ?? (input.variantFeaturedMediaItemId ? { images: [input.variantFeaturedMediaItemId] } : null),
|
|
7264
|
-
selectedOptionValues: input.selectedOptionValues ?? mediaPointerOptionValues(input.selectedOptionValueMediaItemIds)
|
|
7265
|
-
});
|
|
7266
|
-
if (resolved.source !== "none") {
|
|
7267
|
-
return {
|
|
7268
|
-
...resolved,
|
|
7269
|
-
source: resolved.source === "variant_media_selected" ? "variant_featured" : resolved.source
|
|
7270
|
-
};
|
|
7271
|
-
}
|
|
7272
|
-
const display = resolveProductDisplayMedia({
|
|
7273
|
-
productMediaPool: input.productMediaPool
|
|
7274
|
-
});
|
|
7275
|
-
return {
|
|
7276
|
-
primaryImage: display.primaryImage,
|
|
7277
|
-
images: display.images,
|
|
7278
|
-
source: display.source
|
|
7279
|
-
};
|
|
7280
|
-
}
|
|
7281
|
-
|
|
7282
|
-
// src/utils/product-gallery.ts
|
|
7283
|
-
function mediaId(value) {
|
|
7284
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
7285
|
-
return String(value);
|
|
7286
|
-
}
|
|
7287
|
-
if (typeof value === "object" && value !== null && "id" in value) {
|
|
7288
|
-
const id = value.id;
|
|
7289
|
-
if (typeof id === "string" || typeof id === "number") return String(id);
|
|
7290
|
-
}
|
|
7291
|
-
return null;
|
|
7292
|
-
}
|
|
7293
|
-
function relationshipIds(values) {
|
|
7294
|
-
if (!Array.isArray(values)) return [];
|
|
7295
|
-
return values.map((value) => mediaId(value)).filter((value) => Boolean(value));
|
|
7296
|
-
}
|
|
7297
|
-
function buildPoolById2(pool) {
|
|
7298
|
-
const poolById = /* @__PURE__ */ new Map();
|
|
7299
|
-
for (const item of pool) {
|
|
7300
|
-
const id = mediaId(item);
|
|
7301
|
-
if (id) poolById.set(id, item);
|
|
7302
|
-
}
|
|
7303
|
-
return poolById;
|
|
7304
|
-
}
|
|
7305
|
-
function mediaSetItemsInPool(mediaSet, poolById) {
|
|
7306
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7307
|
-
const items = [];
|
|
7308
|
-
const primaryId = mediaId(mediaSet.primaryMediaItemId);
|
|
7309
|
-
if (primaryId) {
|
|
7310
|
-
const primary = poolById.get(primaryId);
|
|
7311
|
-
if (primary) {
|
|
7312
|
-
seen.add(primaryId);
|
|
7313
|
-
items.push(primary);
|
|
7314
|
-
}
|
|
7315
|
-
}
|
|
7316
|
-
for (const itemId of relationshipIds(mediaSet.items)) {
|
|
7317
|
-
if (seen.has(itemId)) continue;
|
|
7318
|
-
const item = poolById.get(itemId);
|
|
7319
|
-
if (!item) continue;
|
|
7320
|
-
seen.add(itemId);
|
|
7321
|
-
items.push(item);
|
|
7322
|
-
}
|
|
7323
|
-
return items;
|
|
7324
|
-
}
|
|
7325
|
-
function resolveLegacyMediaSet(input) {
|
|
7326
|
-
if (!Array.isArray(input.mediaSets)) return null;
|
|
7327
|
-
const pool = input.productMediaPool ?? input.pool ?? [];
|
|
7328
|
-
const poolById = buildPoolById2(pool);
|
|
7329
|
-
const selectedVariantId = mediaId(input.selectedVariantId);
|
|
7330
|
-
if (selectedVariantId) {
|
|
7331
|
-
const exactSet = input.mediaSets.find(
|
|
7332
|
-
(set) => set.matchType === "exact-variant" && relationshipIds(set.variantIds).includes(selectedVariantId)
|
|
7333
|
-
);
|
|
7334
|
-
if (exactSet) {
|
|
7335
|
-
const images = mediaSetItemsInPool(exactSet, poolById);
|
|
7336
|
-
if (images.length > 0) {
|
|
7337
|
-
return {
|
|
7338
|
-
primaryImage: images[0] ?? null,
|
|
7339
|
-
images,
|
|
7340
|
-
source: "exact_variant_set"
|
|
7341
|
-
};
|
|
7342
|
-
}
|
|
7343
|
-
}
|
|
7344
|
-
}
|
|
7345
|
-
const selectedOptionValueIds = new Set(
|
|
7346
|
-
relationshipIds(input.selectedOptionValueIds)
|
|
7347
|
-
);
|
|
7348
|
-
const optionSetMatches = input.mediaSets.filter((set) => set.matchType === "option-values").map((set) => {
|
|
7349
|
-
const optionValueIds = relationshipIds(set.optionValueIds);
|
|
7350
|
-
if (optionValueIds.length === 0) return null;
|
|
7351
|
-
if (!optionValueIds.every((id) => selectedOptionValueIds.has(id))) {
|
|
7352
|
-
return null;
|
|
7353
|
-
}
|
|
7354
|
-
const images = mediaSetItemsInPool(set, poolById);
|
|
7355
|
-
if (images.length === 0) return null;
|
|
7356
|
-
return { optionValueCount: optionValueIds.length, images };
|
|
7357
|
-
}).filter(
|
|
7358
|
-
(match) => Boolean(match)
|
|
7359
|
-
).sort((a, b) => b.optionValueCount - a.optionValueCount);
|
|
7360
|
-
if (optionSetMatches.length > 0) {
|
|
7361
|
-
const images = optionSetMatches[0].images;
|
|
7362
|
-
return {
|
|
7363
|
-
primaryImage: images[0] ?? null,
|
|
7364
|
-
images,
|
|
7365
|
-
source: "option_value_set"
|
|
7366
|
-
};
|
|
7367
|
-
}
|
|
7368
|
-
const defaultSet = input.mediaSets.find((set) => set.matchType === "default");
|
|
7369
|
-
if (defaultSet) {
|
|
7370
|
-
const images = mediaSetItemsInPool(defaultSet, poolById);
|
|
7371
|
-
if (images.length > 0) {
|
|
7372
|
-
return {
|
|
7373
|
-
primaryImage: images[0] ?? null,
|
|
7374
|
-
images,
|
|
7375
|
-
source: "default_set"
|
|
7376
|
-
};
|
|
7377
|
-
}
|
|
7378
|
-
}
|
|
7379
|
-
return {
|
|
7380
|
-
primaryImage: null,
|
|
7381
|
-
images: [],
|
|
7382
|
-
source: "none"
|
|
7383
|
-
};
|
|
7384
|
-
}
|
|
7385
|
-
function resolveProductGallery(input) {
|
|
7386
|
-
const selectedVariantId = mediaId(input.selectedVariantId);
|
|
7387
|
-
const selectedOptionValueIds = relationshipIds(input.selectedOptionValueIds);
|
|
7388
|
-
const selection = resolveProductSelectionMedia({
|
|
7389
|
-
...input,
|
|
7390
|
-
productMediaPool: input.productMediaPool ?? input.pool ?? null,
|
|
7391
|
-
selectedVariant: input.selectedVariant ?? (selectedVariantId ? { id: selectedVariantId } : null),
|
|
7392
|
-
selectedOptionValues: input.selectedOptionValues ?? selectedOptionValueIds.map((id) => ({ id }))
|
|
7393
|
-
});
|
|
7394
|
-
if (selection.source !== "none") {
|
|
7395
|
-
return selection;
|
|
7396
|
-
}
|
|
7397
|
-
const legacyResolved = resolveLegacyMediaSet(input);
|
|
7398
|
-
if (legacyResolved && legacyResolved.source !== "none") return legacyResolved;
|
|
7399
|
-
return resolveProductDisplayMedia({
|
|
7400
|
-
productMediaPool: input.productMediaPool ?? input.pool ?? null,
|
|
7401
|
-
featuredImage: input.featuredImage
|
|
7402
|
-
});
|
|
7403
|
-
}
|
|
7404
|
-
|
|
7405
7446
|
// src/utils/image.ts
|
|
7406
7447
|
var IMAGE_SIZES = [200, 400, 800, 1200, 1600];
|
|
7407
7448
|
function imageSizeCandidates(sizes) {
|
|
@@ -7533,7 +7574,7 @@ function createAnalytics(config) {
|
|
|
7533
7574
|
}, destroy() {
|
|
7534
7575
|
} };
|
|
7535
7576
|
}
|
|
7536
|
-
const
|
|
7577
|
+
const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
|
|
7537
7578
|
const respectDnt = config.respectDnt !== false;
|
|
7538
7579
|
function isDntActive() {
|
|
7539
7580
|
if (!respectDnt) return false;
|
|
@@ -7574,10 +7615,10 @@ function createAnalytics(config) {
|
|
|
7574
7615
|
try {
|
|
7575
7616
|
if (typeof navigator.sendBeacon === "function") {
|
|
7576
7617
|
const blob = new Blob([body], { type: "text/plain" });
|
|
7577
|
-
const sent = navigator.sendBeacon(
|
|
7618
|
+
const sent = navigator.sendBeacon(endpoint, blob);
|
|
7578
7619
|
if (sent) return;
|
|
7579
7620
|
}
|
|
7580
|
-
fetch(
|
|
7621
|
+
fetch(endpoint, {
|
|
7581
7622
|
method: "POST",
|
|
7582
7623
|
keepalive: true,
|
|
7583
7624
|
headers: { "Content-Type": "application/json" },
|