@01.software/sdk 0.44.0 → 0.46.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 +366 -2
- package/MIGRATION.md +108 -10
- package/README.md +486 -98
- package/dist/{server-nXOezi4b.d.cts → catalog-mappers-sIshKNb3.d.cts} +14 -3
- package/dist/{server-nXOezi4b.d.ts → catalog-mappers-sIshKNb3.d.ts} +14 -3
- package/dist/client.cjs +2693 -345
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +10 -7
- package/dist/client.d.ts +10 -7
- package/dist/client.js +2693 -345
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-DWooaiTr.d.ts → collection-client-D6kKrYdq.d.ts} +8 -5
- package/dist/{collection-client-Dyl-CDcj.d.cts → collection-client-DolMjCoC.d.cts} +8 -5
- package/dist/{const-pGDnsy0o.d.ts → const-BAG0MH0u.d.cts} +13 -10
- package/dist/{const-1vleZ6ov.d.cts → const-CaPq2AE4.d.ts} +13 -10
- package/dist/errors.cjs +74 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +38 -1
- package/dist/errors.d.ts +38 -1
- package/dist/errors.js +74 -1
- package/dist/errors.js.map +1 -1
- package/dist/{index-DUNySyxV.d.ts → index-BNICJxBL.d.ts} +4 -4
- package/dist/{index-a6g7vqAD.d.cts → index-YGrZrxNn.d.cts} +4 -4
- package/dist/index.cjs +2754 -368
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -19
- package/dist/index.d.ts +18 -19
- package/dist/index.js +2754 -368
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-CDsuOEfM.d.cts → payload-types-CJZuXcgF.d.cts} +6671 -4001
- package/dist/{payload-types-CDsuOEfM.d.ts → payload-types-CJZuXcgF.d.ts} +6671 -4001
- package/dist/query.cjs +558 -101
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +43 -45
- package/dist/query.d.ts +43 -45
- package/dist/query.js +558 -101
- package/dist/query.js.map +1 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/realtime.js.map +1 -1
- package/dist/server.cjs +2343 -437
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +11 -10
- package/dist/server.d.ts +11 -10
- package/dist/server.js +2343 -437
- package/dist/server.js.map +1 -1
- package/dist/storefront-cache.cjs +65 -1
- package/dist/storefront-cache.cjs.map +1 -1
- package/dist/storefront-cache.js +65 -1
- package/dist/storefront-cache.js.map +1 -1
- package/dist/types-BC6rVmJa.d.ts +47 -0
- package/dist/{types-CDND3hzq.d.cts → types-C60vHIkY.d.ts} +1134 -509
- package/dist/types-D5p7-m1l.d.cts +47 -0
- package/dist/{types-Dt9FJisi.d.ts → types-xlqBeW2N.d.cts} +1134 -509
- package/dist/ui/canvas/server.cjs +244 -2
- package/dist/ui/canvas/server.cjs.map +1 -1
- package/dist/ui/canvas/server.d.cts +27 -1
- package/dist/ui/canvas/server.d.ts +27 -1
- package/dist/ui/canvas/server.js +244 -2
- package/dist/ui/canvas/server.js.map +1 -1
- package/dist/ui/canvas.cjs +419 -103
- package/dist/ui/canvas.cjs.map +1 -1
- package/dist/ui/canvas.d.cts +19 -7
- package/dist/ui/canvas.d.ts +19 -7
- package/dist/ui/canvas.js +419 -103
- package/dist/ui/canvas.js.map +1 -1
- 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 +2 -1
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +4 -4
- package/dist/webhook.d.ts +4 -4
- package/dist/webhook.js +2 -1
- package/dist/webhook.js.map +1 -1
- package/package.json +10 -9
- package/dist/types-SoXsbKhj.d.cts +0 -33
- package/dist/types-oiae_LMm.d.ts +0 -33
package/dist/index.js
CHANGED
|
@@ -28,10 +28,136 @@ var SDKError = class extends Error {
|
|
|
28
28
|
details: this.details,
|
|
29
29
|
userMessage: this.userMessage,
|
|
30
30
|
suggestion: this.suggestion,
|
|
31
|
-
...this.requestId !== void 0 && { requestId: this.requestId }
|
|
31
|
+
...this.requestId !== void 0 && { requestId: this.requestId },
|
|
32
|
+
...this.kind !== void 0 && { kind: this.kind },
|
|
33
|
+
...this.reason !== void 0 && { reason: this.reason },
|
|
34
|
+
...this.rawReason !== void 0 && { rawReason: this.rawReason },
|
|
35
|
+
...this.retryable !== void 0 && { retryable: this.retryable },
|
|
36
|
+
...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
|
|
32
37
|
};
|
|
33
38
|
}
|
|
34
39
|
};
|
|
40
|
+
var COMMERCE_ERROR_CODES = [
|
|
41
|
+
"validation_failed",
|
|
42
|
+
"unauthorized",
|
|
43
|
+
"forbidden",
|
|
44
|
+
"token_expired",
|
|
45
|
+
"origin_not_allowed",
|
|
46
|
+
"server_credentials_required",
|
|
47
|
+
"not_found",
|
|
48
|
+
"conflict",
|
|
49
|
+
"cart_revision_conflict",
|
|
50
|
+
"rate_limit_exceeded",
|
|
51
|
+
"usage_limit_exceeded",
|
|
52
|
+
"service_unavailable",
|
|
53
|
+
"idempotency_conflict",
|
|
54
|
+
"idempotency_in_progress",
|
|
55
|
+
"cart_not_active",
|
|
56
|
+
"cart_locked",
|
|
57
|
+
"cart_empty",
|
|
58
|
+
"cart_market_unavailable",
|
|
59
|
+
"cart_market_mismatch",
|
|
60
|
+
"checkout_not_open",
|
|
61
|
+
"payment_slot_held",
|
|
62
|
+
"reservation_expired",
|
|
63
|
+
"payment_session_not_cancelable",
|
|
64
|
+
"provider_identity_mismatch",
|
|
65
|
+
"provider_unavailable",
|
|
66
|
+
"lock_timeout",
|
|
67
|
+
"price_changed",
|
|
68
|
+
"pricing_fact_in_use",
|
|
69
|
+
"insufficient_stock",
|
|
70
|
+
"market_not_found",
|
|
71
|
+
"market_shipping_currency_unsupported",
|
|
72
|
+
"missing_market_rate",
|
|
73
|
+
"missing_shipping_amount",
|
|
74
|
+
"no_enabled_payment_provider",
|
|
75
|
+
"product_market_unavailable",
|
|
76
|
+
"unsupported_currency",
|
|
77
|
+
"missing_price_row",
|
|
78
|
+
"payment_provider_currency_unsupported",
|
|
79
|
+
"discount_code_not_found",
|
|
80
|
+
"discount_not_started",
|
|
81
|
+
"discount_expired",
|
|
82
|
+
"discount_usage_limit",
|
|
83
|
+
"discount_per_customer_limit",
|
|
84
|
+
"discount_customer_required",
|
|
85
|
+
"discount_first_order_only",
|
|
86
|
+
"discount_customer_not_eligible",
|
|
87
|
+
"discount_customer_excluded",
|
|
88
|
+
"discount_items_required",
|
|
89
|
+
"discount_product_not_eligible",
|
|
90
|
+
"discount_product_excluded",
|
|
91
|
+
"discount_min_order_amount",
|
|
92
|
+
"discount_currency_scope_required",
|
|
93
|
+
"discount_allocation_method_unsupported",
|
|
94
|
+
"currency_mismatch"
|
|
95
|
+
];
|
|
96
|
+
var COMMERCE_ERROR_CODE_SET = new Set(
|
|
97
|
+
COMMERCE_ERROR_CODES
|
|
98
|
+
);
|
|
99
|
+
var COMMERCE_ERROR_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
|
|
100
|
+
"error",
|
|
101
|
+
"reason",
|
|
102
|
+
"requestId",
|
|
103
|
+
"retryable",
|
|
104
|
+
"details"
|
|
105
|
+
]);
|
|
106
|
+
function isPlainRecord(value) {
|
|
107
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
108
|
+
}
|
|
109
|
+
function commerceProtocolError(issue, trustedRequestId) {
|
|
110
|
+
return createApiError(
|
|
111
|
+
"Invalid canonical commerce error response.",
|
|
112
|
+
502,
|
|
113
|
+
{ protocol: "commerce-error-envelope", issue },
|
|
114
|
+
"The server returned an incompatible commerce error response.",
|
|
115
|
+
"Verify that the Console commerce contract is deployed before using this SDK version.",
|
|
116
|
+
trustedRequestId
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
function parseCommerceErrorEnvelope(body, headerRequestId) {
|
|
120
|
+
if (!isPlainRecord(body)) {
|
|
121
|
+
throw commerceProtocolError("expected_object", headerRequestId);
|
|
122
|
+
}
|
|
123
|
+
if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {
|
|
124
|
+
throw commerceProtocolError("unexpected_field", headerRequestId);
|
|
125
|
+
}
|
|
126
|
+
if (typeof body.error !== "string" || body.error.length === 0 || typeof body.reason !== "string" || body.reason.length === 0 || typeof body.requestId !== "string" || body.requestId.length === 0 || body.retryable !== void 0 && typeof body.retryable !== "boolean" || body.details !== void 0 && !isPlainRecord(body.details)) {
|
|
127
|
+
throw commerceProtocolError("invalid_field", headerRequestId);
|
|
128
|
+
}
|
|
129
|
+
if (headerRequestId && headerRequestId !== body.requestId) {
|
|
130
|
+
throw commerceProtocolError("request_id_mismatch", headerRequestId);
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
error: body.error,
|
|
134
|
+
reason: body.reason,
|
|
135
|
+
requestId: body.requestId,
|
|
136
|
+
retryable: body.retryable === true,
|
|
137
|
+
...body.details === void 0 ? {} : { details: body.details }
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function enhanceCommerceError(error, body, headerRequestId) {
|
|
141
|
+
const envelope = parseCommerceErrorEnvelope(body, headerRequestId);
|
|
142
|
+
const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason);
|
|
143
|
+
Object.assign(error, {
|
|
144
|
+
code: envelope.reason,
|
|
145
|
+
kind: "commerce",
|
|
146
|
+
reason: known ? envelope.reason : "unknown_commerce_error",
|
|
147
|
+
...known ? {} : { rawReason: envelope.reason },
|
|
148
|
+
requestId: envelope.requestId,
|
|
149
|
+
retryable: envelope.retryable,
|
|
150
|
+
details: envelope.details
|
|
151
|
+
});
|
|
152
|
+
return error;
|
|
153
|
+
}
|
|
154
|
+
function isCommerceSDKError(error) {
|
|
155
|
+
if (!(error instanceof SDKError) || error.kind !== "commerce") return false;
|
|
156
|
+
if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return error.reason === "unknown_commerce_error" ? typeof error.rawReason === "string" : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === void 0;
|
|
160
|
+
}
|
|
35
161
|
var NetworkError = class extends SDKError {
|
|
36
162
|
constructor(message, status, details, userMessage, suggestion) {
|
|
37
163
|
super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
|
|
@@ -270,6 +396,7 @@ var NON_RETRYABLE_STATUSES = [400, 401, 403, 404, 409, 422];
|
|
|
270
396
|
var SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
|
|
271
397
|
var DEFAULT_MAX_RETRIES = 3;
|
|
272
398
|
var STOREFRONT_BROWSER_MAX_RETRIES = 1;
|
|
399
|
+
var MAX_AUTOMATIC_RETRY_AFTER_SECONDS = 5 * 60;
|
|
273
400
|
function debugLog(debug, type, message, data) {
|
|
274
401
|
if (!debug) return;
|
|
275
402
|
const shouldLog = debug === true || type === "request" && debug.logRequests || type === "response" && debug.logResponses || type === "error" && debug.logErrors;
|
|
@@ -293,6 +420,11 @@ function redactSensitiveHeaders(headers) {
|
|
|
293
420
|
redacted["x-preview-token"]
|
|
294
421
|
);
|
|
295
422
|
}
|
|
423
|
+
if (redacted["x-custom-payment-signature"]) {
|
|
424
|
+
redacted["x-custom-payment-signature"] = redactSensitiveHeader(
|
|
425
|
+
redacted["x-custom-payment-signature"]
|
|
426
|
+
);
|
|
427
|
+
}
|
|
296
428
|
return redacted;
|
|
297
429
|
}
|
|
298
430
|
function getErrorSuggestion(status) {
|
|
@@ -384,116 +516,129 @@ function attachRequestId(err, id) {
|
|
|
384
516
|
}
|
|
385
517
|
function parseRetryAfter(response) {
|
|
386
518
|
const raw = response.headers.get("Retry-After");
|
|
387
|
-
if (!raw) return
|
|
388
|
-
|
|
519
|
+
if (!raw) return { permitsAutomaticRetry: true };
|
|
520
|
+
const trimmed = raw.trim();
|
|
521
|
+
let seconds;
|
|
522
|
+
if (/^\d+$/.test(trimmed)) {
|
|
523
|
+
seconds = Number(trimmed);
|
|
524
|
+
if (!Number.isSafeInteger(seconds)) {
|
|
525
|
+
return { permitsAutomaticRetry: false };
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
const retryAt = Date.parse(trimmed);
|
|
529
|
+
if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
|
|
530
|
+
seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
seconds,
|
|
534
|
+
permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
|
|
535
|
+
};
|
|
389
536
|
}
|
|
390
|
-
function mapResponseToError(status, parsed, details, requestId, retryAfter) {
|
|
537
|
+
function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
|
|
391
538
|
const errorDetails = {
|
|
392
539
|
...details,
|
|
393
540
|
...parsed.errors && { errors: parsed.errors },
|
|
394
|
-
...parsed.body && { body: parsed.body }
|
|
541
|
+
...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
|
|
395
542
|
};
|
|
396
543
|
const suggestion = getParsedErrorSuggestion(status, parsed);
|
|
544
|
+
const finalize = (error) => {
|
|
545
|
+
const withRequestId = attachRequestId(error, requestId);
|
|
546
|
+
if (retryAfter !== void 0) {
|
|
547
|
+
Object.assign(withRequestId, { retryAfter });
|
|
548
|
+
}
|
|
549
|
+
return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
|
|
550
|
+
};
|
|
397
551
|
if (status === 400 || status === 422) {
|
|
398
|
-
return
|
|
552
|
+
return finalize(
|
|
399
553
|
createValidationError(
|
|
400
554
|
parsed.errorMessage,
|
|
401
555
|
errorDetails,
|
|
402
556
|
parsed.userMessage,
|
|
403
557
|
suggestion,
|
|
404
558
|
status
|
|
405
|
-
)
|
|
406
|
-
requestId
|
|
559
|
+
)
|
|
407
560
|
);
|
|
408
561
|
}
|
|
409
562
|
if (status === 401) {
|
|
410
|
-
return
|
|
563
|
+
return finalize(
|
|
411
564
|
createAuthError(
|
|
412
565
|
parsed.errorMessage,
|
|
413
566
|
errorDetails,
|
|
414
567
|
parsed.userMessage,
|
|
415
568
|
suggestion
|
|
416
|
-
)
|
|
417
|
-
requestId
|
|
569
|
+
)
|
|
418
570
|
);
|
|
419
571
|
}
|
|
420
572
|
if (status === 403) {
|
|
421
|
-
return
|
|
573
|
+
return finalize(
|
|
422
574
|
createPermissionError(
|
|
423
575
|
parsed.errorMessage,
|
|
424
576
|
errorDetails,
|
|
425
577
|
parsed.userMessage,
|
|
426
578
|
suggestion
|
|
427
|
-
)
|
|
428
|
-
requestId
|
|
579
|
+
)
|
|
429
580
|
);
|
|
430
581
|
}
|
|
431
582
|
if (status === 404) {
|
|
432
|
-
return
|
|
583
|
+
return finalize(
|
|
433
584
|
createNotFoundError(
|
|
434
585
|
parsed.errorMessage,
|
|
435
586
|
errorDetails,
|
|
436
587
|
parsed.userMessage,
|
|
437
588
|
suggestion
|
|
438
|
-
)
|
|
439
|
-
requestId
|
|
589
|
+
)
|
|
440
590
|
);
|
|
441
591
|
}
|
|
442
592
|
if (status === 409) {
|
|
443
|
-
return
|
|
593
|
+
return finalize(
|
|
444
594
|
createConflictError(
|
|
445
595
|
parsed.errorMessage,
|
|
446
596
|
errorDetails,
|
|
447
597
|
parsed.userMessage,
|
|
448
598
|
suggestion
|
|
449
|
-
)
|
|
450
|
-
requestId
|
|
599
|
+
)
|
|
451
600
|
);
|
|
452
601
|
}
|
|
453
602
|
if (status === 410) {
|
|
454
|
-
return
|
|
603
|
+
return finalize(
|
|
455
604
|
createGoneError(
|
|
456
605
|
parsed.errorMessage,
|
|
457
606
|
errorDetails,
|
|
458
607
|
parsed.userMessage,
|
|
459
608
|
suggestion
|
|
460
|
-
)
|
|
461
|
-
requestId
|
|
609
|
+
)
|
|
462
610
|
);
|
|
463
611
|
}
|
|
464
612
|
if (status === 429) {
|
|
465
|
-
return
|
|
613
|
+
return finalize(
|
|
466
614
|
createRateLimitError(
|
|
467
615
|
parsed.errorMessage,
|
|
468
616
|
retryAfter,
|
|
469
617
|
errorDetails,
|
|
470
618
|
parsed.userMessage,
|
|
471
619
|
suggestion
|
|
472
|
-
)
|
|
473
|
-
requestId
|
|
620
|
+
)
|
|
474
621
|
);
|
|
475
622
|
}
|
|
476
623
|
if (status === 503) {
|
|
477
|
-
return
|
|
624
|
+
return finalize(
|
|
478
625
|
createServiceUnavailableError(
|
|
479
626
|
parsed.errorMessage,
|
|
480
627
|
retryAfter,
|
|
481
628
|
errorDetails,
|
|
482
629
|
parsed.userMessage,
|
|
483
630
|
suggestion
|
|
484
|
-
)
|
|
485
|
-
requestId
|
|
631
|
+
)
|
|
486
632
|
);
|
|
487
633
|
}
|
|
488
|
-
return
|
|
634
|
+
return finalize(
|
|
489
635
|
createNetworkError(
|
|
490
636
|
parsed.errorMessage,
|
|
491
637
|
status,
|
|
492
638
|
errorDetails,
|
|
493
639
|
parsed.userMessage,
|
|
494
640
|
suggestion
|
|
495
|
-
)
|
|
496
|
-
requestId
|
|
641
|
+
)
|
|
497
642
|
);
|
|
498
643
|
}
|
|
499
644
|
async function httpFetch(url, options) {
|
|
@@ -506,6 +651,7 @@ async function httpFetch(url, options) {
|
|
|
506
651
|
debug,
|
|
507
652
|
retry,
|
|
508
653
|
onUnauthorized,
|
|
654
|
+
errorFamily,
|
|
509
655
|
...requestInit
|
|
510
656
|
} = options || {};
|
|
511
657
|
const baseUrl = resolveApiUrl(apiUrl);
|
|
@@ -558,6 +704,8 @@ async function httpFetch(url, options) {
|
|
|
558
704
|
headers: redactSensitiveHeaders(response.headers)
|
|
559
705
|
});
|
|
560
706
|
if (!response.ok) {
|
|
707
|
+
const parsed = await parseErrorBody(response);
|
|
708
|
+
const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
|
|
561
709
|
if (isUsageLimitExceededResponse(response)) {
|
|
562
710
|
const limit = parseInt(
|
|
563
711
|
response.headers.get("X-Usage-Limit") || "0",
|
|
@@ -571,7 +719,7 @@ async function httpFetch(url, options) {
|
|
|
571
719
|
response.headers.get("X-Usage-Remaining") || "0",
|
|
572
720
|
10
|
|
573
721
|
);
|
|
574
|
-
|
|
722
|
+
const usageError = attachRequestId(
|
|
575
723
|
createUsageLimitError(
|
|
576
724
|
`Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
|
|
577
725
|
{ limit, current, remaining },
|
|
@@ -585,9 +733,9 @@ async function httpFetch(url, options) {
|
|
|
585
733
|
),
|
|
586
734
|
requestId
|
|
587
735
|
);
|
|
736
|
+
throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
|
|
588
737
|
}
|
|
589
|
-
|
|
590
|
-
if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
|
|
738
|
+
if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
|
|
591
739
|
hasRetried401 = true;
|
|
592
740
|
try {
|
|
593
741
|
const newToken = await onUnauthorized();
|
|
@@ -609,13 +757,18 @@ async function httpFetch(url, options) {
|
|
|
609
757
|
parsed,
|
|
610
758
|
details,
|
|
611
759
|
requestId,
|
|
612
|
-
retryAfter
|
|
760
|
+
retryAfter.seconds,
|
|
761
|
+
errorFamily
|
|
613
762
|
);
|
|
614
763
|
const method2 = (requestInit.method || "GET").toUpperCase();
|
|
615
764
|
const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
|
|
616
|
-
|
|
765
|
+
const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
|
|
766
|
+
if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
|
|
617
767
|
lastError = error;
|
|
618
|
-
const retryDelay =
|
|
768
|
+
const retryDelay = Math.max(
|
|
769
|
+
retryConfig.retryDelay(attempt),
|
|
770
|
+
(retryAfter.seconds ?? 0) * 1e3
|
|
771
|
+
);
|
|
619
772
|
debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
|
|
620
773
|
await delay(retryDelay);
|
|
621
774
|
continue;
|
|
@@ -685,87 +838,45 @@ async function httpFetch(url, options) {
|
|
|
685
838
|
throw lastError ?? new NetworkError("Request failed after retries");
|
|
686
839
|
}
|
|
687
840
|
|
|
688
|
-
// src/core/api/endpoints.ts
|
|
689
|
-
var COMMERCE_ENDPOINTS = {
|
|
690
|
-
orders: {
|
|
691
|
-
create: "/api/orders/create",
|
|
692
|
-
update: "/api/orders/update",
|
|
693
|
-
confirmPayment: "/api/orders/confirm-payment",
|
|
694
|
-
byPayment: "/api/orders/by-payment",
|
|
695
|
-
cancel: "/api/orders/cancel",
|
|
696
|
-
resolveCancelRefund: "/api/orders/resolve-cancel-refund",
|
|
697
|
-
checkout: "/api/orders/checkout",
|
|
698
|
-
createFulfillment: "/api/orders/create-fulfillment",
|
|
699
|
-
updateFulfillment: "/api/orders/update-fulfillment"
|
|
700
|
-
},
|
|
701
|
-
transactions: {
|
|
702
|
-
update: "/api/transactions/update"
|
|
703
|
-
},
|
|
704
|
-
returns: {
|
|
705
|
-
create: "/api/returns/create",
|
|
706
|
-
update: "/api/returns/update",
|
|
707
|
-
returnRefund: "/api/returns/return-refund"
|
|
708
|
-
},
|
|
709
|
-
fulfillmentOrders: {
|
|
710
|
-
prepare: "/api/fulfillment-orders/prepare-fulfillment-order"
|
|
711
|
-
},
|
|
712
|
-
fulfillments: {
|
|
713
|
-
bulkImport: "/api/fulfillments/bulk-import"
|
|
714
|
-
},
|
|
715
|
-
carts: {
|
|
716
|
-
mine: "/api/carts/mine",
|
|
717
|
-
merge: "/api/carts/merge",
|
|
718
|
-
addItem: "/api/carts/add-item",
|
|
719
|
-
updateItem: "/api/carts/update-item",
|
|
720
|
-
removeItem: "/api/carts/remove-item",
|
|
721
|
-
applyDiscount: "/api/carts/apply-discount",
|
|
722
|
-
removeDiscount: "/api/carts/remove-discount",
|
|
723
|
-
clear: "/api/carts/clear"
|
|
724
|
-
},
|
|
725
|
-
products: {
|
|
726
|
-
stockCheck: "/api/products/stock-check",
|
|
727
|
-
stockSnapshot: "/api/products/stock",
|
|
728
|
-
listingGroups: "/api/products/listing-groups",
|
|
729
|
-
listingGroupsCatalog: "/api/products/listing-groups/catalog",
|
|
730
|
-
listingGroupsQuery: "/api/products/listing-groups/query",
|
|
731
|
-
listingGroupsQueryCatalog: "/api/products/listing-groups/query/catalog",
|
|
732
|
-
detail: "/api/products/detail",
|
|
733
|
-
detailCatalog: "/api/products/detail/catalog",
|
|
734
|
-
upsert: "/api/products/upsert"
|
|
735
|
-
}
|
|
736
|
-
};
|
|
737
|
-
var COMMERCE_ENDPOINT_PATHS = Object.values(
|
|
738
|
-
COMMERCE_ENDPOINTS
|
|
739
|
-
).flatMap((group) => Object.values(group));
|
|
740
|
-
var MEMBERSHIP_ENDPOINTS = {
|
|
741
|
-
subscribe: "/api/memberships/subscribe",
|
|
742
|
-
cancel: (id) => `/api/memberships/${id}/cancel`,
|
|
743
|
-
me: "/api/memberships/me"
|
|
744
|
-
};
|
|
745
|
-
|
|
746
841
|
// src/core/internal/utils/query-string.ts
|
|
747
|
-
function
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
842
|
+
function normalizedMarket(value) {
|
|
843
|
+
const market = value?.trim();
|
|
844
|
+
return market || void 0;
|
|
845
|
+
}
|
|
846
|
+
function appendProductLocaleSearchParams(search, options) {
|
|
847
|
+
if (options?.locale) search.set("locale", options.locale);
|
|
848
|
+
if (options?.fallbackLocale !== void 0) {
|
|
849
|
+
search.set(
|
|
850
|
+
"fallbackLocale",
|
|
851
|
+
options.fallbackLocale === false ? "none" : options.fallbackLocale
|
|
852
|
+
);
|
|
753
853
|
}
|
|
754
|
-
return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
|
|
755
854
|
}
|
|
756
|
-
function
|
|
855
|
+
function productDetailSearchParams(params) {
|
|
757
856
|
const search = new URLSearchParams();
|
|
758
857
|
if ("slug" in params) {
|
|
759
858
|
search.set("slug", params.slug);
|
|
760
859
|
} else {
|
|
761
860
|
search.set("id", params.id);
|
|
762
861
|
}
|
|
763
|
-
|
|
862
|
+
const market = normalizedMarket(params.market);
|
|
863
|
+
if (market) search.set("market", market);
|
|
864
|
+
appendProductLocaleSearchParams(search, params);
|
|
865
|
+
return search.toString();
|
|
764
866
|
}
|
|
765
|
-
function
|
|
766
|
-
|
|
867
|
+
function listingGroupsSearchParams(params) {
|
|
868
|
+
const ids = params.productIds.map(encodeURIComponent).join(",");
|
|
869
|
+
const search = new URLSearchParams();
|
|
870
|
+
const market = normalizedMarket(params.market);
|
|
871
|
+
if (market) search.set("market", market);
|
|
872
|
+
appendProductLocaleSearchParams(search, params);
|
|
873
|
+
const query = search.toString();
|
|
874
|
+
return `ids=${ids}${query ? `&${query}` : ""}`;
|
|
767
875
|
}
|
|
768
876
|
function appendListingGroupsQuerySearchParams(search, options) {
|
|
877
|
+
const market = normalizedMarket(options?.market);
|
|
878
|
+
if (market) search.set("market", market);
|
|
879
|
+
appendProductLocaleSearchParams(search, options);
|
|
769
880
|
if (options?.page != null) search.set("page", String(options.page));
|
|
770
881
|
if (options?.limit != null) search.set("limit", String(options.limit));
|
|
771
882
|
if (options?.sort != null) {
|
|
@@ -776,20 +887,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
|
|
|
776
887
|
search.set("whereJson", JSON.stringify(options.where));
|
|
777
888
|
}
|
|
778
889
|
}
|
|
779
|
-
function
|
|
780
|
-
const search = new URLSearchParams();
|
|
781
|
-
appendListingGroupsQuerySearchParams(search, options);
|
|
782
|
-
const query = search.toString();
|
|
783
|
-
return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
|
|
784
|
-
}
|
|
785
|
-
function listingGroupsQueryCatalogUrl(options) {
|
|
890
|
+
function listingPageSearchParams(options) {
|
|
786
891
|
const search = new URLSearchParams();
|
|
787
892
|
appendListingGroupsQuerySearchParams(search, options);
|
|
788
|
-
|
|
789
|
-
return `${COMMERCE_ENDPOINTS.products.listingGroupsQueryCatalog}${query ? `?${query}` : ""}`;
|
|
893
|
+
return search.toString();
|
|
790
894
|
}
|
|
791
|
-
function
|
|
792
|
-
return
|
|
895
|
+
function stockSnapshotSearchParams(params) {
|
|
896
|
+
return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
|
|
793
897
|
}
|
|
794
898
|
|
|
795
899
|
// src/core/collection/http-client.ts
|
|
@@ -832,10 +936,15 @@ var HttpClient = class {
|
|
|
832
936
|
throw err;
|
|
833
937
|
}
|
|
834
938
|
}
|
|
835
|
-
buildUrl(
|
|
836
|
-
if (!options) return
|
|
837
|
-
const
|
|
838
|
-
|
|
939
|
+
buildUrl(endpoint2, options) {
|
|
940
|
+
if (!options) return endpoint2;
|
|
941
|
+
const { fallbackLocale, ...rest } = options;
|
|
942
|
+
const queryOptions = fallbackLocale === void 0 ? rest : {
|
|
943
|
+
...rest,
|
|
944
|
+
"fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
|
|
945
|
+
};
|
|
946
|
+
const queryString = stringify(queryOptions, { addQueryPrefix: true });
|
|
947
|
+
return queryString ? `${endpoint2}${queryString}` : endpoint2;
|
|
839
948
|
}
|
|
840
949
|
assertJsonResponse(response) {
|
|
841
950
|
const contentType = response.headers.get("content-type");
|
|
@@ -984,39 +1093,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
984
1093
|
from(collection) {
|
|
985
1094
|
return new ReadOnlyCollectionQueryBuilder(this, collection);
|
|
986
1095
|
}
|
|
987
|
-
async requestFind(
|
|
988
|
-
const url = this.buildUrl(
|
|
1096
|
+
async requestFind(endpoint2, options) {
|
|
1097
|
+
const url = this.buildUrl(endpoint2, options);
|
|
989
1098
|
const response = await this.fetchWithTracking(url, {
|
|
990
1099
|
...this.defaultOptions,
|
|
991
1100
|
method: "GET"
|
|
992
1101
|
});
|
|
993
1102
|
return this.parseFindResponse(response);
|
|
994
1103
|
}
|
|
995
|
-
async requestFindEndpoint(
|
|
996
|
-
const response = await this.fetchWithTracking(
|
|
1104
|
+
async requestFindEndpoint(endpoint2, data) {
|
|
1105
|
+
const response = await this.fetchWithTracking(endpoint2, {
|
|
997
1106
|
...this.defaultOptions,
|
|
998
1107
|
method: "POST",
|
|
999
1108
|
body: data ? JSON.stringify(data) : void 0
|
|
1000
1109
|
});
|
|
1001
1110
|
return this.parseFindResponse(response);
|
|
1002
1111
|
}
|
|
1003
|
-
async requestFindEndpointGet(
|
|
1004
|
-
const response = await this.fetchWithTracking(
|
|
1112
|
+
async requestFindEndpointGet(endpoint2) {
|
|
1113
|
+
const response = await this.fetchWithTracking(endpoint2, {
|
|
1005
1114
|
...this.defaultOptions,
|
|
1006
1115
|
method: "GET"
|
|
1007
1116
|
});
|
|
1008
1117
|
return this.parseFindResponse(response);
|
|
1009
1118
|
}
|
|
1010
|
-
async requestFindById(
|
|
1011
|
-
const url = this.buildUrl(
|
|
1119
|
+
async requestFindById(endpoint2, options) {
|
|
1120
|
+
const url = this.buildUrl(endpoint2, options);
|
|
1012
1121
|
const response = await this.fetchWithTracking(url, {
|
|
1013
1122
|
...this.defaultOptions,
|
|
1014
1123
|
method: "GET"
|
|
1015
1124
|
});
|
|
1016
1125
|
return this.parseDocumentResponse(response);
|
|
1017
1126
|
}
|
|
1018
|
-
async requestCount(
|
|
1019
|
-
const url = this.buildUrl(
|
|
1127
|
+
async requestCount(endpoint2, options) {
|
|
1128
|
+
const url = this.buildUrl(endpoint2, options);
|
|
1020
1129
|
const response = await this.fetchWithTracking(url, {
|
|
1021
1130
|
...this.defaultOptions,
|
|
1022
1131
|
method: "GET"
|
|
@@ -1026,53 +1135,347 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1026
1135
|
};
|
|
1027
1136
|
|
|
1028
1137
|
// src/core/api/parse-response.ts
|
|
1029
|
-
async function parseApiResponse(response,
|
|
1030
|
-
|
|
1138
|
+
async function parseApiResponse(response, endpoint2, options = {}) {
|
|
1139
|
+
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
1140
|
+
return void 0;
|
|
1141
|
+
}
|
|
1142
|
+
let parsed;
|
|
1031
1143
|
try {
|
|
1032
|
-
|
|
1144
|
+
parsed = await response.json();
|
|
1033
1145
|
} catch {
|
|
1034
1146
|
throw createApiError(
|
|
1035
|
-
`Invalid JSON response from ${
|
|
1147
|
+
`Invalid JSON response from ${endpoint2}`,
|
|
1036
1148
|
response.status,
|
|
1037
1149
|
void 0,
|
|
1038
1150
|
"Server returned an invalid response.",
|
|
1039
1151
|
"Check if the API endpoint is available."
|
|
1040
1152
|
);
|
|
1041
1153
|
}
|
|
1154
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
1155
|
+
return parsed;
|
|
1156
|
+
}
|
|
1157
|
+
const data = parsed;
|
|
1042
1158
|
if (data.error) {
|
|
1043
1159
|
const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
|
|
1044
1160
|
const reason = typeof data.reason === "string" ? data.reason : void 0;
|
|
1045
1161
|
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
1046
|
-
const
|
|
1047
|
-
|
|
1162
|
+
const retryAfter = parseRetryAfter(response).seconds;
|
|
1163
|
+
let error;
|
|
1048
1164
|
if (reason === "validation_failed") {
|
|
1049
|
-
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1165
|
+
error = createValidationError(errorMessage, data, errorMessage);
|
|
1166
|
+
} else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
|
|
1167
|
+
error = createAuthError(errorMessage, data, errorMessage);
|
|
1168
|
+
} else if (reason === "forbidden") {
|
|
1169
|
+
error = createPermissionError(errorMessage, data, errorMessage);
|
|
1170
|
+
} else if (reason === "rate_limit_exceeded") {
|
|
1171
|
+
error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
|
|
1172
|
+
} else if (reason === "not_found") {
|
|
1173
|
+
error = createNotFoundError(errorMessage, data, errorMessage);
|
|
1174
|
+
} else if (reason === "conflict") {
|
|
1175
|
+
error = createConflictError(errorMessage, data, errorMessage);
|
|
1176
|
+
} else {
|
|
1177
|
+
error = createApiError(
|
|
1178
|
+
errorMessage,
|
|
1179
|
+
response.status,
|
|
1180
|
+
data,
|
|
1181
|
+
errorMessage,
|
|
1182
|
+
"An error occurred while processing the request."
|
|
1183
|
+
);
|
|
1053
1184
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1185
|
+
const withRequestId = attachRequestId(error, requestId);
|
|
1186
|
+
if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
|
|
1187
|
+
throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
|
|
1188
|
+
}
|
|
1189
|
+
return data;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
// ../../internal/http-contracts/src/index.ts
|
|
1193
|
+
var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
|
|
1194
|
+
var operation = (collection, method, path) => Object.freeze({
|
|
1195
|
+
[operationBrand]: true,
|
|
1196
|
+
collection,
|
|
1197
|
+
method,
|
|
1198
|
+
path
|
|
1199
|
+
});
|
|
1200
|
+
var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
1201
|
+
products: {
|
|
1202
|
+
detail: operation("products", "get", "/detail"),
|
|
1203
|
+
detailCatalog: operation("products", "get", "/detail/catalog"),
|
|
1204
|
+
listingGroups: operation("products", "get", "/listing-groups"),
|
|
1205
|
+
listingGroupsCatalog: operation(
|
|
1206
|
+
"products",
|
|
1207
|
+
"get",
|
|
1208
|
+
"/listing-groups/catalog"
|
|
1209
|
+
),
|
|
1210
|
+
listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
|
|
1211
|
+
listingGroupsQueryGet: operation(
|
|
1212
|
+
"products",
|
|
1213
|
+
"get",
|
|
1214
|
+
"/listing-groups/query"
|
|
1215
|
+
),
|
|
1216
|
+
listingGroupsQueryCatalog: operation(
|
|
1217
|
+
"products",
|
|
1218
|
+
"get",
|
|
1219
|
+
"/listing-groups/query/catalog"
|
|
1220
|
+
),
|
|
1221
|
+
stockCheck: operation("products", "post", "/stock-check"),
|
|
1222
|
+
stockSnapshot: operation("products", "get", "/stock"),
|
|
1223
|
+
upsert: operation("products", "post", "/upsert")
|
|
1224
|
+
},
|
|
1225
|
+
orders: {
|
|
1226
|
+
create: operation("orders", "post", "/create"),
|
|
1227
|
+
update: operation("orders", "post", "/update"),
|
|
1228
|
+
confirmPayment: operation("orders", "post", "/confirm-payment"),
|
|
1229
|
+
byPayment: operation("orders", "get", "/by-payment"),
|
|
1230
|
+
cancel: operation("orders", "post", "/cancel"),
|
|
1231
|
+
resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
|
|
1232
|
+
checkout: operation("orders", "post", "/checkout"),
|
|
1233
|
+
createFulfillment: operation("orders", "post", "/create-fulfillment"),
|
|
1234
|
+
updateFulfillment: operation("orders", "post", "/update-fulfillment")
|
|
1235
|
+
},
|
|
1236
|
+
checkouts: {
|
|
1237
|
+
detail: operation("checkouts", "post", "/detail"),
|
|
1238
|
+
query: operation("checkouts", "post", "/query")
|
|
1239
|
+
},
|
|
1240
|
+
transactions: {
|
|
1241
|
+
update: operation("transactions", "post", "/update")
|
|
1242
|
+
},
|
|
1243
|
+
returns: {
|
|
1244
|
+
create: operation("returns", "post", "/create"),
|
|
1245
|
+
update: operation("returns", "post", "/update"),
|
|
1246
|
+
returnRefund: operation("returns", "post", "/return-refund")
|
|
1247
|
+
},
|
|
1248
|
+
fulfillmentOrders: {
|
|
1249
|
+
prepare: operation(
|
|
1250
|
+
"fulfillment-orders",
|
|
1251
|
+
"post",
|
|
1252
|
+
"/prepare-fulfillment-order"
|
|
1253
|
+
)
|
|
1254
|
+
},
|
|
1255
|
+
fulfillments: {
|
|
1256
|
+
bulkImport: operation("fulfillments", "post", "/bulk-import")
|
|
1257
|
+
},
|
|
1258
|
+
carts: {
|
|
1259
|
+
create: operation("carts", "post", "/create"),
|
|
1260
|
+
retrieve: operation("carts", "post", "/retrieve"),
|
|
1261
|
+
mine: operation("carts", "post", "/mine"),
|
|
1262
|
+
merge: operation("carts", "post", "/merge"),
|
|
1263
|
+
addItem: operation("carts", "post", "/add-item"),
|
|
1264
|
+
updateItem: operation("carts", "post", "/update-item"),
|
|
1265
|
+
removeItem: operation("carts", "post", "/remove-item"),
|
|
1266
|
+
updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
|
|
1267
|
+
updateAttributes: operation("carts", "post", "/update-attributes"),
|
|
1268
|
+
clear: operation("carts", "post", "/clear")
|
|
1269
|
+
},
|
|
1270
|
+
paymentSessions: {
|
|
1271
|
+
create: operation("payment-sessions", "post", "/create"),
|
|
1272
|
+
retrieve: operation("payment-sessions", "post", "/retrieve"),
|
|
1273
|
+
cancel: operation("payment-sessions", "post", "/cancel"),
|
|
1274
|
+
server: {
|
|
1275
|
+
create: operation("payment-sessions", "post", "/server/create"),
|
|
1276
|
+
retrieve: operation("payment-sessions", "post", "/server/retrieve"),
|
|
1277
|
+
cancel: operation("payment-sessions", "post", "/server/cancel"),
|
|
1278
|
+
confirm: operation("payment-sessions", "post", "/server/confirm")
|
|
1279
|
+
},
|
|
1280
|
+
custom: {
|
|
1281
|
+
create: operation("orders", "post", "/custom-payment-sessions"),
|
|
1282
|
+
confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
|
|
1056
1283
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1284
|
+
},
|
|
1285
|
+
shippingPolicies: {
|
|
1286
|
+
calculate: operation("shipping-policies", "post", "/calculate")
|
|
1287
|
+
},
|
|
1288
|
+
discounts: {
|
|
1289
|
+
validate: operation("discounts", "post", "/validate")
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1292
|
+
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
1293
|
+
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
1294
|
+
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
1295
|
+
me: operation(null, "get", "/memberships/me")
|
|
1296
|
+
};
|
|
1297
|
+
var EVENTS_ENDPOINT_OPERATIONS = {
|
|
1298
|
+
occurrences: {
|
|
1299
|
+
range: operation("event-occurrences", "get", "/range"),
|
|
1300
|
+
admissionAvailability: operation(
|
|
1301
|
+
"event-occurrences",
|
|
1302
|
+
"get",
|
|
1303
|
+
"/admission-availability"
|
|
1304
|
+
)
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
function resolveOperationTemplate(descriptor) {
|
|
1308
|
+
return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
|
|
1309
|
+
}
|
|
1310
|
+
function resolveOperationPath(descriptor, options) {
|
|
1311
|
+
const path = resolveOperationTemplate(descriptor).replace(
|
|
1312
|
+
/:([A-Za-z][A-Za-z0-9_]*)/g,
|
|
1313
|
+
(_, key) => {
|
|
1314
|
+
const value = options?.pathParams?.[key];
|
|
1315
|
+
if (value === void 0) {
|
|
1316
|
+
throw new TypeError(`Missing path parameter: ${key}`);
|
|
1317
|
+
}
|
|
1318
|
+
return encodeURIComponent(value);
|
|
1059
1319
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1320
|
+
);
|
|
1321
|
+
const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
|
|
1322
|
+
if (unresolved) {
|
|
1323
|
+
throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
|
|
1324
|
+
}
|
|
1325
|
+
const query = options?.query?.toString().replace(/^\?/, "");
|
|
1326
|
+
return query ? `${path}?${query}` : path;
|
|
1327
|
+
}
|
|
1328
|
+
function resolveOperationMethod(descriptor) {
|
|
1329
|
+
return descriptor.method.toUpperCase();
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
// src/core/api/endpoints.ts
|
|
1333
|
+
var endpoint = (method, path) => ({ method, path });
|
|
1334
|
+
var sharedEndpoint = (descriptor) => descriptor;
|
|
1335
|
+
function resolveOperationMethod2(descriptor) {
|
|
1336
|
+
return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
|
|
1337
|
+
}
|
|
1338
|
+
function resolveOperationPath2(descriptor, options) {
|
|
1339
|
+
if ("collection" in descriptor) {
|
|
1340
|
+
return resolveOperationPath(descriptor, options);
|
|
1341
|
+
}
|
|
1342
|
+
const query = options?.query?.toString().replace(/^\?/, "");
|
|
1343
|
+
return query ? `${descriptor.path}?${query}` : descriptor.path;
|
|
1344
|
+
}
|
|
1345
|
+
var COMMERCE_ENDPOINTS = {
|
|
1346
|
+
products: {
|
|
1347
|
+
detail: endpoint("GET", "/api/products/detail"),
|
|
1348
|
+
detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
|
|
1349
|
+
listingGroups: endpoint("GET", "/api/products/listing-groups"),
|
|
1350
|
+
listingGroupsCatalog: endpoint(
|
|
1351
|
+
"GET",
|
|
1352
|
+
"/api/products/listing-groups/catalog"
|
|
1353
|
+
),
|
|
1354
|
+
listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
|
|
1355
|
+
listingGroupsQueryCatalog: endpoint(
|
|
1356
|
+
"GET",
|
|
1357
|
+
"/api/products/listing-groups/query/catalog"
|
|
1358
|
+
),
|
|
1359
|
+
stockCheck: endpoint("POST", "/api/products/stock-check"),
|
|
1360
|
+
stockSnapshot: endpoint("GET", "/api/products/stock"),
|
|
1361
|
+
upsert: endpoint("POST", "/api/products/upsert")
|
|
1362
|
+
},
|
|
1363
|
+
orders: {
|
|
1364
|
+
update: endpoint("POST", "/api/orders/update"),
|
|
1365
|
+
byPayment: endpoint("GET", "/api/orders/by-payment"),
|
|
1366
|
+
cancel: endpoint("POST", "/api/orders/cancel"),
|
|
1367
|
+
resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
|
|
1368
|
+
createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
|
|
1369
|
+
updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
|
|
1370
|
+
},
|
|
1371
|
+
checkouts: {
|
|
1372
|
+
create: endpoint("POST", "/api/orders/checkout"),
|
|
1373
|
+
retrieve: endpoint("POST", "/api/checkouts/detail"),
|
|
1374
|
+
server: {
|
|
1375
|
+
create: endpoint("POST", "/api/orders/checkout"),
|
|
1376
|
+
retrieve: endpoint("POST", "/api/checkouts/detail"),
|
|
1377
|
+
query: endpoint("POST", "/api/checkouts/query")
|
|
1062
1378
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1379
|
+
},
|
|
1380
|
+
returns: {
|
|
1381
|
+
create: endpoint("POST", "/api/returns/create"),
|
|
1382
|
+
update: endpoint("POST", "/api/returns/update"),
|
|
1383
|
+
returnRefund: endpoint("POST", "/api/returns/return-refund")
|
|
1384
|
+
},
|
|
1385
|
+
fulfillmentOrders: {
|
|
1386
|
+
prepare: endpoint(
|
|
1387
|
+
"POST",
|
|
1388
|
+
"/api/fulfillment-orders/prepare-fulfillment-order"
|
|
1389
|
+
)
|
|
1390
|
+
},
|
|
1391
|
+
fulfillments: {
|
|
1392
|
+
bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
|
|
1393
|
+
},
|
|
1394
|
+
carts: {
|
|
1395
|
+
create: endpoint("POST", "/api/carts/create"),
|
|
1396
|
+
retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
|
|
1397
|
+
mine: endpoint("POST", "/api/carts/mine"),
|
|
1398
|
+
merge: endpoint("POST", "/api/carts/merge"),
|
|
1399
|
+
server: {
|
|
1400
|
+
// Server credentials are an authorization lane, not a second Cart
|
|
1401
|
+
// transport. These must stay bound to the registered shared operations.
|
|
1402
|
+
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
|
|
1403
|
+
retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
|
|
1404
|
+
mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
|
|
1405
|
+
merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
|
|
1406
|
+
addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
|
|
1407
|
+
updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
|
|
1408
|
+
removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
|
|
1409
|
+
updateDiscountCodes: sharedEndpoint(
|
|
1410
|
+
COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
|
|
1411
|
+
),
|
|
1412
|
+
updateAttributes: sharedEndpoint(
|
|
1413
|
+
COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
|
|
1414
|
+
),
|
|
1415
|
+
clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
|
|
1416
|
+
},
|
|
1417
|
+
addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
|
|
1418
|
+
updateItem: endpoint("POST", "/api/carts/update-item"),
|
|
1419
|
+
removeItem: endpoint("POST", "/api/carts/remove-item"),
|
|
1420
|
+
updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
|
|
1421
|
+
updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
|
|
1422
|
+
clear: endpoint("POST", "/api/carts/clear")
|
|
1423
|
+
},
|
|
1424
|
+
paymentSessions: {
|
|
1425
|
+
create: endpoint("POST", "/api/payment-sessions/create"),
|
|
1426
|
+
retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
|
|
1427
|
+
cancel: endpoint("POST", "/api/payment-sessions/cancel"),
|
|
1428
|
+
custom: {
|
|
1429
|
+
create: sharedEndpoint(
|
|
1430
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.create
|
|
1431
|
+
),
|
|
1432
|
+
confirm: sharedEndpoint(
|
|
1433
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.custom.confirm
|
|
1434
|
+
)
|
|
1435
|
+
},
|
|
1436
|
+
server: {
|
|
1437
|
+
create: endpoint("POST", "/api/payment-sessions/server/create"),
|
|
1438
|
+
retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
|
|
1439
|
+
cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
|
|
1440
|
+
confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
|
|
1065
1441
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
);
|
|
1442
|
+
},
|
|
1443
|
+
shippingPolicies: {
|
|
1444
|
+
calculate: endpoint("POST", "/api/shipping-policies/calculate")
|
|
1070
1445
|
}
|
|
1071
|
-
|
|
1446
|
+
};
|
|
1447
|
+
function isCommerceEndpointDescriptor(value) {
|
|
1448
|
+
if (!value || typeof value !== "object") return false;
|
|
1449
|
+
const candidate = value;
|
|
1450
|
+
return typeof candidate.method === "string" && typeof candidate.path === "string";
|
|
1451
|
+
}
|
|
1452
|
+
function flattenEndpointPaths(value) {
|
|
1453
|
+
if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
|
|
1454
|
+
if (!value || typeof value !== "object") return [];
|
|
1455
|
+
return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
|
|
1456
|
+
}
|
|
1457
|
+
function flattenEndpointDescriptors(value) {
|
|
1458
|
+
if (isCommerceEndpointDescriptor(value)) return [value];
|
|
1459
|
+
if (!value || typeof value !== "object") return [];
|
|
1460
|
+
return Object.values(value).flatMap(
|
|
1461
|
+
(entry) => flattenEndpointDescriptors(entry)
|
|
1462
|
+
);
|
|
1072
1463
|
}
|
|
1464
|
+
var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
|
|
1465
|
+
var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
|
|
1466
|
+
var MEMBERSHIP_ENDPOINTS = {
|
|
1467
|
+
subscribe: "/api/memberships/subscribe",
|
|
1468
|
+
cancel: (id) => `/api/memberships/${id}/cancel`,
|
|
1469
|
+
me: "/api/memberships/me"
|
|
1470
|
+
};
|
|
1471
|
+
var MEMBERSHIP_ENDPOINT_PATHS = [
|
|
1472
|
+
MEMBERSHIP_ENDPOINTS.subscribe,
|
|
1473
|
+
MEMBERSHIP_ENDPOINTS.cancel(":id"),
|
|
1474
|
+
MEMBERSHIP_ENDPOINTS.me
|
|
1475
|
+
];
|
|
1073
1476
|
|
|
1074
1477
|
// src/core/api/customer-scoped-api.ts
|
|
1075
|
-
var
|
|
1478
|
+
var CustomerScopedTransport = class {
|
|
1076
1479
|
constructor(apiName, options) {
|
|
1077
1480
|
if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
|
|
1078
1481
|
throw createConfigError(
|
|
@@ -1090,10 +1493,10 @@ var CustomerScopedApi = class {
|
|
|
1090
1493
|
this.onUnauthorized = options.onUnauthorized;
|
|
1091
1494
|
this.onRequestId = options.onRequestId;
|
|
1092
1495
|
}
|
|
1093
|
-
async request(
|
|
1496
|
+
async request(endpoint2, options) {
|
|
1094
1497
|
const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
|
|
1095
1498
|
try {
|
|
1096
|
-
const response = await httpFetch(
|
|
1499
|
+
const response = await httpFetch(endpoint2, {
|
|
1097
1500
|
method: options.method,
|
|
1098
1501
|
apiUrl: this.apiUrl,
|
|
1099
1502
|
publishableKey: this.publishableKey,
|
|
@@ -1103,10 +1506,13 @@ var CustomerScopedApi = class {
|
|
|
1103
1506
|
...options.body !== void 0 && {
|
|
1104
1507
|
body: JSON.stringify(options.body)
|
|
1105
1508
|
},
|
|
1106
|
-
...options.headers && { headers: options.headers }
|
|
1509
|
+
...options.headers && { headers: options.headers },
|
|
1510
|
+
...options.errorFamily && { errorFamily: options.errorFamily }
|
|
1107
1511
|
});
|
|
1108
1512
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
1109
|
-
return parseApiResponse(response,
|
|
1513
|
+
return parseApiResponse(response, endpoint2, {
|
|
1514
|
+
errorFamily: options.errorFamily
|
|
1515
|
+
});
|
|
1110
1516
|
} catch (err) {
|
|
1111
1517
|
const id = err instanceof SDKError ? err.requestId ?? null : null;
|
|
1112
1518
|
this.onRequestId?.(id);
|
|
@@ -1114,6 +1520,26 @@ var CustomerScopedApi = class {
|
|
|
1114
1520
|
}
|
|
1115
1521
|
}
|
|
1116
1522
|
};
|
|
1523
|
+
var CustomerScopedApi = class {
|
|
1524
|
+
constructor(apiName, options) {
|
|
1525
|
+
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1526
|
+
}
|
|
1527
|
+
requestEndpoint(endpoint2, body, options) {
|
|
1528
|
+
return this.transport.request(resolveOperationPath2(endpoint2, options), {
|
|
1529
|
+
method: resolveOperationMethod2(endpoint2),
|
|
1530
|
+
body,
|
|
1531
|
+
headers: options?.headers
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
var RawCustomerScopedApi = class {
|
|
1536
|
+
constructor(apiName, options) {
|
|
1537
|
+
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1538
|
+
}
|
|
1539
|
+
request(endpoint2, options) {
|
|
1540
|
+
return this.transport.request(endpoint2, options);
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1117
1543
|
|
|
1118
1544
|
// src/core/community/community-client.ts
|
|
1119
1545
|
var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
|
|
@@ -1124,7 +1550,7 @@ function unwrapPayloadDoc(value) {
|
|
|
1124
1550
|
}
|
|
1125
1551
|
return value;
|
|
1126
1552
|
}
|
|
1127
|
-
var CommunityClient = class extends
|
|
1553
|
+
var CommunityClient = class extends RawCustomerScopedApi {
|
|
1128
1554
|
constructor(options) {
|
|
1129
1555
|
super("CommunityClient", { ...options, requiresCredential: false });
|
|
1130
1556
|
}
|
|
@@ -1168,11 +1594,11 @@ var CommunityClient = class extends CustomerScopedApi {
|
|
|
1168
1594
|
if (params.page !== void 0) urlParams.set("page", String(params.page));
|
|
1169
1595
|
return `/api/comments/public?${urlParams.toString()}`;
|
|
1170
1596
|
}
|
|
1171
|
-
async execute(
|
|
1172
|
-
return this.request(
|
|
1597
|
+
async execute(endpoint2, method, body) {
|
|
1598
|
+
return this.request(endpoint2, { method, body });
|
|
1173
1599
|
}
|
|
1174
|
-
async executeDoc(
|
|
1175
|
-
const response = await this.execute(
|
|
1600
|
+
async executeDoc(endpoint2, method, body) {
|
|
1601
|
+
const response = await this.execute(endpoint2, method, body);
|
|
1176
1602
|
return unwrapPayloadDoc(response);
|
|
1177
1603
|
}
|
|
1178
1604
|
createPost(params) {
|
|
@@ -1408,56 +1834,1538 @@ var CommunityClient = class extends CustomerScopedApi {
|
|
|
1408
1834
|
body
|
|
1409
1835
|
);
|
|
1410
1836
|
}
|
|
1411
|
-
};
|
|
1412
|
-
|
|
1413
|
-
// src/core/content/content-client.ts
|
|
1414
|
-
var PublicContentApi = class extends
|
|
1415
|
-
get(
|
|
1416
|
-
return this.request(
|
|
1417
|
-
}
|
|
1418
|
-
};
|
|
1419
|
-
function appendCommonParams(search, options, defaultSort) {
|
|
1420
|
-
search.set("sort", options?.sort ?? defaultSort);
|
|
1421
|
-
if (options?.page != null) search.set("page", String(options.page));
|
|
1422
|
-
if (options?.limit != null) search.set("limit", String(options.limit));
|
|
1423
|
-
}
|
|
1424
|
-
function linksListPath(options) {
|
|
1425
|
-
const search = new URLSearchParams();
|
|
1426
|
-
appendCommonParams(search, options, "-publishedAt,-createdAt");
|
|
1427
|
-
if (options?.categoryId) search.set("categoryId", options.categoryId);
|
|
1428
|
-
if (options?.categorySlug) {
|
|
1429
|
-
search.set("categorySlug", options.categorySlug);
|
|
1430
|
-
}
|
|
1431
|
-
if (options?.tagId) search.set("tagId", options.tagId);
|
|
1432
|
-
if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
|
|
1433
|
-
if (options?.featured != null)
|
|
1434
|
-
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
if (options?.
|
|
1441
|
-
|
|
1837
|
+
};
|
|
1838
|
+
|
|
1839
|
+
// src/core/content/content-client.ts
|
|
1840
|
+
var PublicContentApi = class extends RawCustomerScopedApi {
|
|
1841
|
+
get(endpoint2) {
|
|
1842
|
+
return this.request(endpoint2, { method: "GET" });
|
|
1843
|
+
}
|
|
1844
|
+
};
|
|
1845
|
+
function appendCommonParams(search, options, defaultSort) {
|
|
1846
|
+
search.set("sort", options?.sort ?? defaultSort);
|
|
1847
|
+
if (options?.page != null) search.set("page", String(options.page));
|
|
1848
|
+
if (options?.limit != null) search.set("limit", String(options.limit));
|
|
1849
|
+
}
|
|
1850
|
+
function linksListPath(options) {
|
|
1851
|
+
const search = new URLSearchParams();
|
|
1852
|
+
appendCommonParams(search, options, "-publishedAt,-createdAt");
|
|
1853
|
+
if (options?.categoryId) search.set("categoryId", options.categoryId);
|
|
1854
|
+
if (options?.categorySlug) {
|
|
1855
|
+
search.set("categorySlug", options.categorySlug);
|
|
1856
|
+
}
|
|
1857
|
+
if (options?.tagId) search.set("tagId", options.tagId);
|
|
1858
|
+
if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
|
|
1859
|
+
if (options?.featured != null)
|
|
1860
|
+
search.set("featured", String(options.featured));
|
|
1861
|
+
return `/api/links/storefront?${search}`;
|
|
1862
|
+
}
|
|
1863
|
+
function galleryItemsListPath(options) {
|
|
1864
|
+
const search = new URLSearchParams();
|
|
1865
|
+
appendCommonParams(search, options, "manual");
|
|
1866
|
+
if (options?.galleryId) search.set("galleryId", options.galleryId);
|
|
1867
|
+
if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
|
|
1868
|
+
return `/api/gallery-items/storefront?${search}`;
|
|
1869
|
+
}
|
|
1870
|
+
var ContentClient = class {
|
|
1871
|
+
constructor(options) {
|
|
1872
|
+
const api = new PublicContentApi("ContentClient", {
|
|
1873
|
+
publishableKey: options.publishableKey,
|
|
1874
|
+
apiUrl: options.apiUrl,
|
|
1875
|
+
onRequestId: options.onRequestId,
|
|
1876
|
+
requiresCredential: false
|
|
1877
|
+
});
|
|
1878
|
+
this.links = {
|
|
1879
|
+
list: (params) => api.get(linksListPath(params))
|
|
1880
|
+
};
|
|
1881
|
+
this.galleryItems = {
|
|
1882
|
+
list: (params) => api.get(
|
|
1883
|
+
galleryItemsListPath(params)
|
|
1884
|
+
)
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
};
|
|
1888
|
+
|
|
1889
|
+
// src/core/api/canonical-response.ts
|
|
1890
|
+
var CART_STATUSES = ["active", "completed", "abandoned"];
|
|
1891
|
+
var MAX_CART_LINE_QUANTITY = 99;
|
|
1892
|
+
var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
|
|
1893
|
+
var MAX_COMMERCE_ADDRESS_LENGTH = 500;
|
|
1894
|
+
var MAX_COMMERCE_EMAIL_LENGTH = 254;
|
|
1895
|
+
var MAX_COMMERCE_PHONE_LENGTH = 32;
|
|
1896
|
+
var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
|
|
1897
|
+
var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
|
|
1898
|
+
var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
|
|
1899
|
+
var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
|
|
1900
|
+
var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
|
|
1901
|
+
var ORDER_FINANCIAL_STATUSES = [
|
|
1902
|
+
"pending",
|
|
1903
|
+
"authorized",
|
|
1904
|
+
"expired",
|
|
1905
|
+
"partially_paid",
|
|
1906
|
+
"paid",
|
|
1907
|
+
"canceled",
|
|
1908
|
+
"partially_refunded",
|
|
1909
|
+
"refunded",
|
|
1910
|
+
"reconciliation_required"
|
|
1911
|
+
];
|
|
1912
|
+
var ORDER_FULFILLMENT_STATUSES = [
|
|
1913
|
+
"unfulfilled",
|
|
1914
|
+
"in_progress",
|
|
1915
|
+
"on_hold",
|
|
1916
|
+
"partially_fulfilled",
|
|
1917
|
+
"shipped",
|
|
1918
|
+
"fulfilled",
|
|
1919
|
+
"canceled"
|
|
1920
|
+
];
|
|
1921
|
+
var ORDER_RETURN_STATUSES = [
|
|
1922
|
+
"no_return",
|
|
1923
|
+
"return_requested",
|
|
1924
|
+
"in_progress",
|
|
1925
|
+
"returned"
|
|
1926
|
+
];
|
|
1927
|
+
var ORDER_CONFIRMATION_STATUSES = ["unconfirmed", "confirmed"];
|
|
1928
|
+
var ORDER_PRIMARY_DISPLAY_STATUSES = [
|
|
1929
|
+
"pending",
|
|
1930
|
+
"paid",
|
|
1931
|
+
"canceled",
|
|
1932
|
+
"refunded",
|
|
1933
|
+
"preparing",
|
|
1934
|
+
"shipped",
|
|
1935
|
+
"delivered",
|
|
1936
|
+
"confirmed"
|
|
1937
|
+
];
|
|
1938
|
+
var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
|
|
1939
|
+
var ABANDONED_REASONS = ["expired", "customer", "operator"];
|
|
1940
|
+
var PAYMENT_PROVIDERS = ["toss"];
|
|
1941
|
+
var PAYMENT_PROVIDER_STATUSES = [
|
|
1942
|
+
"requires_payment_method",
|
|
1943
|
+
"requires_action",
|
|
1944
|
+
"requires_confirmation",
|
|
1945
|
+
"initializing",
|
|
1946
|
+
"processing",
|
|
1947
|
+
"authorized",
|
|
1948
|
+
"canceling",
|
|
1949
|
+
"unknown",
|
|
1950
|
+
"captured",
|
|
1951
|
+
"failed",
|
|
1952
|
+
"canceled"
|
|
1953
|
+
];
|
|
1954
|
+
var PAYMENT_FAILURE_REASONS = [
|
|
1955
|
+
"payment_declined",
|
|
1956
|
+
"authentication_failed",
|
|
1957
|
+
"authorization_expired",
|
|
1958
|
+
"payment_method_unavailable",
|
|
1959
|
+
"provider_terminal_failure",
|
|
1960
|
+
"unknown_provider_terminal_failure"
|
|
1961
|
+
];
|
|
1962
|
+
var CART_WARNING_CODES = [
|
|
1963
|
+
"DISCOUNT_CODE_NOT_HONOURED",
|
|
1964
|
+
"DISCOUNT_CURRENTLY_INACTIVE",
|
|
1965
|
+
"DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
|
|
1966
|
+
"DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
|
|
1967
|
+
"DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
|
|
1968
|
+
"DISCOUNT_NO_ENTITLED_LINE_ITEMS",
|
|
1969
|
+
"DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
|
|
1970
|
+
"DISCOUNT_NOT_FOUND",
|
|
1971
|
+
"DISCOUNT_PURCHASE_NOT_IN_RANGE",
|
|
1972
|
+
"DISCOUNT_USAGE_LIMIT_REACHED",
|
|
1973
|
+
"MERCHANDISE_NOT_ENOUGH_STOCK",
|
|
1974
|
+
"MERCHANDISE_OUT_OF_STOCK"
|
|
1975
|
+
];
|
|
1976
|
+
function invalidCanonicalResponse(resource, details) {
|
|
1977
|
+
throw createApiError(
|
|
1978
|
+
`Invalid canonical ${resource} response.`,
|
|
1979
|
+
502,
|
|
1980
|
+
{ resource, ...details },
|
|
1981
|
+
`The server returned an incompatible ${resource} response.`,
|
|
1982
|
+
"Verify that the Console commerce contract is deployed before using this SDK version."
|
|
1983
|
+
);
|
|
1984
|
+
}
|
|
1985
|
+
function fail(resource, path, expected) {
|
|
1986
|
+
invalidCanonicalResponse(resource, { path, expected });
|
|
1987
|
+
}
|
|
1988
|
+
function record(value, resource, path) {
|
|
1989
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1990
|
+
fail(resource, path, "object");
|
|
1991
|
+
}
|
|
1992
|
+
return value;
|
|
1993
|
+
}
|
|
1994
|
+
function exact(value, required, optional, resource, path) {
|
|
1995
|
+
for (const key of required) {
|
|
1996
|
+
if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
|
|
1997
|
+
}
|
|
1998
|
+
const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
|
|
1999
|
+
const unexpected = Object.keys(value).find((key) => !allowed.has(key));
|
|
2000
|
+
if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
|
|
2001
|
+
}
|
|
2002
|
+
function string(value, resource, path) {
|
|
2003
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2004
|
+
fail(resource, path, "non-empty string");
|
|
2005
|
+
}
|
|
2006
|
+
return value;
|
|
2007
|
+
}
|
|
2008
|
+
function boundedString(value, maxLength, resource, path, allowEmpty = false) {
|
|
2009
|
+
if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
|
|
2010
|
+
fail(
|
|
2011
|
+
resource,
|
|
2012
|
+
path,
|
|
2013
|
+
`${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
|
|
2014
|
+
);
|
|
2015
|
+
}
|
|
2016
|
+
return value;
|
|
2017
|
+
}
|
|
2018
|
+
function nullableString(value, resource, path) {
|
|
2019
|
+
if (value !== null && typeof value !== "string") {
|
|
2020
|
+
fail(resource, path, "string or null");
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
function cartLineQuantity(value, resource, path) {
|
|
2024
|
+
const quantity = positiveInteger(value, resource, path);
|
|
2025
|
+
if (quantity > MAX_CART_LINE_QUANTITY) {
|
|
2026
|
+
fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
|
|
2027
|
+
}
|
|
2028
|
+
return quantity;
|
|
2029
|
+
}
|
|
2030
|
+
function boolean(value, resource, path) {
|
|
2031
|
+
if (typeof value !== "boolean") fail(resource, path, "boolean");
|
|
2032
|
+
}
|
|
2033
|
+
function safeMinor(value, resource, path) {
|
|
2034
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
2035
|
+
fail(resource, path, "non-negative safe integer");
|
|
2036
|
+
}
|
|
2037
|
+
return value;
|
|
2038
|
+
}
|
|
2039
|
+
function positiveInteger(value, resource, path) {
|
|
2040
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
2041
|
+
fail(resource, path, "positive safe integer");
|
|
2042
|
+
}
|
|
2043
|
+
return value;
|
|
2044
|
+
}
|
|
2045
|
+
function enumValue(value, values, resource, path) {
|
|
2046
|
+
if (typeof value !== "string" || !values.includes(value)) {
|
|
2047
|
+
fail(resource, path, values.join(" | "));
|
|
2048
|
+
}
|
|
2049
|
+
return value;
|
|
2050
|
+
}
|
|
2051
|
+
function timestamp(value, resource, path) {
|
|
2052
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
|
|
2053
|
+
fail(resource, path, "ISO 8601 timestamp with offset");
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
function currency(value, resource, path) {
|
|
2057
|
+
if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
|
|
2058
|
+
fail(resource, path, "three-letter uppercase currency code");
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
function array(value, resource, path) {
|
|
2062
|
+
if (!Array.isArray(value)) fail(resource, path, "array");
|
|
2063
|
+
return value;
|
|
2064
|
+
}
|
|
2065
|
+
function optionalNullableNumber(value, resource, path) {
|
|
2066
|
+
if (value !== void 0 && value !== null && typeof value !== "number") {
|
|
2067
|
+
fail(resource, path, "number or null");
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
function validateMediaSize(value, resource, path) {
|
|
2071
|
+
const item = record(value, resource, path);
|
|
2072
|
+
exact(
|
|
2073
|
+
item,
|
|
2074
|
+
[],
|
|
2075
|
+
["width", "height", "mimeType", "filename", "url"],
|
|
2076
|
+
resource,
|
|
2077
|
+
path
|
|
2078
|
+
);
|
|
2079
|
+
optionalNullableNumber(item.width, resource, `${path}.width`);
|
|
2080
|
+
optionalNullableNumber(item.height, resource, `${path}.height`);
|
|
2081
|
+
for (const key of ["mimeType", "filename", "url"]) {
|
|
2082
|
+
if (item[key] !== void 0)
|
|
2083
|
+
nullableString(item[key], resource, `${path}.${key}`);
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
function validateMedia(value, resource, path) {
|
|
2087
|
+
if (typeof value === "string") return;
|
|
2088
|
+
const media = record(value, resource, path);
|
|
2089
|
+
exact(
|
|
2090
|
+
media,
|
|
2091
|
+
[],
|
|
2092
|
+
["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
|
|
2093
|
+
resource,
|
|
2094
|
+
path
|
|
2095
|
+
);
|
|
2096
|
+
if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
|
|
2097
|
+
fail(resource, `${path}.id`, "string, number, or null");
|
|
2098
|
+
}
|
|
2099
|
+
for (const key of ["alt", "mimeType", "filename", "url"]) {
|
|
2100
|
+
if (media[key] !== void 0)
|
|
2101
|
+
nullableString(media[key], resource, `${path}.${key}`);
|
|
2102
|
+
}
|
|
2103
|
+
optionalNullableNumber(media.width, resource, `${path}.width`);
|
|
2104
|
+
optionalNullableNumber(media.height, resource, `${path}.height`);
|
|
2105
|
+
if (media.sizes !== void 0) {
|
|
2106
|
+
const sizes = record(media.sizes, resource, `${path}.sizes`);
|
|
2107
|
+
Object.entries(sizes).forEach(
|
|
2108
|
+
([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
function validateReference(value, resource, path) {
|
|
2113
|
+
const ref = record(value, resource, path);
|
|
2114
|
+
exact(ref, ["id", "title", "handle", "image"], [], resource, path);
|
|
2115
|
+
string(ref.id, resource, `${path}.id`);
|
|
2116
|
+
string(ref.title, resource, `${path}.title`);
|
|
2117
|
+
if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
|
|
2118
|
+
if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
|
|
2119
|
+
}
|
|
2120
|
+
function validateAdmission(value, resource, path) {
|
|
2121
|
+
const admission = record(value, resource, path);
|
|
2122
|
+
exact(
|
|
2123
|
+
admission,
|
|
2124
|
+
["eventId", "occurrenceId", "admissionTypeId"],
|
|
2125
|
+
[],
|
|
2126
|
+
resource,
|
|
2127
|
+
path
|
|
2128
|
+
);
|
|
2129
|
+
string(admission.eventId, resource, `${path}.eventId`);
|
|
2130
|
+
string(admission.occurrenceId, resource, `${path}.occurrenceId`);
|
|
2131
|
+
string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
|
|
2132
|
+
}
|
|
2133
|
+
function compareAdmissions(left, right) {
|
|
2134
|
+
for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
|
|
2135
|
+
if (left[field] < right[field]) return -1;
|
|
2136
|
+
if (left[field] > right[field]) return 1;
|
|
2137
|
+
}
|
|
2138
|
+
return 0;
|
|
2139
|
+
}
|
|
2140
|
+
function validateAdmissions(value, resource, path) {
|
|
2141
|
+
const admissions = array(value, resource, path);
|
|
2142
|
+
if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
|
|
2143
|
+
let prior;
|
|
2144
|
+
admissions.forEach((admission, index) => {
|
|
2145
|
+
validateAdmission(admission, resource, `${path}[${index}]`);
|
|
2146
|
+
const item = admission;
|
|
2147
|
+
const comparison = prior ? compareAdmissions(item, prior) : void 0;
|
|
2148
|
+
if (comparison !== void 0 && comparison <= 0) {
|
|
2149
|
+
fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
|
|
2150
|
+
}
|
|
2151
|
+
prior = item;
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
function validateAttributes(value, resource, path) {
|
|
2155
|
+
const attributes = array(value, resource, path);
|
|
2156
|
+
if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
|
|
2157
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2158
|
+
attributes.forEach((value2, index) => {
|
|
2159
|
+
const itemPath = `${path}[${index}]`;
|
|
2160
|
+
const attribute = record(value2, resource, itemPath);
|
|
2161
|
+
exact(attribute, ["key", "value"], [], resource, itemPath);
|
|
2162
|
+
const key = string(attribute.key, resource, `${itemPath}.key`);
|
|
2163
|
+
if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
|
|
2164
|
+
fail(
|
|
2165
|
+
resource,
|
|
2166
|
+
`${itemPath}.key`,
|
|
2167
|
+
"unique, non-reserved key of at most 40 characters"
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
keys.add(key);
|
|
2171
|
+
if (typeof attribute.value !== "string" || attribute.value.length > 500) {
|
|
2172
|
+
fail(resource, `${itemPath}.value`, "string of at most 500 characters");
|
|
2173
|
+
}
|
|
2174
|
+
});
|
|
2175
|
+
}
|
|
2176
|
+
function validateCustomer(value, resource, path) {
|
|
2177
|
+
const customer = record(value, resource, path);
|
|
2178
|
+
exact(customer, ["email"], ["name", "phone"], resource, path);
|
|
2179
|
+
const email = boundedString(
|
|
2180
|
+
customer.email,
|
|
2181
|
+
MAX_COMMERCE_EMAIL_LENGTH,
|
|
2182
|
+
resource,
|
|
2183
|
+
`${path}.email`
|
|
2184
|
+
);
|
|
2185
|
+
if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
|
|
2186
|
+
email
|
|
2187
|
+
)) {
|
|
2188
|
+
fail(resource, `${path}.email`, "email address");
|
|
2189
|
+
}
|
|
2190
|
+
if (customer.name !== void 0)
|
|
2191
|
+
boundedString(
|
|
2192
|
+
customer.name,
|
|
2193
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
2194
|
+
resource,
|
|
2195
|
+
`${path}.name`
|
|
2196
|
+
);
|
|
2197
|
+
if (customer.phone !== void 0)
|
|
2198
|
+
boundedString(
|
|
2199
|
+
customer.phone,
|
|
2200
|
+
MAX_COMMERCE_PHONE_LENGTH,
|
|
2201
|
+
resource,
|
|
2202
|
+
`${path}.phone`
|
|
2203
|
+
);
|
|
2204
|
+
}
|
|
2205
|
+
function validateShippingAddress(value, resource, path) {
|
|
2206
|
+
const address = record(value, resource, path);
|
|
2207
|
+
exact(
|
|
2208
|
+
address,
|
|
2209
|
+
["recipientName", "phone", "postalCode", "address", "detailAddress"],
|
|
2210
|
+
["countryCode", "regionCode", "deliveryMessage"],
|
|
2211
|
+
resource,
|
|
2212
|
+
path
|
|
2213
|
+
);
|
|
2214
|
+
boundedString(
|
|
2215
|
+
address.recipientName,
|
|
2216
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
2217
|
+
resource,
|
|
2218
|
+
`${path}.recipientName`
|
|
2219
|
+
);
|
|
2220
|
+
boundedString(
|
|
2221
|
+
address.phone,
|
|
2222
|
+
MAX_COMMERCE_PHONE_LENGTH,
|
|
2223
|
+
resource,
|
|
2224
|
+
`${path}.phone`
|
|
2225
|
+
);
|
|
2226
|
+
boundedString(
|
|
2227
|
+
address.postalCode,
|
|
2228
|
+
MAX_COMMERCE_POSTAL_CODE_LENGTH,
|
|
2229
|
+
resource,
|
|
2230
|
+
`${path}.postalCode`
|
|
2231
|
+
);
|
|
2232
|
+
for (const key of ["address", "detailAddress"]) {
|
|
2233
|
+
boundedString(
|
|
2234
|
+
address[key],
|
|
2235
|
+
MAX_COMMERCE_ADDRESS_LENGTH,
|
|
2236
|
+
resource,
|
|
2237
|
+
`${path}.${key}`
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
if (address.countryCode !== void 0) {
|
|
2241
|
+
if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
|
|
2242
|
+
fail(resource, `${path}.countryCode`, "two-letter country code");
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
if (address.regionCode !== void 0) {
|
|
2246
|
+
if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
|
|
2247
|
+
fail(
|
|
2248
|
+
resource,
|
|
2249
|
+
`${path}.regionCode`,
|
|
2250
|
+
"trimmed string of at most 64 characters"
|
|
2251
|
+
);
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
if (address.deliveryMessage !== void 0) {
|
|
2255
|
+
boundedString(
|
|
2256
|
+
address.deliveryMessage,
|
|
2257
|
+
MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
|
|
2258
|
+
resource,
|
|
2259
|
+
`${path}.deliveryMessage`,
|
|
2260
|
+
true
|
|
2261
|
+
);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
function validateOrderReference(value, resource, path) {
|
|
2265
|
+
const order = record(value, resource, path);
|
|
2266
|
+
exact(order, ["id", "orderNumber"], [], resource, path);
|
|
2267
|
+
string(order.id, resource, `${path}.id`);
|
|
2268
|
+
string(order.orderNumber, resource, `${path}.orderNumber`);
|
|
2269
|
+
}
|
|
2270
|
+
function validateIntegrationMetadata(value, resource, path) {
|
|
2271
|
+
const metadata = record(value, resource, path);
|
|
2272
|
+
if (Object.keys(metadata).length > 50)
|
|
2273
|
+
fail(resource, path, "at most 50 entries");
|
|
2274
|
+
Object.entries(metadata).forEach(([key, entry]) => {
|
|
2275
|
+
if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
|
|
2276
|
+
fail(resource, `${path}.${key}`, "valid metadata key");
|
|
2277
|
+
}
|
|
2278
|
+
if (typeof entry !== "string" || entry.length > 500) {
|
|
2279
|
+
fail(resource, `${path}.${key}`, "string of at most 500 characters");
|
|
2280
|
+
}
|
|
2281
|
+
});
|
|
2282
|
+
}
|
|
2283
|
+
function validateCartItem(value, resource, path) {
|
|
2284
|
+
const item = record(value, resource, path);
|
|
2285
|
+
exact(
|
|
2286
|
+
item,
|
|
2287
|
+
[
|
|
2288
|
+
"id",
|
|
2289
|
+
"product",
|
|
2290
|
+
"variant",
|
|
2291
|
+
"admissions",
|
|
2292
|
+
"quantity",
|
|
2293
|
+
"unitPriceMinor",
|
|
2294
|
+
"discountMinor",
|
|
2295
|
+
"estimatedLineTotalMinor",
|
|
2296
|
+
"requiresShipping"
|
|
2297
|
+
],
|
|
2298
|
+
[],
|
|
2299
|
+
resource,
|
|
2300
|
+
path
|
|
2301
|
+
);
|
|
2302
|
+
string(item.id, resource, `${path}.id`);
|
|
2303
|
+
validateReference(item.product, resource, `${path}.product`);
|
|
2304
|
+
validateReference(item.variant, resource, `${path}.variant`);
|
|
2305
|
+
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2306
|
+
cartLineQuantity(item.quantity, resource, `${path}.quantity`);
|
|
2307
|
+
const unitPrice = safeMinor(
|
|
2308
|
+
item.unitPriceMinor,
|
|
2309
|
+
resource,
|
|
2310
|
+
`${path}.unitPriceMinor`
|
|
2311
|
+
);
|
|
2312
|
+
const discount = safeMinor(
|
|
2313
|
+
item.discountMinor,
|
|
2314
|
+
resource,
|
|
2315
|
+
`${path}.discountMinor`
|
|
2316
|
+
);
|
|
2317
|
+
const estimatedLineTotal = safeMinor(
|
|
2318
|
+
item.estimatedLineTotalMinor,
|
|
2319
|
+
resource,
|
|
2320
|
+
`${path}.estimatedLineTotalMinor`
|
|
2321
|
+
);
|
|
2322
|
+
const quantity = item.quantity;
|
|
2323
|
+
const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
|
|
2324
|
+
if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
|
|
2325
|
+
fail(
|
|
2326
|
+
resource,
|
|
2327
|
+
`${path}.estimatedLineTotalMinor`,
|
|
2328
|
+
"unitPriceMinor * quantity - discountMinor"
|
|
2329
|
+
);
|
|
2330
|
+
}
|
|
2331
|
+
boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
|
|
2332
|
+
}
|
|
2333
|
+
function validatePublicCart(value, resource = "Cart") {
|
|
2334
|
+
const cart = record(value, resource, "$");
|
|
2335
|
+
exact(
|
|
2336
|
+
cart,
|
|
2337
|
+
[
|
|
2338
|
+
"id",
|
|
2339
|
+
"status",
|
|
2340
|
+
"revision",
|
|
2341
|
+
"currency",
|
|
2342
|
+
"market",
|
|
2343
|
+
"subtotalMinor",
|
|
2344
|
+
"discountMinor",
|
|
2345
|
+
"estimatedTotalMinor",
|
|
2346
|
+
"discountCodes",
|
|
2347
|
+
"attributes",
|
|
2348
|
+
"items",
|
|
2349
|
+
"expiresAt",
|
|
2350
|
+
"createdAt",
|
|
2351
|
+
"updatedAt"
|
|
2352
|
+
],
|
|
2353
|
+
[],
|
|
2354
|
+
resource,
|
|
2355
|
+
"$"
|
|
2356
|
+
);
|
|
2357
|
+
string(cart.id, resource, "$.id");
|
|
2358
|
+
enumValue(cart.status, CART_STATUSES, resource, "$.status");
|
|
2359
|
+
safeMinor(cart.revision, resource, "$.revision");
|
|
2360
|
+
currency(cart.currency, resource, "$.currency");
|
|
2361
|
+
const market = record(cart.market, resource, "$.market");
|
|
2362
|
+
exact(market, ["id", "handle", "name"], [], resource, "$.market");
|
|
2363
|
+
for (const key of ["id", "handle", "name"])
|
|
2364
|
+
string(market[key], resource, `$.market.${key}`);
|
|
2365
|
+
const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
|
|
2366
|
+
const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
|
|
2367
|
+
const estimatedTotal = safeMinor(
|
|
2368
|
+
cart.estimatedTotalMinor,
|
|
2369
|
+
resource,
|
|
2370
|
+
"$.estimatedTotalMinor"
|
|
2371
|
+
);
|
|
2372
|
+
array(cart.discountCodes, resource, "$.discountCodes").forEach(
|
|
2373
|
+
(value2, index) => {
|
|
2374
|
+
const itemPath = `$.discountCodes[${index}]`;
|
|
2375
|
+
const code = record(value2, resource, itemPath);
|
|
2376
|
+
exact(code, ["code", "applicable"], [], resource, itemPath);
|
|
2377
|
+
boundedString(
|
|
2378
|
+
code.code,
|
|
2379
|
+
MAX_CART_DISCOUNT_CODE_LENGTH,
|
|
2380
|
+
resource,
|
|
2381
|
+
`${itemPath}.code`
|
|
2382
|
+
);
|
|
2383
|
+
boolean(code.applicable, resource, `${itemPath}.applicable`);
|
|
2384
|
+
}
|
|
2385
|
+
);
|
|
2386
|
+
validateAttributes(cart.attributes, resource, "$.attributes");
|
|
2387
|
+
const items = array(cart.items, resource, "$.items");
|
|
2388
|
+
items.forEach(
|
|
2389
|
+
(item, index) => validateCartItem(item, resource, `$.items[${index}]`)
|
|
2390
|
+
);
|
|
2391
|
+
const expectedSubtotal = items.reduce((total, value2) => {
|
|
2392
|
+
const item = value2;
|
|
2393
|
+
return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
|
|
2394
|
+
}, 0n);
|
|
2395
|
+
const expectedDiscount = items.reduce((total, value2) => {
|
|
2396
|
+
const item = value2;
|
|
2397
|
+
return total + BigInt(item.discountMinor);
|
|
2398
|
+
}, 0n);
|
|
2399
|
+
if (BigInt(subtotal) !== expectedSubtotal) {
|
|
2400
|
+
fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
|
|
2401
|
+
}
|
|
2402
|
+
if (BigInt(discount) !== expectedDiscount) {
|
|
2403
|
+
fail(resource, "$.discountMinor", "sum of cart line discounts");
|
|
2404
|
+
}
|
|
2405
|
+
if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
|
|
2406
|
+
fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
|
|
2407
|
+
}
|
|
2408
|
+
timestamp(cart.expiresAt, resource, "$.expiresAt");
|
|
2409
|
+
timestamp(cart.createdAt, resource, "$.createdAt");
|
|
2410
|
+
timestamp(cart.updatedAt, resource, "$.updatedAt");
|
|
2411
|
+
return value;
|
|
2412
|
+
}
|
|
2413
|
+
function validateWarnings(value, resource, path) {
|
|
2414
|
+
array(value, resource, path).forEach((value2, index) => {
|
|
2415
|
+
const itemPath = `${path}[${index}]`;
|
|
2416
|
+
const warning = record(value2, resource, itemPath);
|
|
2417
|
+
exact(warning, ["code", "message", "target"], [], resource, itemPath);
|
|
2418
|
+
enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
|
|
2419
|
+
string(warning.message, resource, `${itemPath}.message`);
|
|
2420
|
+
string(warning.target, resource, `${itemPath}.target`);
|
|
2421
|
+
});
|
|
2422
|
+
}
|
|
2423
|
+
function validateCartMutationResult(value) {
|
|
2424
|
+
const result = record(value, "Cart mutation result", "$");
|
|
2425
|
+
exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
|
|
2426
|
+
validatePublicCart(result.cart);
|
|
2427
|
+
validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
|
|
2428
|
+
return value;
|
|
2429
|
+
}
|
|
2430
|
+
function validateCreateCartResult(value) {
|
|
2431
|
+
const result = record(value, "Cart create result", "$");
|
|
2432
|
+
exact(
|
|
2433
|
+
result,
|
|
2434
|
+
["cart", "warnings", "cartToken"],
|
|
2435
|
+
[],
|
|
2436
|
+
"Cart create result",
|
|
2437
|
+
"$"
|
|
2438
|
+
);
|
|
2439
|
+
const cart = record(result.cart, "Cart create result", "$.cart");
|
|
2440
|
+
validatePublicCart(cart);
|
|
2441
|
+
if (cart.revision !== 0) {
|
|
2442
|
+
fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
|
|
2443
|
+
}
|
|
2444
|
+
validateWarnings(result.warnings, "Cart create result", "$.warnings");
|
|
2445
|
+
boundedString(
|
|
2446
|
+
result.cartToken,
|
|
2447
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
2448
|
+
"Cart create result",
|
|
2449
|
+
"$.cartToken"
|
|
2450
|
+
);
|
|
2451
|
+
return value;
|
|
2452
|
+
}
|
|
2453
|
+
function validateCartMineResult(value) {
|
|
2454
|
+
const result = record(value, "Cart mine result", "$");
|
|
2455
|
+
exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
|
|
2456
|
+
if (result.cart === null || result.cartToken === null) {
|
|
2457
|
+
if (result.cart !== null || result.cartToken !== null) {
|
|
2458
|
+
fail("Cart mine result", "$", "cart and cartToken must both be null");
|
|
2459
|
+
}
|
|
2460
|
+
} else {
|
|
2461
|
+
validatePublicCart(result.cart);
|
|
2462
|
+
boundedString(
|
|
2463
|
+
result.cartToken,
|
|
2464
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
2465
|
+
"Cart mine result",
|
|
2466
|
+
"$.cartToken"
|
|
2467
|
+
);
|
|
2468
|
+
}
|
|
2469
|
+
return value;
|
|
2470
|
+
}
|
|
2471
|
+
function validateCartMergeResult(value) {
|
|
2472
|
+
const result = record(value, "Cart merge result", "$");
|
|
2473
|
+
exact(
|
|
2474
|
+
result,
|
|
2475
|
+
["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
|
|
2476
|
+
[],
|
|
2477
|
+
"Cart merge result",
|
|
2478
|
+
"$"
|
|
2479
|
+
);
|
|
2480
|
+
validatePublicCart(result.cart);
|
|
2481
|
+
validateWarnings(result.warnings, "Cart merge result", "$.warnings");
|
|
2482
|
+
boundedString(
|
|
2483
|
+
result.cartToken,
|
|
2484
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
2485
|
+
"Cart merge result",
|
|
2486
|
+
"$.cartToken"
|
|
2487
|
+
);
|
|
2488
|
+
const resolution = enumValue(
|
|
2489
|
+
result.resolution,
|
|
2490
|
+
["unchanged", "claimed", "merged"],
|
|
2491
|
+
"Cart merge result",
|
|
2492
|
+
"$.resolution"
|
|
2493
|
+
);
|
|
2494
|
+
boolean(result.merged, "Cart merge result", "$.merged");
|
|
2495
|
+
boolean(result.claimed, "Cart merge result", "$.claimed");
|
|
2496
|
+
const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
|
|
2497
|
+
if (result.merged !== expected[0] || result.claimed !== expected[1]) {
|
|
2498
|
+
fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
|
|
2499
|
+
}
|
|
2500
|
+
return value;
|
|
2501
|
+
}
|
|
2502
|
+
function validatePublicOrderItem(value, resource, path) {
|
|
2503
|
+
const item = record(value, resource, path);
|
|
2504
|
+
exact(
|
|
2505
|
+
item,
|
|
2506
|
+
[
|
|
2507
|
+
"id",
|
|
2508
|
+
"product",
|
|
2509
|
+
"variant",
|
|
2510
|
+
"productTitle",
|
|
2511
|
+
"variantTitle",
|
|
2512
|
+
"sku",
|
|
2513
|
+
"admissions",
|
|
2514
|
+
"quantity",
|
|
2515
|
+
"unitPriceMinor",
|
|
2516
|
+
"discountMinor",
|
|
2517
|
+
"lineTotalMinor",
|
|
2518
|
+
"requiresShipping"
|
|
2519
|
+
],
|
|
2520
|
+
[],
|
|
2521
|
+
resource,
|
|
2522
|
+
path
|
|
2523
|
+
);
|
|
2524
|
+
string(item.id, resource, `${path}.id`);
|
|
2525
|
+
if (item.product !== null) {
|
|
2526
|
+
validateReference(item.product, resource, `${path}.product`);
|
|
2527
|
+
}
|
|
2528
|
+
if (item.variant !== null) {
|
|
2529
|
+
validateReference(item.variant, resource, `${path}.variant`);
|
|
2530
|
+
}
|
|
2531
|
+
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2532
|
+
nullableString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
2533
|
+
nullableString(item.sku, resource, `${path}.sku`);
|
|
2534
|
+
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2535
|
+
const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
|
|
2536
|
+
const unitPrice = safeMinor(
|
|
2537
|
+
item.unitPriceMinor,
|
|
2538
|
+
resource,
|
|
2539
|
+
`${path}.unitPriceMinor`
|
|
2540
|
+
);
|
|
2541
|
+
const discount = safeMinor(
|
|
2542
|
+
item.discountMinor,
|
|
2543
|
+
resource,
|
|
2544
|
+
`${path}.discountMinor`
|
|
2545
|
+
);
|
|
2546
|
+
const lineTotal = safeMinor(
|
|
2547
|
+
item.lineTotalMinor,
|
|
2548
|
+
resource,
|
|
2549
|
+
`${path}.lineTotalMinor`
|
|
2550
|
+
);
|
|
2551
|
+
const expected = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
|
|
2552
|
+
if (expected < 0n || BigInt(lineTotal) !== expected) {
|
|
2553
|
+
fail(
|
|
2554
|
+
resource,
|
|
2555
|
+
`${path}.lineTotalMinor`,
|
|
2556
|
+
"unitPriceMinor * quantity - discountMinor"
|
|
2557
|
+
);
|
|
2558
|
+
}
|
|
2559
|
+
boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
|
|
2560
|
+
}
|
|
2561
|
+
function validatePublicOrderAt(value, resource, path) {
|
|
2562
|
+
const order = record(value, resource, path);
|
|
2563
|
+
exact(
|
|
2564
|
+
order,
|
|
2565
|
+
[
|
|
2566
|
+
"id",
|
|
2567
|
+
"orderNumber",
|
|
2568
|
+
"amounts",
|
|
2569
|
+
"market",
|
|
2570
|
+
"customerSnapshot",
|
|
2571
|
+
"shippingAddress",
|
|
2572
|
+
"attributes",
|
|
2573
|
+
"items",
|
|
2574
|
+
"financialStatus",
|
|
2575
|
+
"fulfillmentStatus",
|
|
2576
|
+
"returnStatus",
|
|
2577
|
+
"confirmationStatus",
|
|
2578
|
+
"primaryDisplayStatus",
|
|
2579
|
+
"placedAt",
|
|
2580
|
+
"createdAt",
|
|
2581
|
+
"updatedAt"
|
|
2582
|
+
],
|
|
2583
|
+
[],
|
|
2584
|
+
resource,
|
|
2585
|
+
path
|
|
2586
|
+
);
|
|
2587
|
+
string(order.id, resource, `${path}.id`);
|
|
2588
|
+
string(order.orderNumber, resource, `${path}.orderNumber`);
|
|
2589
|
+
const amounts = record(order.amounts, resource, `${path}.amounts`);
|
|
2590
|
+
exact(
|
|
2591
|
+
amounts,
|
|
2592
|
+
[
|
|
2593
|
+
"currency",
|
|
2594
|
+
"subtotalMinor",
|
|
2595
|
+
"shippingMinor",
|
|
2596
|
+
"discountMinor",
|
|
2597
|
+
"totalMinor",
|
|
2598
|
+
"refundedMinor",
|
|
2599
|
+
"currentTotalMinor"
|
|
2600
|
+
],
|
|
2601
|
+
[],
|
|
2602
|
+
resource,
|
|
2603
|
+
`${path}.amounts`
|
|
2604
|
+
);
|
|
2605
|
+
currency(amounts.currency, resource, `${path}.amounts.currency`);
|
|
2606
|
+
const subtotal = safeMinor(
|
|
2607
|
+
amounts.subtotalMinor,
|
|
2608
|
+
resource,
|
|
2609
|
+
`${path}.amounts.subtotalMinor`
|
|
2610
|
+
);
|
|
2611
|
+
const shipping = safeMinor(
|
|
2612
|
+
amounts.shippingMinor,
|
|
2613
|
+
resource,
|
|
2614
|
+
`${path}.amounts.shippingMinor`
|
|
2615
|
+
);
|
|
2616
|
+
const discount = safeMinor(
|
|
2617
|
+
amounts.discountMinor,
|
|
2618
|
+
resource,
|
|
2619
|
+
`${path}.amounts.discountMinor`
|
|
2620
|
+
);
|
|
2621
|
+
const total = safeMinor(
|
|
2622
|
+
amounts.totalMinor,
|
|
2623
|
+
resource,
|
|
2624
|
+
`${path}.amounts.totalMinor`
|
|
2625
|
+
);
|
|
2626
|
+
const refunded = safeMinor(
|
|
2627
|
+
amounts.refundedMinor,
|
|
2628
|
+
resource,
|
|
2629
|
+
`${path}.amounts.refundedMinor`
|
|
2630
|
+
);
|
|
2631
|
+
const current = safeMinor(
|
|
2632
|
+
amounts.currentTotalMinor,
|
|
2633
|
+
resource,
|
|
2634
|
+
`${path}.amounts.currentTotalMinor`
|
|
2635
|
+
);
|
|
2636
|
+
const expectedTotal = BigInt(subtotal) + BigInt(shipping) - BigInt(discount);
|
|
2637
|
+
if (expectedTotal < 0n || BigInt(total) !== expectedTotal) {
|
|
2638
|
+
fail(
|
|
2639
|
+
resource,
|
|
2640
|
+
`${path}.amounts.totalMinor`,
|
|
2641
|
+
"subtotalMinor + shippingMinor - discountMinor"
|
|
2642
|
+
);
|
|
2643
|
+
}
|
|
2644
|
+
if (BigInt(total) - BigInt(refunded) < 0n || current !== total - refunded) {
|
|
2645
|
+
fail(
|
|
2646
|
+
resource,
|
|
2647
|
+
`${path}.amounts.currentTotalMinor`,
|
|
2648
|
+
"totalMinor - refundedMinor"
|
|
2649
|
+
);
|
|
2650
|
+
}
|
|
2651
|
+
if (order.market !== null) {
|
|
2652
|
+
const market = record(order.market, resource, `${path}.market`);
|
|
2653
|
+
exact(market, ["id", "handle", "name"], [], resource, `${path}.market`);
|
|
2654
|
+
for (const key of ["id", "handle", "name"]) {
|
|
2655
|
+
string(market[key], resource, `${path}.market.${key}`);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
validateCustomer(order.customerSnapshot, resource, `${path}.customerSnapshot`);
|
|
2659
|
+
if (order.shippingAddress !== null) {
|
|
2660
|
+
validateShippingAddress(
|
|
2661
|
+
order.shippingAddress,
|
|
2662
|
+
resource,
|
|
2663
|
+
`${path}.shippingAddress`
|
|
2664
|
+
);
|
|
2665
|
+
}
|
|
2666
|
+
validateAttributes(order.attributes, resource, `${path}.attributes`);
|
|
2667
|
+
const items = array(order.items, resource, `${path}.items`);
|
|
2668
|
+
if (items.length === 0) fail(resource, `${path}.items`, "non-empty array");
|
|
2669
|
+
items.forEach(
|
|
2670
|
+
(item, index) => validatePublicOrderItem(item, resource, `${path}.items[${index}]`)
|
|
2671
|
+
);
|
|
2672
|
+
const expectedSubtotal = items.reduce((sum, value2) => {
|
|
2673
|
+
const item = value2;
|
|
2674
|
+
return sum + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
|
|
2675
|
+
}, 0n);
|
|
2676
|
+
const expectedDiscount = items.reduce((sum, value2) => {
|
|
2677
|
+
const item = value2;
|
|
2678
|
+
return sum + BigInt(item.discountMinor);
|
|
2679
|
+
}, 0n);
|
|
2680
|
+
if (BigInt(subtotal) !== expectedSubtotal) {
|
|
2681
|
+
fail(resource, `${path}.amounts.subtotalMinor`, "sum of line subtotals");
|
|
2682
|
+
}
|
|
2683
|
+
if (BigInt(discount) !== expectedDiscount) {
|
|
2684
|
+
fail(resource, `${path}.amounts.discountMinor`, "sum of line discounts");
|
|
2685
|
+
}
|
|
2686
|
+
enumValue(
|
|
2687
|
+
order.financialStatus,
|
|
2688
|
+
ORDER_FINANCIAL_STATUSES,
|
|
2689
|
+
resource,
|
|
2690
|
+
`${path}.financialStatus`
|
|
2691
|
+
);
|
|
2692
|
+
enumValue(
|
|
2693
|
+
order.fulfillmentStatus,
|
|
2694
|
+
ORDER_FULFILLMENT_STATUSES,
|
|
2695
|
+
resource,
|
|
2696
|
+
`${path}.fulfillmentStatus`
|
|
2697
|
+
);
|
|
2698
|
+
enumValue(
|
|
2699
|
+
order.returnStatus,
|
|
2700
|
+
ORDER_RETURN_STATUSES,
|
|
2701
|
+
resource,
|
|
2702
|
+
`${path}.returnStatus`
|
|
2703
|
+
);
|
|
2704
|
+
enumValue(
|
|
2705
|
+
order.confirmationStatus,
|
|
2706
|
+
ORDER_CONFIRMATION_STATUSES,
|
|
2707
|
+
resource,
|
|
2708
|
+
`${path}.confirmationStatus`
|
|
2709
|
+
);
|
|
2710
|
+
enumValue(
|
|
2711
|
+
order.primaryDisplayStatus,
|
|
2712
|
+
ORDER_PRIMARY_DISPLAY_STATUSES,
|
|
2713
|
+
resource,
|
|
2714
|
+
`${path}.primaryDisplayStatus`
|
|
2715
|
+
);
|
|
2716
|
+
timestamp(order.placedAt, resource, `${path}.placedAt`);
|
|
2717
|
+
timestamp(order.createdAt, resource, `${path}.createdAt`);
|
|
2718
|
+
timestamp(order.updatedAt, resource, `${path}.updatedAt`);
|
|
2719
|
+
}
|
|
2720
|
+
function nullablePositiveInteger(value, resource, path) {
|
|
2721
|
+
if (value !== null) positiveInteger(value, resource, path);
|
|
2722
|
+
}
|
|
2723
|
+
function validatePublicOrderList(value) {
|
|
2724
|
+
const resource = "Order list";
|
|
2725
|
+
const result = record(value, resource, "$");
|
|
2726
|
+
exact(
|
|
2727
|
+
result,
|
|
2728
|
+
[
|
|
2729
|
+
"docs",
|
|
2730
|
+
"totalDocs",
|
|
2731
|
+
"limit",
|
|
2732
|
+
"totalPages",
|
|
2733
|
+
"page",
|
|
2734
|
+
"pagingCounter",
|
|
2735
|
+
"hasPrevPage",
|
|
2736
|
+
"hasNextPage",
|
|
2737
|
+
"prevPage",
|
|
2738
|
+
"nextPage"
|
|
2739
|
+
],
|
|
2740
|
+
[],
|
|
2741
|
+
resource,
|
|
2742
|
+
"$"
|
|
2743
|
+
);
|
|
2744
|
+
array(result.docs, resource, "$.docs").forEach(
|
|
2745
|
+
(order, index) => validatePublicOrderAt(order, resource, `$.docs[${index}]`)
|
|
2746
|
+
);
|
|
2747
|
+
safeMinor(result.totalDocs, resource, "$.totalDocs");
|
|
2748
|
+
positiveInteger(result.limit, resource, "$.limit");
|
|
2749
|
+
safeMinor(result.totalPages, resource, "$.totalPages");
|
|
2750
|
+
positiveInteger(result.page, resource, "$.page");
|
|
2751
|
+
positiveInteger(result.pagingCounter, resource, "$.pagingCounter");
|
|
2752
|
+
boolean(result.hasPrevPage, resource, "$.hasPrevPage");
|
|
2753
|
+
boolean(result.hasNextPage, resource, "$.hasNextPage");
|
|
2754
|
+
nullablePositiveInteger(result.prevPage, resource, "$.prevPage");
|
|
2755
|
+
nullablePositiveInteger(result.nextPage, resource, "$.nextPage");
|
|
2756
|
+
return value;
|
|
2757
|
+
}
|
|
2758
|
+
function validateCheckoutItem(value, resource, path) {
|
|
2759
|
+
const item = record(value, resource, path);
|
|
2760
|
+
exact(
|
|
2761
|
+
item,
|
|
2762
|
+
[
|
|
2763
|
+
"id",
|
|
2764
|
+
"product",
|
|
2765
|
+
"variant",
|
|
2766
|
+
"productTitle",
|
|
2767
|
+
"variantTitle",
|
|
2768
|
+
"sku",
|
|
2769
|
+
"admissions",
|
|
2770
|
+
"quantity",
|
|
2771
|
+
"unitPriceMinor",
|
|
2772
|
+
"discountMinor",
|
|
2773
|
+
"lineTotalMinor",
|
|
2774
|
+
"requiresShipping"
|
|
2775
|
+
],
|
|
2776
|
+
[],
|
|
2777
|
+
resource,
|
|
2778
|
+
path
|
|
2779
|
+
);
|
|
2780
|
+
string(item.id, resource, `${path}.id`);
|
|
2781
|
+
validateReference(item.product, resource, `${path}.product`);
|
|
2782
|
+
validateReference(item.variant, resource, `${path}.variant`);
|
|
2783
|
+
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2784
|
+
nullableString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
2785
|
+
nullableString(item.sku, resource, `${path}.sku`);
|
|
2786
|
+
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2787
|
+
cartLineQuantity(item.quantity, resource, `${path}.quantity`);
|
|
2788
|
+
const unitPrice = safeMinor(
|
|
2789
|
+
item.unitPriceMinor,
|
|
2790
|
+
resource,
|
|
2791
|
+
`${path}.unitPriceMinor`
|
|
2792
|
+
);
|
|
2793
|
+
const discount = safeMinor(
|
|
2794
|
+
item.discountMinor,
|
|
2795
|
+
resource,
|
|
2796
|
+
`${path}.discountMinor`
|
|
2797
|
+
);
|
|
2798
|
+
const lineTotal = safeMinor(
|
|
2799
|
+
item.lineTotalMinor,
|
|
2800
|
+
resource,
|
|
2801
|
+
`${path}.lineTotalMinor`
|
|
2802
|
+
);
|
|
2803
|
+
const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
|
|
2804
|
+
if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
|
|
2805
|
+
fail(
|
|
2806
|
+
resource,
|
|
2807
|
+
`${path}.lineTotalMinor`,
|
|
2808
|
+
"unitPriceMinor * quantity - discountMinor"
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
|
|
2812
|
+
}
|
|
2813
|
+
function validateCheckoutAmounts(value, resource, path) {
|
|
2814
|
+
const amounts = record(value, resource, path);
|
|
2815
|
+
exact(
|
|
2816
|
+
amounts,
|
|
2817
|
+
[
|
|
2818
|
+
"currency",
|
|
2819
|
+
"subtotalMinor",
|
|
2820
|
+
"shippingMinor",
|
|
2821
|
+
"discountMinor",
|
|
2822
|
+
"totalMinor"
|
|
2823
|
+
],
|
|
2824
|
+
[],
|
|
2825
|
+
resource,
|
|
2826
|
+
path
|
|
2827
|
+
);
|
|
2828
|
+
currency(amounts.currency, resource, `${path}.currency`);
|
|
2829
|
+
const subtotal = safeMinor(
|
|
2830
|
+
amounts.subtotalMinor,
|
|
2831
|
+
resource,
|
|
2832
|
+
`${path}.subtotalMinor`
|
|
2833
|
+
);
|
|
2834
|
+
const shipping = safeMinor(
|
|
2835
|
+
amounts.shippingMinor,
|
|
2836
|
+
resource,
|
|
2837
|
+
`${path}.shippingMinor`
|
|
2838
|
+
);
|
|
2839
|
+
const discount = safeMinor(
|
|
2840
|
+
amounts.discountMinor,
|
|
2841
|
+
resource,
|
|
2842
|
+
`${path}.discountMinor`
|
|
2843
|
+
);
|
|
2844
|
+
const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
|
|
2845
|
+
if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
|
|
2846
|
+
fail(
|
|
2847
|
+
resource,
|
|
2848
|
+
`${path}.totalMinor`,
|
|
2849
|
+
"subtotalMinor + shippingMinor - discountMinor"
|
|
2850
|
+
);
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
function validatePaymentSessionReference(value, resource, path) {
|
|
2854
|
+
const session = record(value, resource, path);
|
|
2855
|
+
exact(session, ["id", "provider", "providerStatus"], [], resource, path);
|
|
2856
|
+
string(session.id, resource, `${path}.id`);
|
|
2857
|
+
enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
|
|
2858
|
+
enumValue(
|
|
2859
|
+
session.providerStatus,
|
|
2860
|
+
PAYMENT_PROVIDER_STATUSES,
|
|
2861
|
+
resource,
|
|
2862
|
+
`${path}.providerStatus`
|
|
2863
|
+
);
|
|
2864
|
+
}
|
|
2865
|
+
function checkoutVariantKeys(status, placedVia) {
|
|
2866
|
+
const base = [
|
|
2867
|
+
"id",
|
|
2868
|
+
"amounts",
|
|
2869
|
+
"items",
|
|
2870
|
+
"customerSnapshot",
|
|
2871
|
+
"shippingAddress",
|
|
2872
|
+
"attributes",
|
|
2873
|
+
"expiresAt",
|
|
2874
|
+
"createdAt",
|
|
2875
|
+
"updatedAt",
|
|
2876
|
+
"status",
|
|
2877
|
+
"paymentState",
|
|
2878
|
+
"order"
|
|
2879
|
+
];
|
|
2880
|
+
if (status === "open") return { required: base, optional: [] };
|
|
2881
|
+
if (status === "abandoned") {
|
|
2882
|
+
return {
|
|
2883
|
+
required: [...base, "abandonedAt", "abandonedReason"],
|
|
2884
|
+
optional: []
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
return placedVia === "late_capture" ? {
|
|
2888
|
+
required: [
|
|
2889
|
+
...base,
|
|
2890
|
+
"placedAt",
|
|
2891
|
+
"placedVia",
|
|
2892
|
+
"abandonedAt",
|
|
2893
|
+
"abandonedReason"
|
|
2894
|
+
],
|
|
2895
|
+
optional: []
|
|
2896
|
+
} : { required: [...base, "placedAt"], optional: [] };
|
|
2897
|
+
}
|
|
2898
|
+
function validateCheckoutCore(value, resource, list, server) {
|
|
2899
|
+
const checkout = record(value, resource, "$");
|
|
2900
|
+
const status = enumValue(
|
|
2901
|
+
checkout.status,
|
|
2902
|
+
CHECKOUT_STATUSES,
|
|
2903
|
+
resource,
|
|
2904
|
+
"$.status"
|
|
2905
|
+
);
|
|
2906
|
+
const keys = checkoutVariantKeys(status, checkout.placedVia);
|
|
2907
|
+
if (list) {
|
|
2908
|
+
keys.required = keys.required.filter(
|
|
2909
|
+
(key) => !["items", "shippingAddress", "attributes"].includes(key)
|
|
2910
|
+
);
|
|
2911
|
+
keys.required.push("clientReferenceId");
|
|
2912
|
+
} else if (server) {
|
|
2913
|
+
keys.required.push("clientReferenceId", "integrationMetadata");
|
|
2914
|
+
}
|
|
2915
|
+
exact(checkout, keys.required, keys.optional, resource, "$");
|
|
2916
|
+
string(checkout.id, resource, "$.id");
|
|
2917
|
+
validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
|
|
2918
|
+
if (!list) {
|
|
2919
|
+
const items = array(checkout.items, resource, "$.items");
|
|
2920
|
+
if (items.length === 0) fail(resource, "$.items", "non-empty array");
|
|
2921
|
+
items.forEach(
|
|
2922
|
+
(item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
|
|
2923
|
+
);
|
|
2924
|
+
const expectedSubtotal = items.reduce((total, value2) => {
|
|
2925
|
+
const item = value2;
|
|
2926
|
+
return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
|
|
2927
|
+
}, 0n);
|
|
2928
|
+
const expectedDiscount = items.reduce((total, value2) => {
|
|
2929
|
+
const item = value2;
|
|
2930
|
+
return total + BigInt(item.discountMinor);
|
|
2931
|
+
}, 0n);
|
|
2932
|
+
const amounts = checkout.amounts;
|
|
2933
|
+
if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
|
|
2934
|
+
fail(
|
|
2935
|
+
resource,
|
|
2936
|
+
"$.amounts.subtotalMinor",
|
|
2937
|
+
"sum of undiscounted checkout line totals"
|
|
2938
|
+
);
|
|
2939
|
+
}
|
|
2940
|
+
if (BigInt(amounts.discountMinor) !== expectedDiscount) {
|
|
2941
|
+
fail(
|
|
2942
|
+
resource,
|
|
2943
|
+
"$.amounts.discountMinor",
|
|
2944
|
+
"sum of checkout line discounts"
|
|
2945
|
+
);
|
|
2946
|
+
}
|
|
2947
|
+
if (checkout.shippingAddress !== null) {
|
|
2948
|
+
validateShippingAddress(
|
|
2949
|
+
checkout.shippingAddress,
|
|
2950
|
+
resource,
|
|
2951
|
+
"$.shippingAddress"
|
|
2952
|
+
);
|
|
2953
|
+
}
|
|
2954
|
+
validateAttributes(checkout.attributes, resource, "$.attributes");
|
|
2955
|
+
}
|
|
2956
|
+
validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
|
|
2957
|
+
timestamp(checkout.expiresAt, resource, "$.expiresAt");
|
|
2958
|
+
timestamp(checkout.createdAt, resource, "$.createdAt");
|
|
2959
|
+
timestamp(checkout.updatedAt, resource, "$.updatedAt");
|
|
2960
|
+
const paymentState = record(checkout.paymentState, resource, "$.paymentState");
|
|
2961
|
+
exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
|
|
2962
|
+
if (status === "open") {
|
|
2963
|
+
if (paymentState.activePaymentSession !== null) {
|
|
2964
|
+
validatePaymentSessionReference(
|
|
2965
|
+
paymentState.activePaymentSession,
|
|
2966
|
+
resource,
|
|
2967
|
+
"$.paymentState.activePaymentSession"
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2970
|
+
if (checkout.order !== null)
|
|
2971
|
+
fail(resource, "$.order", "null for open Checkout");
|
|
2972
|
+
} else {
|
|
2973
|
+
if (paymentState.activePaymentSession !== null) {
|
|
2974
|
+
fail(
|
|
2975
|
+
resource,
|
|
2976
|
+
"$.paymentState.activePaymentSession",
|
|
2977
|
+
"null for spent Checkout"
|
|
2978
|
+
);
|
|
2979
|
+
}
|
|
2980
|
+
if (status === "placed") {
|
|
2981
|
+
timestamp(checkout.placedAt, resource, "$.placedAt");
|
|
2982
|
+
validateOrderReference(checkout.order, resource, "$.order");
|
|
2983
|
+
if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
|
|
2984
|
+
fail(resource, "$.placedVia", "late_capture");
|
|
2985
|
+
}
|
|
2986
|
+
if (checkout.placedVia === "late_capture") {
|
|
2987
|
+
timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
|
|
2988
|
+
enumValue(
|
|
2989
|
+
checkout.abandonedReason,
|
|
2990
|
+
ABANDONED_REASONS,
|
|
2991
|
+
resource,
|
|
2992
|
+
"$.abandonedReason"
|
|
2993
|
+
);
|
|
2994
|
+
}
|
|
2995
|
+
} else {
|
|
2996
|
+
timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
|
|
2997
|
+
enumValue(
|
|
2998
|
+
checkout.abandonedReason,
|
|
2999
|
+
ABANDONED_REASONS,
|
|
3000
|
+
resource,
|
|
3001
|
+
"$.abandonedReason"
|
|
3002
|
+
);
|
|
3003
|
+
if (checkout.order !== null)
|
|
3004
|
+
fail(resource, "$.order", "null for abandoned Checkout");
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
if (list || server) {
|
|
3008
|
+
if (checkout.clientReferenceId !== null) {
|
|
3009
|
+
boundedString(
|
|
3010
|
+
checkout.clientReferenceId,
|
|
3011
|
+
MAX_COMMERCE_RESOURCE_ID_LENGTH,
|
|
3012
|
+
resource,
|
|
3013
|
+
"$.clientReferenceId"
|
|
3014
|
+
);
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
if (server)
|
|
3018
|
+
validateIntegrationMetadata(
|
|
3019
|
+
checkout.integrationMetadata,
|
|
3020
|
+
resource,
|
|
3021
|
+
"$.integrationMetadata"
|
|
3022
|
+
);
|
|
3023
|
+
}
|
|
3024
|
+
function validatePublicCheckout(value) {
|
|
3025
|
+
validateCheckoutCore(value, "Checkout", false, false);
|
|
3026
|
+
return value;
|
|
3027
|
+
}
|
|
3028
|
+
function validateServerCheckout(value) {
|
|
3029
|
+
validateCheckoutCore(value, "Server Checkout", false, true);
|
|
3030
|
+
return value;
|
|
3031
|
+
}
|
|
3032
|
+
function validateCreateCheckoutResult(value, server) {
|
|
3033
|
+
const resource = server ? "Server Checkout create result" : "Checkout create result";
|
|
3034
|
+
const result = record(value, resource, "$");
|
|
3035
|
+
exact(result, ["checkout", "checkoutToken"], [], resource, "$");
|
|
3036
|
+
if (server) validateServerCheckout(result.checkout);
|
|
3037
|
+
else validatePublicCheckout(result.checkout);
|
|
3038
|
+
boundedString(
|
|
3039
|
+
result.checkoutToken,
|
|
3040
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
3041
|
+
resource,
|
|
3042
|
+
"$.checkoutToken"
|
|
3043
|
+
);
|
|
3044
|
+
return value;
|
|
3045
|
+
}
|
|
3046
|
+
function validateCheckoutQueryResult(value) {
|
|
3047
|
+
const result = record(value, "Checkout query result", "$");
|
|
3048
|
+
exact(
|
|
3049
|
+
result,
|
|
3050
|
+
["data", "hasMore", "nextCursor"],
|
|
3051
|
+
[],
|
|
3052
|
+
"Checkout query result",
|
|
3053
|
+
"$"
|
|
3054
|
+
);
|
|
3055
|
+
array(result.data, "Checkout query result", "$.data").forEach(
|
|
3056
|
+
(item) => validateCheckoutCore(item, "Checkout list item", true, false)
|
|
3057
|
+
);
|
|
3058
|
+
boolean(result.hasMore, "Checkout query result", "$.hasMore");
|
|
3059
|
+
if (result.nextCursor !== null)
|
|
3060
|
+
boundedString(
|
|
3061
|
+
result.nextCursor,
|
|
3062
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
3063
|
+
"Checkout query result",
|
|
3064
|
+
"$.nextCursor"
|
|
3065
|
+
);
|
|
3066
|
+
if (result.hasMore === true && result.nextCursor === null) {
|
|
3067
|
+
fail(
|
|
3068
|
+
"Checkout query result",
|
|
3069
|
+
"$.nextCursor",
|
|
3070
|
+
"non-null when hasMore is true"
|
|
3071
|
+
);
|
|
3072
|
+
}
|
|
3073
|
+
return value;
|
|
3074
|
+
}
|
|
3075
|
+
function validateMoney(value, resource, path) {
|
|
3076
|
+
const money = record(value, resource, path);
|
|
3077
|
+
exact(money, ["amountMinor", "currency"], [], resource, path);
|
|
3078
|
+
safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
|
|
3079
|
+
currency(money.currency, resource, `${path}.currency`);
|
|
3080
|
+
}
|
|
3081
|
+
function validateCaptureEvidence(value, resource, path) {
|
|
3082
|
+
const evidence = record(value, resource, path);
|
|
3083
|
+
exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
|
|
3084
|
+
safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
|
|
3085
|
+
currency(evidence.currency, resource, `${path}.currency`);
|
|
3086
|
+
timestamp(evidence.observedAt, resource, `${path}.observedAt`);
|
|
3087
|
+
}
|
|
3088
|
+
function validateNoReconciliation(value, resource, path) {
|
|
3089
|
+
const reconciliation = record(value, resource, path);
|
|
3090
|
+
exact(reconciliation, ["status"], [], resource, path);
|
|
3091
|
+
if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
|
|
3092
|
+
}
|
|
3093
|
+
function validateRequiredReconciliation(value, allowed, resource, path) {
|
|
3094
|
+
const reconciliation = record(value, resource, path);
|
|
3095
|
+
exact(reconciliation, ["status", "reasons"], [], resource, path);
|
|
3096
|
+
if (reconciliation.status !== "required")
|
|
3097
|
+
fail(resource, `${path}.status`, "required");
|
|
3098
|
+
const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
|
|
3099
|
+
if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
|
|
3100
|
+
let previous = -1;
|
|
3101
|
+
reasons.forEach((reason, index) => {
|
|
3102
|
+
const current = allowed.indexOf(reason);
|
|
3103
|
+
if (current < 0 || current <= previous) {
|
|
3104
|
+
fail(
|
|
3105
|
+
resource,
|
|
3106
|
+
`${path}.reasons[${index}]`,
|
|
3107
|
+
"unique canonical-sorted reconciliation reason"
|
|
3108
|
+
);
|
|
3109
|
+
}
|
|
3110
|
+
previous = current;
|
|
3111
|
+
});
|
|
3112
|
+
}
|
|
3113
|
+
function validateNextAction(value, resource, path) {
|
|
3114
|
+
const action = record(value, resource, path);
|
|
3115
|
+
exact(
|
|
3116
|
+
action,
|
|
3117
|
+
[
|
|
3118
|
+
"type",
|
|
3119
|
+
"clientKey",
|
|
3120
|
+
"paymentMethodVariantKey",
|
|
3121
|
+
"agreementVariantKey",
|
|
3122
|
+
"providerOrderId",
|
|
3123
|
+
"providerCustomerKey",
|
|
3124
|
+
"orderName"
|
|
3125
|
+
],
|
|
3126
|
+
["customerName", "customerEmail"],
|
|
3127
|
+
resource,
|
|
3128
|
+
path
|
|
3129
|
+
);
|
|
3130
|
+
if (action.type !== "toss_widget")
|
|
3131
|
+
fail(resource, `${path}.type`, "toss_widget");
|
|
3132
|
+
for (const key of [
|
|
3133
|
+
"clientKey",
|
|
3134
|
+
"paymentMethodVariantKey",
|
|
3135
|
+
"agreementVariantKey"
|
|
3136
|
+
]) {
|
|
3137
|
+
boundedString(action[key], 255, resource, `${path}.${key}`);
|
|
3138
|
+
}
|
|
3139
|
+
string(action.providerOrderId, resource, `${path}.providerOrderId`);
|
|
3140
|
+
string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
|
|
3141
|
+
boundedString(
|
|
3142
|
+
action.orderName,
|
|
3143
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
3144
|
+
resource,
|
|
3145
|
+
`${path}.orderName`
|
|
3146
|
+
);
|
|
3147
|
+
if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
|
|
3148
|
+
fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
|
|
3149
|
+
}
|
|
3150
|
+
if (action.providerCustomerKey !== "ANONYMOUS" && !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
|
|
3151
|
+
action.providerCustomerKey
|
|
3152
|
+
)) {
|
|
3153
|
+
fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
|
|
3154
|
+
}
|
|
3155
|
+
if (action.customerName !== void 0)
|
|
3156
|
+
boundedString(
|
|
3157
|
+
action.customerName,
|
|
3158
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
3159
|
+
resource,
|
|
3160
|
+
`${path}.customerName`
|
|
3161
|
+
);
|
|
3162
|
+
if (action.customerEmail !== void 0)
|
|
3163
|
+
validateCustomer({ email: action.customerEmail }, resource, path);
|
|
3164
|
+
}
|
|
3165
|
+
function validatePublicPaymentSession(value) {
|
|
3166
|
+
const resource = "PaymentSession";
|
|
3167
|
+
const session = record(value, resource, "$");
|
|
3168
|
+
enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
|
|
3169
|
+
const status = enumValue(
|
|
3170
|
+
session.providerStatus,
|
|
3171
|
+
PAYMENT_PROVIDER_STATUSES,
|
|
3172
|
+
resource,
|
|
3173
|
+
"$.providerStatus"
|
|
3174
|
+
);
|
|
3175
|
+
const common = [
|
|
3176
|
+
"id",
|
|
3177
|
+
"money",
|
|
3178
|
+
"expiresAt",
|
|
3179
|
+
"sessionRole",
|
|
3180
|
+
"provider",
|
|
3181
|
+
"providerStatus",
|
|
3182
|
+
"presentationStatus",
|
|
3183
|
+
"finalizationStatus",
|
|
3184
|
+
"reconciliation",
|
|
3185
|
+
"order"
|
|
3186
|
+
];
|
|
3187
|
+
const optional = [];
|
|
3188
|
+
if (status === "requires_payment_method" || status === "requires_action")
|
|
3189
|
+
optional.push("nextAction");
|
|
3190
|
+
else if (status === "captured") common.push("providerEvidence");
|
|
3191
|
+
else if (status === "failed") common.push("failure");
|
|
3192
|
+
else if (status === "canceled") common.push("cancellationReason");
|
|
3193
|
+
exact(session, common, optional, resource, "$");
|
|
3194
|
+
string(session.id, resource, "$.id");
|
|
3195
|
+
validateMoney(session.money, resource, "$.money");
|
|
3196
|
+
if (session.expiresAt !== null)
|
|
3197
|
+
timestamp(session.expiresAt, resource, "$.expiresAt");
|
|
3198
|
+
if (status === "requires_payment_method" || status === "requires_action") {
|
|
3199
|
+
if (session.sessionRole === "active") {
|
|
3200
|
+
if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
|
|
3201
|
+
fail(resource, "$", "actionable active not-ready state");
|
|
3202
|
+
}
|
|
3203
|
+
if (!("nextAction" in session))
|
|
3204
|
+
fail(resource, "$.nextAction", "required field");
|
|
3205
|
+
validateNextAction(session.nextAction, resource, "$.nextAction");
|
|
3206
|
+
} else if (session.sessionRole === "residual") {
|
|
3207
|
+
if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
|
|
3208
|
+
fail(resource, "$", "suppressed residual not-ready state");
|
|
3209
|
+
}
|
|
3210
|
+
if ("nextAction" in session)
|
|
3211
|
+
fail(resource, "$.nextAction", "absent for suppressed state");
|
|
3212
|
+
} else fail(resource, "$.sessionRole", "active | residual");
|
|
3213
|
+
validateNoReconciliation(
|
|
3214
|
+
session.reconciliation,
|
|
3215
|
+
resource,
|
|
3216
|
+
"$.reconciliation"
|
|
3217
|
+
);
|
|
3218
|
+
if (session.order !== null) fail(resource, "$.order", "null");
|
|
3219
|
+
} else if ([
|
|
3220
|
+
"requires_confirmation",
|
|
3221
|
+
"initializing",
|
|
3222
|
+
"processing",
|
|
3223
|
+
"authorized",
|
|
3224
|
+
"canceling"
|
|
3225
|
+
].includes(status)) {
|
|
3226
|
+
enumValue(
|
|
3227
|
+
session.sessionRole,
|
|
3228
|
+
["active", "residual"],
|
|
3229
|
+
resource,
|
|
3230
|
+
"$.sessionRole"
|
|
3231
|
+
);
|
|
3232
|
+
if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
|
|
3233
|
+
fail(resource, "$", "suppressed not-ready state");
|
|
3234
|
+
}
|
|
3235
|
+
validateNoReconciliation(
|
|
3236
|
+
session.reconciliation,
|
|
3237
|
+
resource,
|
|
3238
|
+
"$.reconciliation"
|
|
3239
|
+
);
|
|
3240
|
+
if (session.order !== null) fail(resource, "$.order", "null");
|
|
3241
|
+
} else if (status === "unknown") {
|
|
3242
|
+
enumValue(
|
|
3243
|
+
session.sessionRole,
|
|
3244
|
+
["active", "residual"],
|
|
3245
|
+
resource,
|
|
3246
|
+
"$.sessionRole"
|
|
3247
|
+
);
|
|
3248
|
+
if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
|
|
3249
|
+
fail(resource, "$", "suppressed not-ready state");
|
|
3250
|
+
}
|
|
3251
|
+
validateRequiredReconciliation(
|
|
3252
|
+
session.reconciliation,
|
|
3253
|
+
["provider_outcome_unknown"],
|
|
3254
|
+
resource,
|
|
3255
|
+
"$.reconciliation"
|
|
3256
|
+
);
|
|
3257
|
+
if (session.order !== null) fail(resource, "$.order", "null");
|
|
3258
|
+
} else if (status === "captured") {
|
|
3259
|
+
validateCaptureEvidence(
|
|
3260
|
+
session.providerEvidence,
|
|
3261
|
+
resource,
|
|
3262
|
+
"$.providerEvidence"
|
|
3263
|
+
);
|
|
3264
|
+
if (session.presentationStatus !== "suppressed")
|
|
3265
|
+
fail(resource, "$.presentationStatus", "suppressed");
|
|
3266
|
+
if (session.finalizationStatus === "pending") {
|
|
3267
|
+
enumValue(
|
|
3268
|
+
session.sessionRole,
|
|
3269
|
+
["canonical_candidate", "residual"],
|
|
3270
|
+
resource,
|
|
3271
|
+
"$.sessionRole"
|
|
3272
|
+
);
|
|
3273
|
+
if (session.order !== null)
|
|
3274
|
+
fail(resource, "$.order", "null for pending finalization");
|
|
3275
|
+
const reconciliation = record(
|
|
3276
|
+
session.reconciliation,
|
|
3277
|
+
resource,
|
|
3278
|
+
"$.reconciliation"
|
|
3279
|
+
);
|
|
3280
|
+
if (reconciliation.status === "none")
|
|
3281
|
+
validateNoReconciliation(reconciliation, resource, "$.reconciliation");
|
|
3282
|
+
else
|
|
3283
|
+
validateRequiredReconciliation(
|
|
3284
|
+
reconciliation,
|
|
3285
|
+
[
|
|
3286
|
+
"local_commit_ambiguous",
|
|
3287
|
+
"amount_mismatch",
|
|
3288
|
+
"currency_mismatch",
|
|
3289
|
+
"excess_capture_pending_order"
|
|
3290
|
+
],
|
|
3291
|
+
resource,
|
|
3292
|
+
"$.reconciliation"
|
|
3293
|
+
);
|
|
3294
|
+
} else if (session.finalizationStatus === "committed") {
|
|
3295
|
+
validateOrderReference(session.order, resource, "$.order");
|
|
3296
|
+
const reconciliation = record(
|
|
3297
|
+
session.reconciliation,
|
|
3298
|
+
resource,
|
|
3299
|
+
"$.reconciliation"
|
|
3300
|
+
);
|
|
3301
|
+
if (reconciliation.status === "none") {
|
|
3302
|
+
enumValue(
|
|
3303
|
+
session.sessionRole,
|
|
3304
|
+
["canonical", "historical"],
|
|
3305
|
+
resource,
|
|
3306
|
+
"$.sessionRole"
|
|
3307
|
+
);
|
|
3308
|
+
validateNoReconciliation(reconciliation, resource, "$.reconciliation");
|
|
3309
|
+
} else {
|
|
3310
|
+
enumValue(
|
|
3311
|
+
session.sessionRole,
|
|
3312
|
+
["canonical", "residual"],
|
|
3313
|
+
resource,
|
|
3314
|
+
"$.sessionRole"
|
|
3315
|
+
);
|
|
3316
|
+
validateRequiredReconciliation(
|
|
3317
|
+
reconciliation,
|
|
3318
|
+
[
|
|
3319
|
+
"inventory_unavailable",
|
|
3320
|
+
"admission_unavailable",
|
|
3321
|
+
"amount_mismatch",
|
|
3322
|
+
"currency_mismatch",
|
|
3323
|
+
"excess_capture",
|
|
3324
|
+
"late_capture",
|
|
3325
|
+
"cross_checkout_duplicate"
|
|
3326
|
+
],
|
|
3327
|
+
resource,
|
|
3328
|
+
"$.reconciliation"
|
|
3329
|
+
);
|
|
3330
|
+
}
|
|
3331
|
+
} else fail(resource, "$.finalizationStatus", "pending | committed");
|
|
3332
|
+
} else if (status === "failed") {
|
|
3333
|
+
if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
|
|
3334
|
+
fail(resource, "$", "historical suppressed failed state");
|
|
3335
|
+
}
|
|
3336
|
+
validateNoReconciliation(
|
|
3337
|
+
session.reconciliation,
|
|
3338
|
+
resource,
|
|
3339
|
+
"$.reconciliation"
|
|
3340
|
+
);
|
|
3341
|
+
const failure = record(session.failure, resource, "$.failure");
|
|
3342
|
+
exact(failure, ["reason"], ["message"], resource, "$.failure");
|
|
3343
|
+
enumValue(
|
|
3344
|
+
failure.reason,
|
|
3345
|
+
PAYMENT_FAILURE_REASONS,
|
|
3346
|
+
resource,
|
|
3347
|
+
"$.failure.reason"
|
|
3348
|
+
);
|
|
3349
|
+
if (failure.message !== void 0)
|
|
3350
|
+
string(failure.message, resource, "$.failure.message");
|
|
3351
|
+
} else {
|
|
3352
|
+
if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
|
|
3353
|
+
fail(resource, "$", "historical suppressed canceled state");
|
|
3354
|
+
}
|
|
3355
|
+
validateNoReconciliation(
|
|
3356
|
+
session.reconciliation,
|
|
3357
|
+
resource,
|
|
3358
|
+
"$.reconciliation"
|
|
3359
|
+
);
|
|
3360
|
+
enumValue(
|
|
3361
|
+
session.cancellationReason,
|
|
3362
|
+
["expired", "customer", "operator", "provider"],
|
|
3363
|
+
resource,
|
|
3364
|
+
"$.cancellationReason"
|
|
3365
|
+
);
|
|
3366
|
+
}
|
|
3367
|
+
return value;
|
|
1442
3368
|
}
|
|
1443
|
-
var ContentClient = class {
|
|
1444
|
-
constructor(options) {
|
|
1445
|
-
const api = new PublicContentApi("ContentClient", {
|
|
1446
|
-
publishableKey: options.publishableKey,
|
|
1447
|
-
apiUrl: options.apiUrl,
|
|
1448
|
-
onRequestId: options.onRequestId,
|
|
1449
|
-
requiresCredential: false
|
|
1450
|
-
});
|
|
1451
|
-
this.links = {
|
|
1452
|
-
list: (params) => api.get(linksListPath(params))
|
|
1453
|
-
};
|
|
1454
|
-
this.galleryItems = {
|
|
1455
|
-
list: (params) => api.get(
|
|
1456
|
-
galleryItemsListPath(params)
|
|
1457
|
-
)
|
|
1458
|
-
};
|
|
1459
|
-
}
|
|
1460
|
-
};
|
|
1461
3369
|
|
|
1462
3370
|
// src/core/customer/customer-auth.ts
|
|
1463
3371
|
var DEFAULT_TIMEOUT2 = 15e3;
|
|
@@ -1476,8 +3384,10 @@ var CustomerAuth = class {
|
|
|
1476
3384
|
const persist = options?.persist ?? true;
|
|
1477
3385
|
if (persist) {
|
|
1478
3386
|
const key = typeof persist === "string" ? persist : "customer-token";
|
|
3387
|
+
const refreshKey = `${key}:refresh`;
|
|
1479
3388
|
const isBrowser = typeof window !== "undefined";
|
|
1480
3389
|
this.token = isBrowser ? safeGetItem(key) : null;
|
|
3390
|
+
this.refreshTokenValue = isBrowser ? safeGetItem(refreshKey) : null;
|
|
1481
3391
|
this.onTokenChange = isBrowser ? (token) => {
|
|
1482
3392
|
try {
|
|
1483
3393
|
if (token) localStorage.setItem(key, token);
|
|
@@ -1485,9 +3395,18 @@ var CustomerAuth = class {
|
|
|
1485
3395
|
} catch {
|
|
1486
3396
|
}
|
|
1487
3397
|
} : void 0;
|
|
3398
|
+
this.onRefreshTokenChange = isBrowser ? (refreshToken) => {
|
|
3399
|
+
try {
|
|
3400
|
+
if (refreshToken) localStorage.setItem(refreshKey, refreshToken);
|
|
3401
|
+
else localStorage.removeItem(refreshKey);
|
|
3402
|
+
} catch {
|
|
3403
|
+
}
|
|
3404
|
+
} : void 0;
|
|
1488
3405
|
} else {
|
|
1489
3406
|
this.token = options?.token ?? null;
|
|
3407
|
+
this.refreshTokenValue = options?.refreshToken ?? null;
|
|
1490
3408
|
this.onTokenChange = options?.onTokenChange;
|
|
3409
|
+
this.onRefreshTokenChange = options?.onRefreshTokenChange;
|
|
1491
3410
|
}
|
|
1492
3411
|
}
|
|
1493
3412
|
/**
|
|
@@ -1511,13 +3430,17 @@ var CustomerAuth = class {
|
|
|
1511
3430
|
}
|
|
1512
3431
|
);
|
|
1513
3432
|
this.setToken(result.token);
|
|
3433
|
+
if (result.refreshToken) this.setRefreshToken(result.refreshToken);
|
|
1514
3434
|
return result;
|
|
1515
3435
|
}
|
|
1516
3436
|
/**
|
|
1517
|
-
* Refresh the current token.
|
|
3437
|
+
* Refresh the current token. Uses a refresh token when available, otherwise
|
|
3438
|
+
* falls back to the legacy bearer-token compatibility path.
|
|
1518
3439
|
*/
|
|
1519
3440
|
async refreshToken() {
|
|
1520
|
-
if (!this.token)
|
|
3441
|
+
if (!this.refreshTokenValue && !this.token) {
|
|
3442
|
+
throw new ApiError("Not authenticated", 401);
|
|
3443
|
+
}
|
|
1521
3444
|
if (this.refreshPromise) return this.refreshPromise;
|
|
1522
3445
|
this.refreshPromise = this._doRefreshToken();
|
|
1523
3446
|
try {
|
|
@@ -1527,14 +3450,19 @@ var CustomerAuth = class {
|
|
|
1527
3450
|
}
|
|
1528
3451
|
}
|
|
1529
3452
|
async _doRefreshToken() {
|
|
3453
|
+
const init = this.refreshTokenValue ? {
|
|
3454
|
+
method: "POST",
|
|
3455
|
+
body: JSON.stringify({ refreshToken: this.refreshTokenValue })
|
|
3456
|
+
} : {
|
|
3457
|
+
method: "POST",
|
|
3458
|
+
headers: { Authorization: `Bearer ${this.token}` }
|
|
3459
|
+
};
|
|
1530
3460
|
const result = await this.requestJson(
|
|
1531
3461
|
"/api/customers/refresh",
|
|
1532
|
-
|
|
1533
|
-
method: "POST",
|
|
1534
|
-
headers: { Authorization: `Bearer ${this.token}` }
|
|
1535
|
-
}
|
|
3462
|
+
init
|
|
1536
3463
|
);
|
|
1537
3464
|
this.setToken(result.token);
|
|
3465
|
+
if (result.refreshToken) this.setRefreshToken(result.refreshToken);
|
|
1538
3466
|
return result;
|
|
1539
3467
|
}
|
|
1540
3468
|
/**
|
|
@@ -1542,6 +3470,7 @@ var CustomerAuth = class {
|
|
|
1542
3470
|
*/
|
|
1543
3471
|
logout() {
|
|
1544
3472
|
this.setToken(null);
|
|
3473
|
+
this.setRefreshToken(null);
|
|
1545
3474
|
}
|
|
1546
3475
|
/**
|
|
1547
3476
|
* Get the current authenticated customer's profile
|
|
@@ -1617,25 +3546,28 @@ var CustomerAuth = class {
|
|
|
1617
3546
|
const params = new URLSearchParams();
|
|
1618
3547
|
if (options?.page) params.set("page", String(options.page));
|
|
1619
3548
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
1620
|
-
if (options?.
|
|
1621
|
-
params.set("
|
|
3549
|
+
if (options?.financialStatus) {
|
|
3550
|
+
params.set("financialStatus", options.financialStatus);
|
|
1622
3551
|
}
|
|
1623
|
-
if (options?.
|
|
1624
|
-
params.set("
|
|
3552
|
+
if (options?.fulfillmentStatus) {
|
|
3553
|
+
params.set("fulfillmentStatus", options.fulfillmentStatus);
|
|
1625
3554
|
}
|
|
1626
3555
|
if (options?.returnStatus) params.set("returnStatus", options.returnStatus);
|
|
3556
|
+
if (options?.confirmationStatus) {
|
|
3557
|
+
params.set("confirmationStatus", options.confirmationStatus);
|
|
3558
|
+
}
|
|
1627
3559
|
if (options?.primaryDisplayStatus) {
|
|
1628
3560
|
params.set("primaryDisplayStatus", options.primaryDisplayStatus);
|
|
1629
3561
|
}
|
|
1630
|
-
if (options?.returnDisplayStatus) {
|
|
1631
|
-
params.set("returnDisplayStatus", options.returnDisplayStatus);
|
|
1632
|
-
}
|
|
1633
|
-
if (options?.status) params.set("status", options.status);
|
|
1634
3562
|
const qs = params.toString();
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
3563
|
+
const result = await this.requestJson(
|
|
3564
|
+
`/api/customers/me/orders${qs ? `?${qs}` : ""}`,
|
|
3565
|
+
{
|
|
3566
|
+
method: "GET",
|
|
3567
|
+
headers: { Authorization: `Bearer ${this.token}` }
|
|
3568
|
+
}
|
|
3569
|
+
);
|
|
3570
|
+
return validatePublicOrderList(result);
|
|
1639
3571
|
}
|
|
1640
3572
|
/**
|
|
1641
3573
|
* Get the current token (or null if not authenticated)
|
|
@@ -1643,6 +3575,12 @@ var CustomerAuth = class {
|
|
|
1643
3575
|
getToken() {
|
|
1644
3576
|
return this.token;
|
|
1645
3577
|
}
|
|
3578
|
+
/**
|
|
3579
|
+
* Get the current refresh token (or null if unavailable)
|
|
3580
|
+
*/
|
|
3581
|
+
getRefreshToken() {
|
|
3582
|
+
return this.refreshTokenValue;
|
|
3583
|
+
}
|
|
1646
3584
|
/**
|
|
1647
3585
|
* Set the token manually (e.g. from SSR)
|
|
1648
3586
|
*/
|
|
@@ -1650,6 +3588,13 @@ var CustomerAuth = class {
|
|
|
1650
3588
|
this.token = token;
|
|
1651
3589
|
this.onTokenChange?.(token);
|
|
1652
3590
|
}
|
|
3591
|
+
/**
|
|
3592
|
+
* Set the refresh token manually (e.g. from SSR cookie)
|
|
3593
|
+
*/
|
|
3594
|
+
setRefreshToken(refreshToken) {
|
|
3595
|
+
this.refreshTokenValue = refreshToken;
|
|
3596
|
+
this.onRefreshTokenChange?.(refreshToken);
|
|
3597
|
+
}
|
|
1653
3598
|
/**
|
|
1654
3599
|
* Check if the customer is currently authenticated
|
|
1655
3600
|
*/
|
|
@@ -1678,91 +3623,362 @@ var CustomerAuth = class {
|
|
|
1678
3623
|
}
|
|
1679
3624
|
};
|
|
1680
3625
|
|
|
3626
|
+
// src/core/customer/customer-oauth.ts
|
|
3627
|
+
var DEFAULT_SCOPES = ["openid", "profile", "email"];
|
|
3628
|
+
var DEFAULT_TIMEOUT3 = 15e3;
|
|
3629
|
+
function issuerUrl(issuer, path) {
|
|
3630
|
+
const base = resolveApiUrl(issuer);
|
|
3631
|
+
return new URL(path, base.endsWith("/") ? base : `${base}/`).toString();
|
|
3632
|
+
}
|
|
3633
|
+
function randomBase64Url(bytes) {
|
|
3634
|
+
const buffer = new Uint8Array(bytes);
|
|
3635
|
+
crypto.getRandomValues(buffer);
|
|
3636
|
+
let binary = "";
|
|
3637
|
+
for (const value of buffer) {
|
|
3638
|
+
binary += String.fromCharCode(value);
|
|
3639
|
+
}
|
|
3640
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
3641
|
+
}
|
|
3642
|
+
async function sha256Base64Url(value) {
|
|
3643
|
+
const data = new TextEncoder().encode(value);
|
|
3644
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
3645
|
+
let binary = "";
|
|
3646
|
+
for (const byte of new Uint8Array(digest)) {
|
|
3647
|
+
binary += String.fromCharCode(byte);
|
|
3648
|
+
}
|
|
3649
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
3650
|
+
}
|
|
3651
|
+
function normalizeToken(body) {
|
|
3652
|
+
if (body.token_type !== "Bearer") {
|
|
3653
|
+
throw new Error("Unsupported customer OAuth token type");
|
|
3654
|
+
}
|
|
3655
|
+
return {
|
|
3656
|
+
accessToken: body.access_token,
|
|
3657
|
+
expiresAt: Date.now() + body.expires_in * 1e3,
|
|
3658
|
+
expiresIn: body.expires_in,
|
|
3659
|
+
...body.id_token ? { idToken: body.id_token } : {},
|
|
3660
|
+
refreshToken: body.refresh_token,
|
|
3661
|
+
...body.scope ? { scope: body.scope } : {},
|
|
3662
|
+
tokenType: "Bearer"
|
|
3663
|
+
};
|
|
3664
|
+
}
|
|
3665
|
+
var CustomerOAuth = class {
|
|
3666
|
+
constructor(config) {
|
|
3667
|
+
if (!config.clientId) throw new Error("customer OAuth clientId is required");
|
|
3668
|
+
if (!config.issuer) throw new Error("customer OAuth issuer is required");
|
|
3669
|
+
this.clientId = config.clientId;
|
|
3670
|
+
this.issuer = config.issuer;
|
|
3671
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT3;
|
|
3672
|
+
}
|
|
3673
|
+
async createAuthorizationUrl(input) {
|
|
3674
|
+
const codeVerifier = randomBase64Url(48);
|
|
3675
|
+
const codeChallenge = await sha256Base64Url(codeVerifier);
|
|
3676
|
+
const state = randomBase64Url(32);
|
|
3677
|
+
const nonce = randomBase64Url(32);
|
|
3678
|
+
const scopes = input.scopes ?? DEFAULT_SCOPES;
|
|
3679
|
+
const url = new URL(issuerUrl(this.issuer, "customer-oauth/authorize"));
|
|
3680
|
+
url.searchParams.set("response_type", "code");
|
|
3681
|
+
url.searchParams.set("client_id", this.clientId);
|
|
3682
|
+
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
3683
|
+
url.searchParams.set("scope", scopes.join(" "));
|
|
3684
|
+
url.searchParams.set("state", state);
|
|
3685
|
+
url.searchParams.set("nonce", nonce);
|
|
3686
|
+
url.searchParams.set("code_challenge", codeChallenge);
|
|
3687
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
3688
|
+
return {
|
|
3689
|
+
authorizationUrl: url.toString(),
|
|
3690
|
+
codeChallenge,
|
|
3691
|
+
codeVerifier,
|
|
3692
|
+
nonce,
|
|
3693
|
+
returnTo: input.returnTo ?? null,
|
|
3694
|
+
state
|
|
3695
|
+
};
|
|
3696
|
+
}
|
|
3697
|
+
parseCallback(callbackUrl, options) {
|
|
3698
|
+
const url = new URL(callbackUrl);
|
|
3699
|
+
const error = url.searchParams.get("error");
|
|
3700
|
+
if (error) {
|
|
3701
|
+
throw new Error(
|
|
3702
|
+
url.searchParams.get("error_description") ?? `OAuth error: ${error}`
|
|
3703
|
+
);
|
|
3704
|
+
}
|
|
3705
|
+
const code = url.searchParams.get("code");
|
|
3706
|
+
const state = url.searchParams.get("state");
|
|
3707
|
+
if (!code || !state) throw new Error("OAuth callback is missing code/state");
|
|
3708
|
+
if (state !== options.expectedState) throw new Error("OAuth state mismatch");
|
|
3709
|
+
return { code, state };
|
|
3710
|
+
}
|
|
3711
|
+
async exchangeCode(input) {
|
|
3712
|
+
const body = new URLSearchParams({
|
|
3713
|
+
client_id: this.clientId,
|
|
3714
|
+
code: input.code,
|
|
3715
|
+
code_verifier: input.codeVerifier,
|
|
3716
|
+
grant_type: "authorization_code",
|
|
3717
|
+
redirect_uri: input.redirectUri
|
|
3718
|
+
});
|
|
3719
|
+
return this.tokenRequest(body);
|
|
3720
|
+
}
|
|
3721
|
+
async refresh(input) {
|
|
3722
|
+
const body = new URLSearchParams({
|
|
3723
|
+
client_id: this.clientId,
|
|
3724
|
+
grant_type: "refresh_token",
|
|
3725
|
+
refresh_token: input.refreshToken
|
|
3726
|
+
});
|
|
3727
|
+
return this.tokenRequest(body);
|
|
3728
|
+
}
|
|
3729
|
+
async logout(input) {
|
|
3730
|
+
const body = { client_id: this.clientId };
|
|
3731
|
+
if (input.refreshToken) body.refresh_token = input.refreshToken;
|
|
3732
|
+
if (input.postLogoutRedirectUri) {
|
|
3733
|
+
body.post_logout_redirect_uri = input.postLogoutRedirectUri;
|
|
3734
|
+
}
|
|
3735
|
+
const response = await httpFetch("/customer-oauth/logout", {
|
|
3736
|
+
apiUrl: this.issuer,
|
|
3737
|
+
method: "POST",
|
|
3738
|
+
body: JSON.stringify(body),
|
|
3739
|
+
headers: { "Content-Type": "application/json" },
|
|
3740
|
+
timeout: this.timeout,
|
|
3741
|
+
retry: { maxRetries: 0 }
|
|
3742
|
+
});
|
|
3743
|
+
return parseApiResponse(
|
|
3744
|
+
response,
|
|
3745
|
+
"/customer-oauth/logout"
|
|
3746
|
+
);
|
|
3747
|
+
}
|
|
3748
|
+
verifyIdToken() {
|
|
3749
|
+
throw new Error(
|
|
3750
|
+
"Customer OAuth ID token verification is not implemented; treat idToken as opaque."
|
|
3751
|
+
);
|
|
3752
|
+
}
|
|
3753
|
+
async tokenRequest(body) {
|
|
3754
|
+
const response = await httpFetch("/api/customer-oauth/token", {
|
|
3755
|
+
apiUrl: this.issuer,
|
|
3756
|
+
method: "POST",
|
|
3757
|
+
body,
|
|
3758
|
+
headers: {
|
|
3759
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
3760
|
+
},
|
|
3761
|
+
timeout: this.timeout,
|
|
3762
|
+
retry: { maxRetries: 0 }
|
|
3763
|
+
});
|
|
3764
|
+
return normalizeToken(
|
|
3765
|
+
await parseApiResponse(
|
|
3766
|
+
response,
|
|
3767
|
+
"/api/customer-oauth/token"
|
|
3768
|
+
)
|
|
3769
|
+
);
|
|
3770
|
+
}
|
|
3771
|
+
};
|
|
3772
|
+
|
|
1681
3773
|
// src/core/customer/customer-namespace.ts
|
|
1682
3774
|
var CustomerNamespace = class {
|
|
1683
3775
|
constructor(publishableKey, options, apiUrl) {
|
|
1684
3776
|
this.auth = new CustomerAuth(publishableKey, options, apiUrl);
|
|
3777
|
+
if (options?.oauth) {
|
|
3778
|
+
this.oauth = new CustomerOAuth(options.oauth);
|
|
3779
|
+
}
|
|
1685
3780
|
}
|
|
1686
3781
|
};
|
|
1687
3782
|
|
|
3783
|
+
// src/core/api/commerce-idempotency.ts
|
|
3784
|
+
var UUID_V4_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
3785
|
+
var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
|
|
3786
|
+
function isCommerceIdempotencyKey(value) {
|
|
3787
|
+
return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
|
|
3788
|
+
}
|
|
3789
|
+
function assertCommerceIdempotencyKey(value) {
|
|
3790
|
+
if (isCommerceIdempotencyKey(value)) return;
|
|
3791
|
+
throw createValidationError(
|
|
3792
|
+
"idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
|
|
3793
|
+
{ field: "idempotencyKey" }
|
|
3794
|
+
);
|
|
3795
|
+
}
|
|
3796
|
+
function createCommerceIdempotencyKey() {
|
|
3797
|
+
return globalThis.crypto.randomUUID();
|
|
3798
|
+
}
|
|
3799
|
+
|
|
1688
3800
|
// src/core/api/cart-api.ts
|
|
3801
|
+
var MAX_CART_LINE_ADMISSIONS = 32;
|
|
1689
3802
|
var CartApi = class extends CustomerScopedApi {
|
|
1690
3803
|
constructor(options) {
|
|
1691
3804
|
super("CartApi", { ...options, requiresCredential: false });
|
|
3805
|
+
this.serverTransport = Boolean(options.secretKey);
|
|
1692
3806
|
}
|
|
1693
|
-
|
|
1694
|
-
return this.
|
|
3807
|
+
endpoint(key) {
|
|
3808
|
+
return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
|
|
1695
3809
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
3810
|
+
execute(endpoint2, body, idempotencyKey) {
|
|
3811
|
+
return this.requestEndpoint(endpoint2, body, {
|
|
3812
|
+
...idempotencyKey && {
|
|
3813
|
+
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
3814
|
+
}
|
|
3815
|
+
});
|
|
1702
3816
|
}
|
|
1703
|
-
|
|
1704
|
-
return this.execute("
|
|
3817
|
+
create(params = {}) {
|
|
3818
|
+
return this.execute(this.endpoint("create"), params).then(
|
|
3819
|
+
(value) => validateCreateCartResult(value)
|
|
3820
|
+
);
|
|
1705
3821
|
}
|
|
1706
|
-
|
|
1707
|
-
return this.execute(
|
|
1708
|
-
|
|
1709
|
-
"POST",
|
|
1710
|
-
params
|
|
3822
|
+
retrieve(params) {
|
|
3823
|
+
return this.execute(this.endpoint("retrieve"), params).then(
|
|
3824
|
+
(value) => validatePublicCart(value)
|
|
1711
3825
|
);
|
|
1712
3826
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
3827
|
+
mine(params = {}) {
|
|
3828
|
+
const endpoint2 = this.endpoint("mine");
|
|
3829
|
+
return this.execute(endpoint2, params).then(
|
|
3830
|
+
(value) => validateCartMineResult(value)
|
|
3831
|
+
);
|
|
3832
|
+
}
|
|
3833
|
+
merge(params) {
|
|
3834
|
+
const { idempotencyKey, ...body } = params;
|
|
3835
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3836
|
+
const endpoint2 = this.endpoint("merge");
|
|
3837
|
+
return this.execute(endpoint2, body, idempotencyKey).then(
|
|
3838
|
+
(value) => validateCartMergeResult(value)
|
|
1723
3839
|
);
|
|
1724
3840
|
}
|
|
1725
3841
|
addItem(params) {
|
|
1726
|
-
return this.
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
3842
|
+
return this.mutate(this.endpoint("addItem"), params);
|
|
3843
|
+
}
|
|
3844
|
+
mutate(endpoint2, params) {
|
|
3845
|
+
const { idempotencyKey, ...body } = params;
|
|
3846
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3847
|
+
return this.execute(endpoint2, body, idempotencyKey).then(
|
|
3848
|
+
(value) => validateCartMutationResult(value)
|
|
1730
3849
|
);
|
|
1731
3850
|
}
|
|
1732
3851
|
updateItem(params) {
|
|
1733
|
-
return this.
|
|
1734
|
-
COMMERCE_ENDPOINTS.carts.updateItem,
|
|
1735
|
-
"POST",
|
|
1736
|
-
params
|
|
1737
|
-
);
|
|
3852
|
+
return this.mutate(this.endpoint("updateItem"), params);
|
|
1738
3853
|
}
|
|
1739
3854
|
removeItem(params) {
|
|
1740
|
-
return this.
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
3855
|
+
return this.mutate(this.endpoint("removeItem"), params);
|
|
3856
|
+
}
|
|
3857
|
+
clear(params) {
|
|
3858
|
+
return this.mutate(this.endpoint("clear"), params);
|
|
3859
|
+
}
|
|
3860
|
+
updateDiscountCodes(params) {
|
|
3861
|
+
return this.mutate(this.endpoint("updateDiscountCodes"), params);
|
|
3862
|
+
}
|
|
3863
|
+
updateAttributes(params) {
|
|
3864
|
+
return this.mutate(this.endpoint("updateAttributes"), params);
|
|
3865
|
+
}
|
|
3866
|
+
};
|
|
3867
|
+
|
|
3868
|
+
// src/core/api/checkout-api.ts
|
|
3869
|
+
var CheckoutApi = class extends CustomerScopedApi {
|
|
3870
|
+
constructor(options) {
|
|
3871
|
+
super("CheckoutApi", { ...options, requiresCredential: false });
|
|
3872
|
+
}
|
|
3873
|
+
post(endpoint2, body, idempotencyKey) {
|
|
3874
|
+
return this.requestEndpoint(endpoint2, body, {
|
|
3875
|
+
...idempotencyKey && {
|
|
3876
|
+
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
3877
|
+
}
|
|
3878
|
+
});
|
|
3879
|
+
}
|
|
3880
|
+
async publicCheckout(result) {
|
|
3881
|
+
return validatePublicCheckout(await result);
|
|
3882
|
+
}
|
|
3883
|
+
async serverCheckout(result) {
|
|
3884
|
+
return validateServerCheckout(await result);
|
|
3885
|
+
}
|
|
3886
|
+
async createResult(result) {
|
|
3887
|
+
return validateCreateCheckoutResult(
|
|
3888
|
+
await result,
|
|
3889
|
+
false
|
|
1744
3890
|
);
|
|
1745
3891
|
}
|
|
1746
|
-
|
|
1747
|
-
return
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
params
|
|
3892
|
+
async createServerResult(result) {
|
|
3893
|
+
return validateCreateCheckoutResult(
|
|
3894
|
+
await result,
|
|
3895
|
+
true
|
|
1751
3896
|
);
|
|
1752
3897
|
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
3898
|
+
create(params) {
|
|
3899
|
+
const { idempotencyKey, ...body } = params;
|
|
3900
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3901
|
+
return this.createResult(
|
|
3902
|
+
this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
|
|
1758
3903
|
);
|
|
1759
3904
|
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
3905
|
+
createServer(params) {
|
|
3906
|
+
const { idempotencyKey, ...body } = params;
|
|
3907
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3908
|
+
return this.createServerResult(
|
|
3909
|
+
this.post(
|
|
3910
|
+
COMMERCE_ENDPOINTS.checkouts.server.create,
|
|
3911
|
+
body,
|
|
3912
|
+
idempotencyKey
|
|
3913
|
+
)
|
|
3914
|
+
);
|
|
3915
|
+
}
|
|
3916
|
+
retrieve(params) {
|
|
3917
|
+
return this.publicCheckout(
|
|
3918
|
+
this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
|
|
3919
|
+
);
|
|
3920
|
+
}
|
|
3921
|
+
retrieveServer(params) {
|
|
3922
|
+
return this.serverCheckout(
|
|
3923
|
+
this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
|
|
3924
|
+
);
|
|
3925
|
+
}
|
|
3926
|
+
async query(params = {}) {
|
|
3927
|
+
const result = await this.post(
|
|
3928
|
+
COMMERCE_ENDPOINTS.checkouts.server.query,
|
|
1764
3929
|
params
|
|
1765
3930
|
);
|
|
3931
|
+
return validateCheckoutQueryResult(result);
|
|
3932
|
+
}
|
|
3933
|
+
};
|
|
3934
|
+
|
|
3935
|
+
// src/core/api/payment-session-api.ts
|
|
3936
|
+
var PaymentSessionApi = class extends CustomerScopedApi {
|
|
3937
|
+
constructor(options) {
|
|
3938
|
+
super("PaymentSessionApi", { ...options, requiresCredential: false });
|
|
3939
|
+
this.serverTransport = Boolean(options.secretKey);
|
|
3940
|
+
}
|
|
3941
|
+
post(endpoint2, body, idempotencyKey) {
|
|
3942
|
+
return this.requestEndpoint(endpoint2, body, {
|
|
3943
|
+
...idempotencyKey && {
|
|
3944
|
+
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
3945
|
+
}
|
|
3946
|
+
});
|
|
3947
|
+
}
|
|
3948
|
+
async paymentSession(result) {
|
|
3949
|
+
return validatePublicPaymentSession(await result);
|
|
3950
|
+
}
|
|
3951
|
+
create(params) {
|
|
3952
|
+
const { idempotencyKey, ...body } = params;
|
|
3953
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3954
|
+
return this.paymentSession(
|
|
3955
|
+
this.post(
|
|
3956
|
+
this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
|
|
3957
|
+
body,
|
|
3958
|
+
idempotencyKey
|
|
3959
|
+
)
|
|
3960
|
+
);
|
|
3961
|
+
}
|
|
3962
|
+
retrieve(params) {
|
|
3963
|
+
const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
3964
|
+
return this.paymentSession(this.post(endpoint2, params));
|
|
3965
|
+
}
|
|
3966
|
+
cancel(params) {
|
|
3967
|
+
const { idempotencyKey, ...body } = params;
|
|
3968
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3969
|
+
const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
3970
|
+
return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
|
|
3971
|
+
}
|
|
3972
|
+
confirm(params) {
|
|
3973
|
+
const { idempotencyKey, ...body } = params;
|
|
3974
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3975
|
+
return this.paymentSession(
|
|
3976
|
+
this.post(
|
|
3977
|
+
COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
|
|
3978
|
+
body,
|
|
3979
|
+
idempotencyKey
|
|
3980
|
+
)
|
|
3981
|
+
);
|
|
1766
3982
|
}
|
|
1767
3983
|
};
|
|
1768
3984
|
|
|
@@ -2765,9 +4981,13 @@ function resolveVariantIdForCompleteSelection(matrix, selectedByOptionId) {
|
|
|
2765
4981
|
return getExactSelectedVariantEntry(matrix, normalized, matchingVariantEntries)?.id ?? null;
|
|
2766
4982
|
}
|
|
2767
4983
|
function buildSelectionPrice(variants) {
|
|
2768
|
-
const { min, max } = getMinMax(
|
|
4984
|
+
const { min, max } = getMinMax(
|
|
4985
|
+
variants.map((variant) => variant.resolvedPrice?.amount ?? variant.price)
|
|
4986
|
+
);
|
|
2769
4987
|
const { min: compareAtMin, max: compareAtMax } = getMinMax(
|
|
2770
|
-
variants.map(
|
|
4988
|
+
variants.map(
|
|
4989
|
+
(variant) => variant.resolvedPrice?.compareAtPrice ?? variant.compareAtPrice
|
|
4990
|
+
)
|
|
2771
4991
|
);
|
|
2772
4992
|
return {
|
|
2773
4993
|
min,
|
|
@@ -2827,8 +5047,8 @@ function buildSelectionStock(selectedVariant, matchingVariants) {
|
|
|
2827
5047
|
return {
|
|
2828
5048
|
availableForSale: getVariantAvailableForSale(selectedVariant),
|
|
2829
5049
|
isUnlimited: selectedVariant.isUnlimited,
|
|
2830
|
-
stock: selectedVariant.stock,
|
|
2831
|
-
reservedStock: selectedVariant.reservedStock,
|
|
5050
|
+
stock: "stock" in selectedVariant ? selectedVariant.stock : null,
|
|
5051
|
+
reservedStock: "reservedStock" in selectedVariant ? selectedVariant.reservedStock : null,
|
|
2832
5052
|
availableStock
|
|
2833
5053
|
};
|
|
2834
5054
|
}
|
|
@@ -3210,6 +5430,9 @@ function compareVariantOrder(a, b) {
|
|
|
3210
5430
|
}
|
|
3211
5431
|
function getVariantAvailableForSale(variant) {
|
|
3212
5432
|
if (variant.isActive === false) return false;
|
|
5433
|
+
if (typeof variant.availableForSale === "boolean") {
|
|
5434
|
+
return variant.availableForSale;
|
|
5435
|
+
}
|
|
3213
5436
|
if (variant.isUnlimited) return true;
|
|
3214
5437
|
if (variant.inventoryPolicy === "continue") return true;
|
|
3215
5438
|
return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
|
|
@@ -3323,7 +5546,7 @@ function buildProductListingCard(item, options = {}) {
|
|
|
3323
5546
|
{ listing: { selectionHintVariant } },
|
|
3324
5547
|
options
|
|
3325
5548
|
),
|
|
3326
|
-
title: product.title,
|
|
5549
|
+
title: product.title ?? "",
|
|
3327
5550
|
representativeVariant,
|
|
3328
5551
|
primaryImage: listingPrimaryMedia,
|
|
3329
5552
|
priceRange,
|
|
@@ -3510,6 +5733,11 @@ function productDetailResultFromError(error) {
|
|
|
3510
5733
|
if (!reason) return void 0;
|
|
3511
5734
|
return { found: false, reason };
|
|
3512
5735
|
}
|
|
5736
|
+
var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
|
|
5737
|
+
var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
|
|
5738
|
+
"priceRange.minVariantPrice.amount",
|
|
5739
|
+
"priceRange.maxVariantPrice.amount"
|
|
5740
|
+
]);
|
|
3513
5741
|
function nonEmpty(values) {
|
|
3514
5742
|
return values?.length ? values : void 0;
|
|
3515
5743
|
}
|
|
@@ -3557,14 +5785,34 @@ function buildProductListingPageWhere(params) {
|
|
|
3557
5785
|
if (clauses.length === 1) return clauses[0];
|
|
3558
5786
|
return { and: clauses };
|
|
3559
5787
|
}
|
|
3560
|
-
function
|
|
5788
|
+
function productListingPageUsesBasePriceSort(sort) {
|
|
5789
|
+
const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
|
|
5790
|
+
return values.some(
|
|
5791
|
+
(value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
|
|
5792
|
+
);
|
|
5793
|
+
}
|
|
5794
|
+
function assertMarketListingPageQuerySupported(params) {
|
|
5795
|
+
if (!params.market?.trim()) return;
|
|
5796
|
+
const priceFilter = params.filters?.price;
|
|
5797
|
+
if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
|
|
5798
|
+
throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
|
|
5799
|
+
}
|
|
5800
|
+
}
|
|
5801
|
+
function buildProductListingPageRequest(params) {
|
|
5802
|
+
assertMarketListingPageQuerySupported(params);
|
|
3561
5803
|
const options = {
|
|
5804
|
+
market: params.market,
|
|
5805
|
+
locale: params.locale,
|
|
5806
|
+
fallbackLocale: params.fallbackLocale,
|
|
3562
5807
|
page: params.page,
|
|
3563
5808
|
limit: params.limit,
|
|
3564
5809
|
sort: params.sort,
|
|
3565
5810
|
where: buildProductListingPageWhere(params)
|
|
3566
5811
|
};
|
|
3567
|
-
return
|
|
5812
|
+
return {
|
|
5813
|
+
operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
|
|
5814
|
+
query: listingPageSearchParams(options)
|
|
5815
|
+
};
|
|
3568
5816
|
}
|
|
3569
5817
|
function withProductListingCards(response, options) {
|
|
3570
5818
|
return {
|
|
@@ -3581,30 +5829,15 @@ function isProductUpsertFieldValidationErrorBody(value) {
|
|
|
3581
5829
|
return typeof body.error === "string" && typeof body.field === "string" && (reason === PRODUCT_UPSERT_UNKNOWN_FIELD_REASON || reason === PRODUCT_UPSERT_READONLY_FIELD_REASON);
|
|
3582
5830
|
}
|
|
3583
5831
|
|
|
3584
|
-
// src/core/api/order-api.ts
|
|
3585
|
-
function idempotencyRequestOptions(idempotencyKey) {
|
|
3586
|
-
return idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0;
|
|
3587
|
-
}
|
|
3588
|
-
function splitIdempotencyKey(params) {
|
|
3589
|
-
const { idempotencyKey, ...body } = params;
|
|
3590
|
-
return { body, idempotencyKey };
|
|
3591
|
-
}
|
|
3592
|
-
|
|
3593
5832
|
// src/core/commerce/commerce-client.ts
|
|
3594
5833
|
var BrowserCommerceApi = class extends CustomerScopedApi {
|
|
3595
|
-
|
|
3596
|
-
return
|
|
3597
|
-
method: "POST",
|
|
3598
|
-
body,
|
|
3599
|
-
headers: requestOptions?.headers
|
|
3600
|
-
});
|
|
3601
|
-
}
|
|
3602
|
-
get(endpoint) {
|
|
3603
|
-
return this.request(endpoint, { method: "GET" });
|
|
5834
|
+
requestEndpoint(endpoint2, body, options) {
|
|
5835
|
+
return super.requestEndpoint(endpoint2, body, options);
|
|
3604
5836
|
}
|
|
3605
5837
|
};
|
|
3606
5838
|
var CommerceClient = class {
|
|
3607
5839
|
constructor(options) {
|
|
5840
|
+
this.market = options.market;
|
|
3608
5841
|
const cartApi = new CartApi({
|
|
3609
5842
|
publishableKey: options.publishableKey,
|
|
3610
5843
|
apiUrl: options.apiUrl,
|
|
@@ -3612,6 +5845,20 @@ var CommerceClient = class {
|
|
|
3612
5845
|
onUnauthorized: options.onUnauthorized,
|
|
3613
5846
|
onRequestId: options.onRequestId
|
|
3614
5847
|
});
|
|
5848
|
+
const checkoutApi = new CheckoutApi({
|
|
5849
|
+
publishableKey: options.publishableKey,
|
|
5850
|
+
apiUrl: options.apiUrl,
|
|
5851
|
+
customerToken: options.customerToken,
|
|
5852
|
+
onUnauthorized: options.onUnauthorized,
|
|
5853
|
+
onRequestId: options.onRequestId
|
|
5854
|
+
});
|
|
5855
|
+
const paymentSessionApi = new PaymentSessionApi({
|
|
5856
|
+
publishableKey: options.publishableKey,
|
|
5857
|
+
apiUrl: options.apiUrl,
|
|
5858
|
+
customerToken: options.customerToken,
|
|
5859
|
+
onUnauthorized: options.onUnauthorized,
|
|
5860
|
+
onRequestId: options.onRequestId
|
|
5861
|
+
});
|
|
3615
5862
|
const api = new BrowserCommerceApi("CommerceClient", {
|
|
3616
5863
|
publishableKey: options.publishableKey,
|
|
3617
5864
|
apiUrl: options.apiUrl,
|
|
@@ -3620,29 +5867,42 @@ var CommerceClient = class {
|
|
|
3620
5867
|
onRequestId: options.onRequestId
|
|
3621
5868
|
});
|
|
3622
5869
|
this.product = {
|
|
3623
|
-
stockCheck: (params) => api.
|
|
3624
|
-
|
|
5870
|
+
stockCheck: (params) => api.requestEndpoint(
|
|
5871
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
|
|
3625
5872
|
params
|
|
3626
5873
|
),
|
|
3627
|
-
stockSnapshot: (params) => api.
|
|
3628
|
-
|
|
3629
|
-
|
|
5874
|
+
stockSnapshot: (params) => api.requestEndpoint(
|
|
5875
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
|
|
5876
|
+
void 0,
|
|
5877
|
+
{ query: stockSnapshotSearchParams(params) }
|
|
5878
|
+
),
|
|
5879
|
+
listingGroups: (params) => api.requestEndpoint(
|
|
5880
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
|
|
5881
|
+
void 0,
|
|
5882
|
+
{ query: listingGroupsSearchParams(this.withMarket(params)) }
|
|
3630
5883
|
),
|
|
3631
|
-
listingGroupsCatalog: (params) => api.
|
|
3632
|
-
|
|
5884
|
+
listingGroupsCatalog: (params) => api.requestEndpoint(
|
|
5885
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
|
|
5886
|
+
void 0,
|
|
5887
|
+
{ query: listingGroupsSearchParams(this.withMarket(params)) }
|
|
3633
5888
|
),
|
|
3634
5889
|
listingPage: async (params = {}) => {
|
|
3635
5890
|
const catalogParams = {
|
|
3636
5891
|
...params,
|
|
3637
5892
|
mode: "catalog"
|
|
3638
5893
|
};
|
|
3639
|
-
const
|
|
3640
|
-
|
|
5894
|
+
const request = buildProductListingPageRequest(
|
|
5895
|
+
this.withMarket(catalogParams)
|
|
5896
|
+
);
|
|
5897
|
+
const response = await api.requestEndpoint(request.operation, void 0, { query: request.query });
|
|
5898
|
+
return withProductListingCards(response, this.withMarket(catalogParams));
|
|
3641
5899
|
},
|
|
3642
5900
|
detail: async (params) => {
|
|
3643
5901
|
try {
|
|
3644
|
-
const product = await api.
|
|
3645
|
-
|
|
5902
|
+
const product = await api.requestEndpoint(
|
|
5903
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
|
|
5904
|
+
void 0,
|
|
5905
|
+
{ query: productDetailSearchParams(this.withMarket(params)) }
|
|
3646
5906
|
);
|
|
3647
5907
|
return { found: true, product };
|
|
3648
5908
|
} catch (err) {
|
|
@@ -3653,8 +5913,10 @@ var CommerceClient = class {
|
|
|
3653
5913
|
},
|
|
3654
5914
|
detailCatalog: async (params) => {
|
|
3655
5915
|
try {
|
|
3656
|
-
const product = await api.
|
|
3657
|
-
|
|
5916
|
+
const product = await api.requestEndpoint(
|
|
5917
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
|
|
5918
|
+
void 0,
|
|
5919
|
+
{ query: productDetailSearchParams(this.withMarket(params)) }
|
|
3658
5920
|
);
|
|
3659
5921
|
return { found: true, product };
|
|
3660
5922
|
} catch (err) {
|
|
@@ -3664,39 +5926,51 @@ var CommerceClient = class {
|
|
|
3664
5926
|
}
|
|
3665
5927
|
}
|
|
3666
5928
|
};
|
|
3667
|
-
this.
|
|
3668
|
-
create: cartApi.
|
|
3669
|
-
|
|
5929
|
+
this.carts = {
|
|
5930
|
+
create: (params) => cartApi.create(this.withMarket(params ?? {})),
|
|
5931
|
+
retrieve: cartApi.retrieve.bind(cartApi),
|
|
3670
5932
|
addItem: cartApi.addItem.bind(cartApi),
|
|
3671
5933
|
updateItem: cartApi.updateItem.bind(cartApi),
|
|
3672
5934
|
removeItem: cartApi.removeItem.bind(cartApi),
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
clear: cartApi.
|
|
5935
|
+
updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
|
|
5936
|
+
updateAttributes: cartApi.updateAttributes.bind(cartApi),
|
|
5937
|
+
clear: cartApi.clear.bind(cartApi),
|
|
3676
5938
|
merge: cartApi.merge.bind(cartApi),
|
|
3677
5939
|
mine: cartApi.mine.bind(cartApi)
|
|
3678
5940
|
};
|
|
3679
5941
|
this.orders = {
|
|
3680
|
-
checkout: (params) => {
|
|
3681
|
-
const { body, idempotencyKey } = splitIdempotencyKey(params);
|
|
3682
|
-
return api.post(
|
|
3683
|
-
"/api/orders/checkout",
|
|
3684
|
-
body,
|
|
3685
|
-
idempotencyRequestOptions(idempotencyKey)
|
|
3686
|
-
);
|
|
3687
|
-
},
|
|
3688
5942
|
listMine: (params) => options.customerAuth.getMyOrders(params)
|
|
3689
5943
|
};
|
|
5944
|
+
this.checkouts = {
|
|
5945
|
+
create: checkoutApi.create.bind(checkoutApi),
|
|
5946
|
+
retrieve: checkoutApi.retrieve.bind(checkoutApi)
|
|
5947
|
+
};
|
|
5948
|
+
this.paymentSessions = {
|
|
5949
|
+
create: paymentSessionApi.create.bind(paymentSessionApi),
|
|
5950
|
+
retrieve: (params) => paymentSessionApi.retrieve(params),
|
|
5951
|
+
cancel: (params) => paymentSessionApi.cancel(params)
|
|
5952
|
+
};
|
|
3690
5953
|
this.discounts = {
|
|
3691
|
-
validate: (params) => api.
|
|
5954
|
+
validate: (params) => api.requestEndpoint(
|
|
5955
|
+
COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
|
|
5956
|
+
params
|
|
5957
|
+
)
|
|
3692
5958
|
};
|
|
3693
5959
|
this.shipping = {
|
|
3694
|
-
calculate: (params) => api.
|
|
3695
|
-
|
|
5960
|
+
calculate: (params) => api.requestEndpoint(
|
|
5961
|
+
COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
|
|
3696
5962
|
params
|
|
3697
5963
|
)
|
|
3698
5964
|
};
|
|
3699
5965
|
}
|
|
5966
|
+
getDefaultMarket() {
|
|
5967
|
+
return this.market;
|
|
5968
|
+
}
|
|
5969
|
+
withMarket(params) {
|
|
5970
|
+
const defaultMarket = this.market?.trim();
|
|
5971
|
+
if (!defaultMarket || params.market?.trim()) return params;
|
|
5972
|
+
return { ...params, market: defaultMarket };
|
|
5973
|
+
}
|
|
3700
5974
|
};
|
|
3701
5975
|
|
|
3702
5976
|
// src/core/events/events-client.ts
|
|
@@ -3716,7 +5990,17 @@ var EventsClient = class {
|
|
|
3716
5990
|
getRange(params) {
|
|
3717
5991
|
return this.execute(
|
|
3718
5992
|
buildRangeEndpoint(params),
|
|
3719
|
-
|
|
5993
|
+
resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
|
|
5994
|
+
void 0,
|
|
5995
|
+
{ useCustomerAuth: false }
|
|
5996
|
+
);
|
|
5997
|
+
}
|
|
5998
|
+
getAdmissionAvailability(params) {
|
|
5999
|
+
return this.execute(
|
|
6000
|
+
buildAdmissionAvailabilityEndpoint(params),
|
|
6001
|
+
resolveOperationMethod(
|
|
6002
|
+
EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
|
|
6003
|
+
),
|
|
3720
6004
|
void 0,
|
|
3721
6005
|
{ useCustomerAuth: false }
|
|
3722
6006
|
);
|
|
@@ -3745,11 +6029,11 @@ var EventsClient = class {
|
|
|
3745
6029
|
{ useCustomerAuth: false }
|
|
3746
6030
|
);
|
|
3747
6031
|
}
|
|
3748
|
-
async execute(
|
|
6032
|
+
async execute(endpoint2, method, body, options = {}) {
|
|
3749
6033
|
const useCustomerAuth = options.useCustomerAuth === true;
|
|
3750
6034
|
const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
|
|
3751
6035
|
try {
|
|
3752
|
-
const response = await httpFetch(
|
|
6036
|
+
const response = await httpFetch(endpoint2, {
|
|
3753
6037
|
method,
|
|
3754
6038
|
apiUrl: this.apiUrl,
|
|
3755
6039
|
publishableKey: this.publishableKey,
|
|
@@ -3758,7 +6042,7 @@ var EventsClient = class {
|
|
|
3758
6042
|
...body !== void 0 && { body: JSON.stringify(body) }
|
|
3759
6043
|
});
|
|
3760
6044
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
3761
|
-
return parseApiResponse(response,
|
|
6045
|
+
return parseApiResponse(response, endpoint2);
|
|
3762
6046
|
} catch (err) {
|
|
3763
6047
|
const id = err instanceof SDKError ? err.requestId ?? null : null;
|
|
3764
6048
|
this.onRequestId?.(id);
|
|
@@ -3797,7 +6081,17 @@ function buildRangeEndpoint(params) {
|
|
|
3797
6081
|
appendValues(urlParams, "categorySlug", params.categorySlug);
|
|
3798
6082
|
appendValues(urlParams, "tag", params.tag);
|
|
3799
6083
|
appendValues(urlParams, "tagSlug", params.tagSlug);
|
|
3800
|
-
return
|
|
6084
|
+
return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
|
|
6085
|
+
query: urlParams
|
|
6086
|
+
});
|
|
6087
|
+
}
|
|
6088
|
+
function buildAdmissionAvailabilityEndpoint(params) {
|
|
6089
|
+
const urlParams = new URLSearchParams();
|
|
6090
|
+
urlParams.set("occurrence", params.occurrence);
|
|
6091
|
+
return resolveOperationPath(
|
|
6092
|
+
EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
|
|
6093
|
+
{ query: urlParams }
|
|
6094
|
+
);
|
|
3801
6095
|
}
|
|
3802
6096
|
function formatDateParam(value) {
|
|
3803
6097
|
return value instanceof Date ? value.toISOString() : value;
|
|
@@ -3810,15 +6104,62 @@ function appendValues(params, key, value) {
|
|
|
3810
6104
|
}
|
|
3811
6105
|
}
|
|
3812
6106
|
|
|
6107
|
+
// src/core/market/market-discovery.ts
|
|
6108
|
+
function toMarketDTO(row) {
|
|
6109
|
+
return {
|
|
6110
|
+
id: row.id,
|
|
6111
|
+
handle: row.handle,
|
|
6112
|
+
name: row.name,
|
|
6113
|
+
countryCode: row.countryCode,
|
|
6114
|
+
targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
|
|
6115
|
+
currency: row.currency,
|
|
6116
|
+
isPrimary: row.isPrimary === true,
|
|
6117
|
+
isActive: row.isActive === true
|
|
6118
|
+
};
|
|
6119
|
+
}
|
|
6120
|
+
var MarketDiscovery = class {
|
|
6121
|
+
constructor(read) {
|
|
6122
|
+
this.read = read;
|
|
6123
|
+
}
|
|
6124
|
+
async list() {
|
|
6125
|
+
const res = await this.read({
|
|
6126
|
+
where: { isActive: { equals: true } },
|
|
6127
|
+
limit: 100
|
|
6128
|
+
});
|
|
6129
|
+
if (res.hasNextPage) {
|
|
6130
|
+
console.warn(
|
|
6131
|
+
"[markets.list] more than 100 active markets; results truncated to 100."
|
|
6132
|
+
);
|
|
6133
|
+
}
|
|
6134
|
+
return res.docs.map(toMarketDTO);
|
|
6135
|
+
}
|
|
6136
|
+
async default() {
|
|
6137
|
+
const res = await this.read({
|
|
6138
|
+
where: { isPrimary: { equals: true }, isActive: { equals: true } },
|
|
6139
|
+
limit: 1
|
|
6140
|
+
});
|
|
6141
|
+
const row = res.docs[0];
|
|
6142
|
+
return row ? toMarketDTO(row) : null;
|
|
6143
|
+
}
|
|
6144
|
+
};
|
|
6145
|
+
|
|
3813
6146
|
// src/core/client/client.ts
|
|
3814
6147
|
var BrowserMembershipApi = class extends CustomerScopedApi {
|
|
3815
6148
|
me() {
|
|
3816
|
-
return this.
|
|
3817
|
-
|
|
3818
|
-
|
|
6149
|
+
return this.requestEndpoint(
|
|
6150
|
+
MEMBERSHIP_ENDPOINT_OPERATIONS.me
|
|
6151
|
+
);
|
|
6152
|
+
}
|
|
6153
|
+
cancel(params) {
|
|
6154
|
+
const { id, immediate } = params;
|
|
6155
|
+
return this.requestEndpoint(
|
|
6156
|
+
MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
|
|
6157
|
+
immediate !== void 0 ? { immediate } : {},
|
|
6158
|
+
{ pathParams: { id } }
|
|
6159
|
+
);
|
|
3819
6160
|
}
|
|
3820
6161
|
};
|
|
3821
|
-
var Client = class {
|
|
6162
|
+
var Client = class _Client {
|
|
3822
6163
|
constructor(options) {
|
|
3823
6164
|
this.lastRequestId = null;
|
|
3824
6165
|
const publishableKey = options.publishableKey;
|
|
@@ -3850,6 +6191,7 @@ var Client = class {
|
|
|
3850
6191
|
this.commerce = new CommerceClient({
|
|
3851
6192
|
publishableKey: this.config.publishableKey,
|
|
3852
6193
|
apiUrl: this.config.apiUrl,
|
|
6194
|
+
market: this.config.market,
|
|
3853
6195
|
customerToken: () => this.customer.auth.getToken(),
|
|
3854
6196
|
onUnauthorized,
|
|
3855
6197
|
onRequestId,
|
|
@@ -3882,6 +6224,9 @@ var Client = class {
|
|
|
3882
6224
|
onRequestId,
|
|
3883
6225
|
this.config.apiUrl
|
|
3884
6226
|
);
|
|
6227
|
+
this.markets = new MarketDiscovery(
|
|
6228
|
+
(options2) => this.collections.from("markets").find(options2)
|
|
6229
|
+
);
|
|
3885
6230
|
const membershipApi = new BrowserMembershipApi("MembershipApi", {
|
|
3886
6231
|
publishableKey: this.config.publishableKey,
|
|
3887
6232
|
apiUrl: this.config.apiUrl,
|
|
@@ -3890,12 +6235,23 @@ var Client = class {
|
|
|
3890
6235
|
onRequestId
|
|
3891
6236
|
});
|
|
3892
6237
|
this.memberships = {
|
|
3893
|
-
me: membershipApi.me.bind(membershipApi)
|
|
6238
|
+
me: membershipApi.me.bind(membershipApi),
|
|
6239
|
+
cancel: membershipApi.cancel.bind(membershipApi)
|
|
3894
6240
|
};
|
|
3895
6241
|
}
|
|
3896
6242
|
getState() {
|
|
3897
6243
|
return { ...this.state };
|
|
3898
6244
|
}
|
|
6245
|
+
withMarket(market) {
|
|
6246
|
+
return new _Client({
|
|
6247
|
+
...this.config,
|
|
6248
|
+
customer: this.config.customer?.persist === false ? {
|
|
6249
|
+
...this.config.customer,
|
|
6250
|
+
token: this.customer.auth.getToken() ?? void 0
|
|
6251
|
+
} : this.config.customer,
|
|
6252
|
+
market
|
|
6253
|
+
});
|
|
6254
|
+
}
|
|
3899
6255
|
getConfig() {
|
|
3900
6256
|
return { ...this.config };
|
|
3901
6257
|
}
|
|
@@ -3961,6 +6317,7 @@ var COMMERCE_NOTIFICATION_EVENTS = [
|
|
|
3961
6317
|
"returnRequested",
|
|
3962
6318
|
"returnApproved",
|
|
3963
6319
|
"returnRejected",
|
|
6320
|
+
"returnCanceled",
|
|
3964
6321
|
"returnCompleted"
|
|
3965
6322
|
];
|
|
3966
6323
|
function isStringOrNumber(value) {
|
|
@@ -4049,7 +6406,7 @@ function isCommerceNotificationWebhookEvent(event) {
|
|
|
4049
6406
|
if (notification.event === "fulfillmentShipped") {
|
|
4050
6407
|
return sourceCollection === "fulfillments" && matchesOptionalId(data.fulfillmentId, sourceId) && typeof notification.fulfillmentId === "string" && notification.fulfillmentId.length > 0 && matchesOptionalId(notification.fulfillmentId, sourceId) && matchesOptionalId(data.fulfillmentId, notification.fulfillmentId) && matchesOptionalId(changeSourceId, notification.fulfillmentId);
|
|
4051
6408
|
}
|
|
4052
|
-
if (notification.event === "returnRequested" || notification.event === "returnApproved" || notification.event === "returnRejected" || notification.event === "returnCompleted") {
|
|
6409
|
+
if (notification.event === "returnRequested" || notification.event === "returnApproved" || notification.event === "returnRejected" || notification.event === "returnCanceled" || notification.event === "returnCompleted") {
|
|
4053
6410
|
return sourceCollection === "returns" && matchesOptionalId(data.returnId, sourceId) && typeof notification.returnId === "string" && notification.returnId.length > 0 && matchesOptionalId(notification.returnId, sourceId) && matchesOptionalId(data.returnId, notification.returnId) && matchesOptionalId(changeSourceId, notification.returnId);
|
|
4054
6411
|
}
|
|
4055
6412
|
return false;
|
|
@@ -4083,8 +6440,8 @@ function createCommerceEmailWebhookHandler(handlers) {
|
|
|
4083
6440
|
function isWebhookCollection(event, collection) {
|
|
4084
6441
|
return isValidWebhookEvent(event) && event.collection === collection;
|
|
4085
6442
|
}
|
|
4086
|
-
function isWebhookOperation(event,
|
|
4087
|
-
return isValidWebhookEvent(event) && event.operation ===
|
|
6443
|
+
function isWebhookOperation(event, operation2) {
|
|
6444
|
+
return isValidWebhookEvent(event) && event.operation === operation2;
|
|
4088
6445
|
}
|
|
4089
6446
|
var CUSTOMER_PASSWORD_RESET_OPERATION = "password-reset";
|
|
4090
6447
|
function isRecord2(value) {
|
|
@@ -4111,7 +6468,7 @@ function createCustomerAuthWebhookHandler(handlers) {
|
|
|
4111
6468
|
await handlers.unhandled?.(event);
|
|
4112
6469
|
};
|
|
4113
6470
|
}
|
|
4114
|
-
async function verifySignature(payload, secret, signature,
|
|
6471
|
+
async function verifySignature(payload, secret, signature, timestamp2, deliveryId) {
|
|
4115
6472
|
const encoder = new TextEncoder();
|
|
4116
6473
|
const key = await crypto.subtle.importKey(
|
|
4117
6474
|
"raw",
|
|
@@ -4130,12 +6487,12 @@ async function verifySignature(payload, secret, signature, timestamp, deliveryId
|
|
|
4130
6487
|
"HMAC",
|
|
4131
6488
|
key,
|
|
4132
6489
|
sigBytes,
|
|
4133
|
-
encoder.encode(`${
|
|
6490
|
+
encoder.encode(`${timestamp2}.${deliveryId}.${payload}`)
|
|
4134
6491
|
);
|
|
4135
6492
|
}
|
|
4136
|
-
function timestampIsFresh(
|
|
4137
|
-
if (!/^\d+$/.test(
|
|
4138
|
-
const timestampMs = Number(
|
|
6493
|
+
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6494
|
+
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6495
|
+
const timestampMs = Number(timestamp2);
|
|
4139
6496
|
if (!Number.isFinite(timestampMs)) return false;
|
|
4140
6497
|
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
4141
6498
|
return skewMs <= toleranceSeconds * 1e3;
|
|
@@ -4145,14 +6502,14 @@ async function handleWebhook(request, handler, options) {
|
|
|
4145
6502
|
const rawBody = await request.text();
|
|
4146
6503
|
if (options?.secret) {
|
|
4147
6504
|
const signature = request.headers.get("x-webhook-signature") || "";
|
|
4148
|
-
const
|
|
6505
|
+
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
4149
6506
|
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
4150
6507
|
const toleranceSeconds = options.toleranceSeconds ?? 300;
|
|
4151
|
-
const valid = Boolean(
|
|
6508
|
+
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(
|
|
4152
6509
|
rawBody,
|
|
4153
6510
|
options.secret,
|
|
4154
6511
|
signature,
|
|
4155
|
-
|
|
6512
|
+
timestamp2,
|
|
4156
6513
|
deliveryId
|
|
4157
6514
|
);
|
|
4158
6515
|
if (!valid) {
|
|
@@ -4216,12 +6573,21 @@ var INTERNAL_COLLECTIONS = [
|
|
|
4216
6573
|
"analytics-event-schemas",
|
|
4217
6574
|
"subscriptions",
|
|
4218
6575
|
"billing-history",
|
|
6576
|
+
"usage-rate-cards",
|
|
6577
|
+
"usage-invoices",
|
|
4219
6578
|
"inventory-reservations",
|
|
4220
6579
|
"inventory-adjustments",
|
|
6580
|
+
"payment-sessions",
|
|
6581
|
+
"payment-event-inbox",
|
|
6582
|
+
"payment-refund-attempts",
|
|
6583
|
+
"portone-payment-interactions",
|
|
4221
6584
|
"commerce-notification-intents",
|
|
6585
|
+
"commerce-idempotency-records",
|
|
4222
6586
|
"product-collection-items",
|
|
4223
6587
|
"order-status-logs",
|
|
6588
|
+
"fulfillment-events",
|
|
4224
6589
|
"tenant-commerce-config",
|
|
6590
|
+
"customer-oauth-clients",
|
|
4225
6591
|
"api-keys",
|
|
4226
6592
|
"personal-access-tokens",
|
|
4227
6593
|
"tenant-entitlements",
|
|
@@ -4229,12 +6595,18 @@ var INTERNAL_COLLECTIONS = [
|
|
|
4229
6595
|
"direct-upload-sessions",
|
|
4230
6596
|
"webhook-events",
|
|
4231
6597
|
"webhook-deliveries",
|
|
6598
|
+
"webhook-outbox-deliveries",
|
|
4232
6599
|
"audit-logs",
|
|
4233
6600
|
"plans",
|
|
4234
6601
|
"webhooks",
|
|
6602
|
+
"custom-field-definitions",
|
|
4235
6603
|
"event-registrations",
|
|
6604
|
+
"event-admission-holds",
|
|
6605
|
+
"event-admission-types",
|
|
4236
6606
|
"customer-payment-methods",
|
|
4237
|
-
"tenant-payment-credentials"
|
|
6607
|
+
"tenant-payment-credentials",
|
|
6608
|
+
"commerce-payment-accounts",
|
|
6609
|
+
"payment-provider-customer-aliases"
|
|
4238
6610
|
];
|
|
4239
6611
|
var COLLECTIONS = [
|
|
4240
6612
|
"tenants",
|
|
@@ -4293,6 +6665,7 @@ var COLLECTIONS = [
|
|
|
4293
6665
|
"event-occurrences",
|
|
4294
6666
|
"event-tags",
|
|
4295
6667
|
"membership-plans",
|
|
6668
|
+
"membership-plan-prices",
|
|
4296
6669
|
"customer-memberships"
|
|
4297
6670
|
];
|
|
4298
6671
|
var SERVER_ONLY_COLLECTIONS = [
|
|
@@ -4301,9 +6674,14 @@ var SERVER_ONLY_COLLECTIONS = [
|
|
|
4301
6674
|
"images",
|
|
4302
6675
|
"videos",
|
|
4303
6676
|
"orders",
|
|
6677
|
+
"order-tags",
|
|
4304
6678
|
"order-items",
|
|
4305
6679
|
"returns",
|
|
4306
6680
|
"return-items",
|
|
6681
|
+
"refunds",
|
|
6682
|
+
"refund-line-items",
|
|
6683
|
+
"order-edit-sessions",
|
|
6684
|
+
"order-staged-changes",
|
|
4307
6685
|
"fulfillment-orders",
|
|
4308
6686
|
"fulfillment-order-items",
|
|
4309
6687
|
"fulfillments",
|
|
@@ -4316,6 +6694,8 @@ var SERVER_ONLY_COLLECTIONS = [
|
|
|
4316
6694
|
"cart-items",
|
|
4317
6695
|
"checkouts",
|
|
4318
6696
|
"checkout-items",
|
|
6697
|
+
"draft-orders",
|
|
6698
|
+
"draft-order-items",
|
|
4319
6699
|
"posts",
|
|
4320
6700
|
"comments",
|
|
4321
6701
|
"reactions",
|
|
@@ -4711,9 +7091,9 @@ var generateOrderNumber = () => {
|
|
|
4711
7091
|
const year = now.getFullYear().toString().slice(-2);
|
|
4712
7092
|
const month = (now.getMonth() + 1).toString().padStart(2, "0");
|
|
4713
7093
|
const day = now.getDate().toString().padStart(2, "0");
|
|
4714
|
-
const
|
|
4715
|
-
globalThis.crypto.getRandomValues(
|
|
4716
|
-
const random = ((
|
|
7094
|
+
const array2 = new Uint32Array(1);
|
|
7095
|
+
globalThis.crypto.getRandomValues(array2);
|
|
7096
|
+
const random = ((array2[0] ?? 0) % 1e6).toString().padStart(6, "0");
|
|
4717
7097
|
return `${year}${month}${day}${random}`;
|
|
4718
7098
|
};
|
|
4719
7099
|
|
|
@@ -4764,7 +7144,7 @@ function createAnalytics(config) {
|
|
|
4764
7144
|
}, destroy() {
|
|
4765
7145
|
} };
|
|
4766
7146
|
}
|
|
4767
|
-
const
|
|
7147
|
+
const endpoint2 = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
|
|
4768
7148
|
const respectDnt = config.respectDnt !== false;
|
|
4769
7149
|
function isDntActive() {
|
|
4770
7150
|
if (!respectDnt) return false;
|
|
@@ -4805,10 +7185,10 @@ function createAnalytics(config) {
|
|
|
4805
7185
|
try {
|
|
4806
7186
|
if (typeof navigator.sendBeacon === "function") {
|
|
4807
7187
|
const blob = new Blob([body], { type: "text/plain" });
|
|
4808
|
-
const sent = navigator.sendBeacon(
|
|
7188
|
+
const sent = navigator.sendBeacon(endpoint2, blob);
|
|
4809
7189
|
if (sent) return;
|
|
4810
7190
|
}
|
|
4811
|
-
fetch(
|
|
7191
|
+
fetch(endpoint2, {
|
|
4812
7192
|
method: "POST",
|
|
4813
7193
|
keepalive: true,
|
|
4814
7194
|
headers: { "Content-Type": "application/json" },
|
|
@@ -4958,11 +7338,11 @@ export {
|
|
|
4958
7338
|
ApiError,
|
|
4959
7339
|
AuthError,
|
|
4960
7340
|
COLLECTIONS,
|
|
7341
|
+
COMMERCE_ERROR_CODES,
|
|
4961
7342
|
COMMERCE_NOTIFICATION_EVENTS,
|
|
4962
7343
|
COMMERCE_NOTIFICATION_EVENT_TYPE,
|
|
4963
7344
|
COMMERCE_NOTIFICATION_OPERATION,
|
|
4964
7345
|
CUSTOMER_PASSWORD_RESET_OPERATION,
|
|
4965
|
-
CartApi,
|
|
4966
7346
|
CommerceClient,
|
|
4967
7347
|
CommunityClient,
|
|
4968
7348
|
ConfigError,
|
|
@@ -4970,10 +7350,12 @@ export {
|
|
|
4970
7350
|
ContentClient,
|
|
4971
7351
|
CustomerAuth,
|
|
4972
7352
|
CustomerNamespace,
|
|
7353
|
+
CustomerOAuth,
|
|
4973
7354
|
EventsClient,
|
|
4974
7355
|
GoneError,
|
|
4975
7356
|
IMAGE_SIZES,
|
|
4976
7357
|
INTERNAL_COLLECTIONS,
|
|
7358
|
+
MAX_CART_LINE_ADMISSIONS,
|
|
4977
7359
|
NetworkError,
|
|
4978
7360
|
NotFoundError,
|
|
4979
7361
|
ORDER_CHANGED_EVENT_TYPE,
|
|
@@ -4991,6 +7373,7 @@ export {
|
|
|
4991
7373
|
TimeoutError,
|
|
4992
7374
|
UsageLimitError,
|
|
4993
7375
|
ValidationError,
|
|
7376
|
+
assertCommerceIdempotencyKey,
|
|
4994
7377
|
buildProductHref,
|
|
4995
7378
|
buildProductListingCard,
|
|
4996
7379
|
buildProductListingGroupProjection,
|
|
@@ -5001,6 +7384,7 @@ export {
|
|
|
5001
7384
|
createAuthError,
|
|
5002
7385
|
createClient2 as createClient,
|
|
5003
7386
|
createCommerceEmailWebhookHandler,
|
|
7387
|
+
createCommerceIdempotencyKey,
|
|
5004
7388
|
createCommerceNotificationWebhookHandler,
|
|
5005
7389
|
createConflictError,
|
|
5006
7390
|
createCustomerAuthWebhookHandler,
|
|
@@ -5031,7 +7415,9 @@ export {
|
|
|
5031
7415
|
handleWebhook,
|
|
5032
7416
|
isApiError,
|
|
5033
7417
|
isAuthError,
|
|
7418
|
+
isCommerceIdempotencyKey,
|
|
5034
7419
|
isCommerceNotificationWebhookEvent,
|
|
7420
|
+
isCommerceSDKError,
|
|
5035
7421
|
isConfigError,
|
|
5036
7422
|
isConflictError,
|
|
5037
7423
|
isCustomerPasswordResetWebhookEvent,
|