@01.software/sdk 0.44.0 → 0.45.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 +358 -2
- package/MIGRATION.md +89 -10
- package/README.md +441 -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 +2680 -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 +2680 -345
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-Dyl-CDcj.d.cts → collection-client-BSo7VXQE.d.cts} +8 -5
- package/dist/{collection-client-DWooaiTr.d.ts → collection-client-Ckfusuee.d.ts} +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 +2741 -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 +2741 -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 +550 -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 +550 -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 +2252 -444
- 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 +2252 -444
- 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-BlOvjoTX.d.ts} +1095 -509
- package/dist/{types-Dt9FJisi.d.ts → types-C4WuJfw7.d.cts} +1095 -509
- package/dist/types-D5p7-m1l.d.cts +47 -0
- 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 +12 -11
- package/dist/types-SoXsbKhj.d.cts +0 -33
- package/dist/types-oiae_LMm.d.ts +0 -33
package/dist/index.cjs
CHANGED
|
@@ -23,11 +23,11 @@ __export(src_exports, {
|
|
|
23
23
|
ApiError: () => ApiError,
|
|
24
24
|
AuthError: () => AuthError,
|
|
25
25
|
COLLECTIONS: () => COLLECTIONS,
|
|
26
|
+
COMMERCE_ERROR_CODES: () => COMMERCE_ERROR_CODES,
|
|
26
27
|
COMMERCE_NOTIFICATION_EVENTS: () => COMMERCE_NOTIFICATION_EVENTS,
|
|
27
28
|
COMMERCE_NOTIFICATION_EVENT_TYPE: () => COMMERCE_NOTIFICATION_EVENT_TYPE,
|
|
28
29
|
COMMERCE_NOTIFICATION_OPERATION: () => COMMERCE_NOTIFICATION_OPERATION,
|
|
29
30
|
CUSTOMER_PASSWORD_RESET_OPERATION: () => CUSTOMER_PASSWORD_RESET_OPERATION,
|
|
30
|
-
CartApi: () => CartApi,
|
|
31
31
|
CommerceClient: () => CommerceClient,
|
|
32
32
|
CommunityClient: () => CommunityClient,
|
|
33
33
|
ConfigError: () => ConfigError,
|
|
@@ -35,10 +35,12 @@ __export(src_exports, {
|
|
|
35
35
|
ContentClient: () => ContentClient,
|
|
36
36
|
CustomerAuth: () => CustomerAuth,
|
|
37
37
|
CustomerNamespace: () => CustomerNamespace,
|
|
38
|
+
CustomerOAuth: () => CustomerOAuth,
|
|
38
39
|
EventsClient: () => EventsClient,
|
|
39
40
|
GoneError: () => GoneError,
|
|
40
41
|
IMAGE_SIZES: () => IMAGE_SIZES,
|
|
41
42
|
INTERNAL_COLLECTIONS: () => INTERNAL_COLLECTIONS,
|
|
43
|
+
MAX_CART_LINE_ADMISSIONS: () => MAX_CART_LINE_ADMISSIONS,
|
|
42
44
|
NetworkError: () => NetworkError,
|
|
43
45
|
NotFoundError: () => NotFoundError,
|
|
44
46
|
ORDER_CHANGED_EVENT_TYPE: () => ORDER_CHANGED_EVENT_TYPE,
|
|
@@ -56,6 +58,7 @@ __export(src_exports, {
|
|
|
56
58
|
TimeoutError: () => TimeoutError,
|
|
57
59
|
UsageLimitError: () => UsageLimitError,
|
|
58
60
|
ValidationError: () => ValidationError,
|
|
61
|
+
assertCommerceIdempotencyKey: () => assertCommerceIdempotencyKey,
|
|
59
62
|
buildProductHref: () => buildProductHref,
|
|
60
63
|
buildProductListingCard: () => buildProductListingCard,
|
|
61
64
|
buildProductListingGroupProjection: () => buildProductListingGroupProjection,
|
|
@@ -66,6 +69,7 @@ __export(src_exports, {
|
|
|
66
69
|
createAuthError: () => createAuthError,
|
|
67
70
|
createClient: () => createClient2,
|
|
68
71
|
createCommerceEmailWebhookHandler: () => createCommerceEmailWebhookHandler,
|
|
72
|
+
createCommerceIdempotencyKey: () => createCommerceIdempotencyKey,
|
|
69
73
|
createCommerceNotificationWebhookHandler: () => createCommerceNotificationWebhookHandler,
|
|
70
74
|
createConflictError: () => createConflictError,
|
|
71
75
|
createCustomerAuthWebhookHandler: () => createCustomerAuthWebhookHandler,
|
|
@@ -96,7 +100,9 @@ __export(src_exports, {
|
|
|
96
100
|
handleWebhook: () => handleWebhook,
|
|
97
101
|
isApiError: () => isApiError,
|
|
98
102
|
isAuthError: () => isAuthError,
|
|
103
|
+
isCommerceIdempotencyKey: () => isCommerceIdempotencyKey,
|
|
99
104
|
isCommerceNotificationWebhookEvent: () => isCommerceNotificationWebhookEvent,
|
|
105
|
+
isCommerceSDKError: () => isCommerceSDKError,
|
|
100
106
|
isConfigError: () => isConfigError,
|
|
101
107
|
isConflictError: () => isConflictError,
|
|
102
108
|
isCustomerPasswordResetWebhookEvent: () => isCustomerPasswordResetWebhookEvent,
|
|
@@ -167,10 +173,136 @@ var SDKError = class extends Error {
|
|
|
167
173
|
details: this.details,
|
|
168
174
|
userMessage: this.userMessage,
|
|
169
175
|
suggestion: this.suggestion,
|
|
170
|
-
...this.requestId !== void 0 && { requestId: this.requestId }
|
|
176
|
+
...this.requestId !== void 0 && { requestId: this.requestId },
|
|
177
|
+
...this.kind !== void 0 && { kind: this.kind },
|
|
178
|
+
...this.reason !== void 0 && { reason: this.reason },
|
|
179
|
+
...this.rawReason !== void 0 && { rawReason: this.rawReason },
|
|
180
|
+
...this.retryable !== void 0 && { retryable: this.retryable },
|
|
181
|
+
...this.retryAfter !== void 0 && { retryAfter: this.retryAfter }
|
|
171
182
|
};
|
|
172
183
|
}
|
|
173
184
|
};
|
|
185
|
+
var COMMERCE_ERROR_CODES = [
|
|
186
|
+
"validation_failed",
|
|
187
|
+
"unauthorized",
|
|
188
|
+
"forbidden",
|
|
189
|
+
"token_expired",
|
|
190
|
+
"origin_not_allowed",
|
|
191
|
+
"server_credentials_required",
|
|
192
|
+
"not_found",
|
|
193
|
+
"conflict",
|
|
194
|
+
"cart_revision_conflict",
|
|
195
|
+
"rate_limit_exceeded",
|
|
196
|
+
"usage_limit_exceeded",
|
|
197
|
+
"service_unavailable",
|
|
198
|
+
"idempotency_conflict",
|
|
199
|
+
"idempotency_in_progress",
|
|
200
|
+
"cart_not_active",
|
|
201
|
+
"cart_locked",
|
|
202
|
+
"cart_empty",
|
|
203
|
+
"cart_market_unavailable",
|
|
204
|
+
"cart_market_mismatch",
|
|
205
|
+
"checkout_not_open",
|
|
206
|
+
"payment_slot_held",
|
|
207
|
+
"reservation_expired",
|
|
208
|
+
"payment_session_not_cancelable",
|
|
209
|
+
"provider_identity_mismatch",
|
|
210
|
+
"provider_unavailable",
|
|
211
|
+
"lock_timeout",
|
|
212
|
+
"price_changed",
|
|
213
|
+
"pricing_fact_in_use",
|
|
214
|
+
"insufficient_stock",
|
|
215
|
+
"market_not_found",
|
|
216
|
+
"market_shipping_currency_unsupported",
|
|
217
|
+
"missing_market_rate",
|
|
218
|
+
"missing_shipping_amount",
|
|
219
|
+
"no_enabled_payment_provider",
|
|
220
|
+
"product_market_unavailable",
|
|
221
|
+
"unsupported_currency",
|
|
222
|
+
"missing_price_row",
|
|
223
|
+
"payment_provider_currency_unsupported",
|
|
224
|
+
"discount_code_not_found",
|
|
225
|
+
"discount_not_started",
|
|
226
|
+
"discount_expired",
|
|
227
|
+
"discount_usage_limit",
|
|
228
|
+
"discount_per_customer_limit",
|
|
229
|
+
"discount_customer_required",
|
|
230
|
+
"discount_first_order_only",
|
|
231
|
+
"discount_customer_not_eligible",
|
|
232
|
+
"discount_customer_excluded",
|
|
233
|
+
"discount_items_required",
|
|
234
|
+
"discount_product_not_eligible",
|
|
235
|
+
"discount_product_excluded",
|
|
236
|
+
"discount_min_order_amount",
|
|
237
|
+
"discount_currency_scope_required",
|
|
238
|
+
"discount_allocation_method_unsupported",
|
|
239
|
+
"currency_mismatch"
|
|
240
|
+
];
|
|
241
|
+
var COMMERCE_ERROR_CODE_SET = new Set(
|
|
242
|
+
COMMERCE_ERROR_CODES
|
|
243
|
+
);
|
|
244
|
+
var COMMERCE_ERROR_ENVELOPE_KEYS = /* @__PURE__ */ new Set([
|
|
245
|
+
"error",
|
|
246
|
+
"reason",
|
|
247
|
+
"requestId",
|
|
248
|
+
"retryable",
|
|
249
|
+
"details"
|
|
250
|
+
]);
|
|
251
|
+
function isPlainRecord(value) {
|
|
252
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
253
|
+
}
|
|
254
|
+
function commerceProtocolError(issue, trustedRequestId) {
|
|
255
|
+
return createApiError(
|
|
256
|
+
"Invalid canonical commerce error response.",
|
|
257
|
+
502,
|
|
258
|
+
{ protocol: "commerce-error-envelope", issue },
|
|
259
|
+
"The server returned an incompatible commerce error response.",
|
|
260
|
+
"Verify that the Console commerce contract is deployed before using this SDK version.",
|
|
261
|
+
trustedRequestId
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
function parseCommerceErrorEnvelope(body, headerRequestId) {
|
|
265
|
+
if (!isPlainRecord(body)) {
|
|
266
|
+
throw commerceProtocolError("expected_object", headerRequestId);
|
|
267
|
+
}
|
|
268
|
+
if (Object.keys(body).some((key) => !COMMERCE_ERROR_ENVELOPE_KEYS.has(key))) {
|
|
269
|
+
throw commerceProtocolError("unexpected_field", headerRequestId);
|
|
270
|
+
}
|
|
271
|
+
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)) {
|
|
272
|
+
throw commerceProtocolError("invalid_field", headerRequestId);
|
|
273
|
+
}
|
|
274
|
+
if (headerRequestId && headerRequestId !== body.requestId) {
|
|
275
|
+
throw commerceProtocolError("request_id_mismatch", headerRequestId);
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
error: body.error,
|
|
279
|
+
reason: body.reason,
|
|
280
|
+
requestId: body.requestId,
|
|
281
|
+
retryable: body.retryable === true,
|
|
282
|
+
...body.details === void 0 ? {} : { details: body.details }
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function enhanceCommerceError(error, body, headerRequestId) {
|
|
286
|
+
const envelope = parseCommerceErrorEnvelope(body, headerRequestId);
|
|
287
|
+
const known = COMMERCE_ERROR_CODE_SET.has(envelope.reason);
|
|
288
|
+
Object.assign(error, {
|
|
289
|
+
code: envelope.reason,
|
|
290
|
+
kind: "commerce",
|
|
291
|
+
reason: known ? envelope.reason : "unknown_commerce_error",
|
|
292
|
+
...known ? {} : { rawReason: envelope.reason },
|
|
293
|
+
requestId: envelope.requestId,
|
|
294
|
+
retryable: envelope.retryable,
|
|
295
|
+
details: envelope.details
|
|
296
|
+
});
|
|
297
|
+
return error;
|
|
298
|
+
}
|
|
299
|
+
function isCommerceSDKError(error) {
|
|
300
|
+
if (!(error instanceof SDKError) || error.kind !== "commerce") return false;
|
|
301
|
+
if (typeof error.requestId !== "string" || typeof error.retryable !== "boolean" || error.retryAfter !== void 0 && (!Number.isSafeInteger(error.retryAfter) || error.retryAfter < 0) || typeof error.reason !== "string") {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
return error.reason === "unknown_commerce_error" ? typeof error.rawReason === "string" : COMMERCE_ERROR_CODE_SET.has(error.reason) && error.rawReason === void 0;
|
|
305
|
+
}
|
|
174
306
|
var NetworkError = class extends SDKError {
|
|
175
307
|
constructor(message, status, details, userMessage, suggestion) {
|
|
176
308
|
super("NETWORK_ERROR", message, status, details, userMessage, suggestion);
|
|
@@ -409,6 +541,7 @@ var NON_RETRYABLE_STATUSES = [400, 401, 403, 404, 409, 422];
|
|
|
409
541
|
var SAFE_METHODS = ["GET", "HEAD", "OPTIONS"];
|
|
410
542
|
var DEFAULT_MAX_RETRIES = 3;
|
|
411
543
|
var STOREFRONT_BROWSER_MAX_RETRIES = 1;
|
|
544
|
+
var MAX_AUTOMATIC_RETRY_AFTER_SECONDS = 5 * 60;
|
|
412
545
|
function debugLog(debug, type, message, data) {
|
|
413
546
|
if (!debug) return;
|
|
414
547
|
const shouldLog = debug === true || type === "request" && debug.logRequests || type === "response" && debug.logResponses || type === "error" && debug.logErrors;
|
|
@@ -523,116 +656,129 @@ function attachRequestId(err, id) {
|
|
|
523
656
|
}
|
|
524
657
|
function parseRetryAfter(response) {
|
|
525
658
|
const raw = response.headers.get("Retry-After");
|
|
526
|
-
if (!raw) return
|
|
527
|
-
|
|
659
|
+
if (!raw) return { permitsAutomaticRetry: true };
|
|
660
|
+
const trimmed = raw.trim();
|
|
661
|
+
let seconds;
|
|
662
|
+
if (/^\d+$/.test(trimmed)) {
|
|
663
|
+
seconds = Number(trimmed);
|
|
664
|
+
if (!Number.isSafeInteger(seconds)) {
|
|
665
|
+
return { permitsAutomaticRetry: false };
|
|
666
|
+
}
|
|
667
|
+
} else {
|
|
668
|
+
const retryAt = Date.parse(trimmed);
|
|
669
|
+
if (!Number.isFinite(retryAt)) return { permitsAutomaticRetry: true };
|
|
670
|
+
seconds = Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
seconds,
|
|
674
|
+
permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
|
|
675
|
+
};
|
|
528
676
|
}
|
|
529
|
-
function mapResponseToError(status, parsed, details, requestId, retryAfter) {
|
|
677
|
+
function mapResponseToError(status, parsed, details, requestId, retryAfter, errorFamily) {
|
|
530
678
|
const errorDetails = {
|
|
531
679
|
...details,
|
|
532
680
|
...parsed.errors && { errors: parsed.errors },
|
|
533
|
-
...parsed.body && { body: parsed.body }
|
|
681
|
+
...errorFamily !== "commerce" && parsed.body && { body: parsed.body }
|
|
534
682
|
};
|
|
535
683
|
const suggestion = getParsedErrorSuggestion(status, parsed);
|
|
684
|
+
const finalize = (error) => {
|
|
685
|
+
const withRequestId = attachRequestId(error, requestId);
|
|
686
|
+
if (retryAfter !== void 0) {
|
|
687
|
+
Object.assign(withRequestId, { retryAfter });
|
|
688
|
+
}
|
|
689
|
+
return errorFamily === "commerce" ? enhanceCommerceError(withRequestId, parsed.body, requestId) : withRequestId;
|
|
690
|
+
};
|
|
536
691
|
if (status === 400 || status === 422) {
|
|
537
|
-
return
|
|
692
|
+
return finalize(
|
|
538
693
|
createValidationError(
|
|
539
694
|
parsed.errorMessage,
|
|
540
695
|
errorDetails,
|
|
541
696
|
parsed.userMessage,
|
|
542
697
|
suggestion,
|
|
543
698
|
status
|
|
544
|
-
)
|
|
545
|
-
requestId
|
|
699
|
+
)
|
|
546
700
|
);
|
|
547
701
|
}
|
|
548
702
|
if (status === 401) {
|
|
549
|
-
return
|
|
703
|
+
return finalize(
|
|
550
704
|
createAuthError(
|
|
551
705
|
parsed.errorMessage,
|
|
552
706
|
errorDetails,
|
|
553
707
|
parsed.userMessage,
|
|
554
708
|
suggestion
|
|
555
|
-
)
|
|
556
|
-
requestId
|
|
709
|
+
)
|
|
557
710
|
);
|
|
558
711
|
}
|
|
559
712
|
if (status === 403) {
|
|
560
|
-
return
|
|
713
|
+
return finalize(
|
|
561
714
|
createPermissionError(
|
|
562
715
|
parsed.errorMessage,
|
|
563
716
|
errorDetails,
|
|
564
717
|
parsed.userMessage,
|
|
565
718
|
suggestion
|
|
566
|
-
)
|
|
567
|
-
requestId
|
|
719
|
+
)
|
|
568
720
|
);
|
|
569
721
|
}
|
|
570
722
|
if (status === 404) {
|
|
571
|
-
return
|
|
723
|
+
return finalize(
|
|
572
724
|
createNotFoundError(
|
|
573
725
|
parsed.errorMessage,
|
|
574
726
|
errorDetails,
|
|
575
727
|
parsed.userMessage,
|
|
576
728
|
suggestion
|
|
577
|
-
)
|
|
578
|
-
requestId
|
|
729
|
+
)
|
|
579
730
|
);
|
|
580
731
|
}
|
|
581
732
|
if (status === 409) {
|
|
582
|
-
return
|
|
733
|
+
return finalize(
|
|
583
734
|
createConflictError(
|
|
584
735
|
parsed.errorMessage,
|
|
585
736
|
errorDetails,
|
|
586
737
|
parsed.userMessage,
|
|
587
738
|
suggestion
|
|
588
|
-
)
|
|
589
|
-
requestId
|
|
739
|
+
)
|
|
590
740
|
);
|
|
591
741
|
}
|
|
592
742
|
if (status === 410) {
|
|
593
|
-
return
|
|
743
|
+
return finalize(
|
|
594
744
|
createGoneError(
|
|
595
745
|
parsed.errorMessage,
|
|
596
746
|
errorDetails,
|
|
597
747
|
parsed.userMessage,
|
|
598
748
|
suggestion
|
|
599
|
-
)
|
|
600
|
-
requestId
|
|
749
|
+
)
|
|
601
750
|
);
|
|
602
751
|
}
|
|
603
752
|
if (status === 429) {
|
|
604
|
-
return
|
|
753
|
+
return finalize(
|
|
605
754
|
createRateLimitError(
|
|
606
755
|
parsed.errorMessage,
|
|
607
756
|
retryAfter,
|
|
608
757
|
errorDetails,
|
|
609
758
|
parsed.userMessage,
|
|
610
759
|
suggestion
|
|
611
|
-
)
|
|
612
|
-
requestId
|
|
760
|
+
)
|
|
613
761
|
);
|
|
614
762
|
}
|
|
615
763
|
if (status === 503) {
|
|
616
|
-
return
|
|
764
|
+
return finalize(
|
|
617
765
|
createServiceUnavailableError(
|
|
618
766
|
parsed.errorMessage,
|
|
619
767
|
retryAfter,
|
|
620
768
|
errorDetails,
|
|
621
769
|
parsed.userMessage,
|
|
622
770
|
suggestion
|
|
623
|
-
)
|
|
624
|
-
requestId
|
|
771
|
+
)
|
|
625
772
|
);
|
|
626
773
|
}
|
|
627
|
-
return
|
|
774
|
+
return finalize(
|
|
628
775
|
createNetworkError(
|
|
629
776
|
parsed.errorMessage,
|
|
630
777
|
status,
|
|
631
778
|
errorDetails,
|
|
632
779
|
parsed.userMessage,
|
|
633
780
|
suggestion
|
|
634
|
-
)
|
|
635
|
-
requestId
|
|
781
|
+
)
|
|
636
782
|
);
|
|
637
783
|
}
|
|
638
784
|
async function httpFetch(url, options) {
|
|
@@ -645,6 +791,7 @@ async function httpFetch(url, options) {
|
|
|
645
791
|
debug,
|
|
646
792
|
retry,
|
|
647
793
|
onUnauthorized,
|
|
794
|
+
errorFamily,
|
|
648
795
|
...requestInit
|
|
649
796
|
} = options || {};
|
|
650
797
|
const baseUrl = resolveApiUrl(apiUrl);
|
|
@@ -697,6 +844,8 @@ async function httpFetch(url, options) {
|
|
|
697
844
|
headers: redactSensitiveHeaders(response.headers)
|
|
698
845
|
});
|
|
699
846
|
if (!response.ok) {
|
|
847
|
+
const parsed = await parseErrorBody(response);
|
|
848
|
+
const commerceEnvelope = errorFamily === "commerce" ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
|
|
700
849
|
if (isUsageLimitExceededResponse(response)) {
|
|
701
850
|
const limit = parseInt(
|
|
702
851
|
response.headers.get("X-Usage-Limit") || "0",
|
|
@@ -710,7 +859,7 @@ async function httpFetch(url, options) {
|
|
|
710
859
|
response.headers.get("X-Usage-Remaining") || "0",
|
|
711
860
|
10
|
|
712
861
|
);
|
|
713
|
-
|
|
862
|
+
const usageError = attachRequestId(
|
|
714
863
|
createUsageLimitError(
|
|
715
864
|
`Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
|
|
716
865
|
{ limit, current, remaining },
|
|
@@ -724,9 +873,9 @@ async function httpFetch(url, options) {
|
|
|
724
873
|
),
|
|
725
874
|
requestId
|
|
726
875
|
);
|
|
876
|
+
throw errorFamily === "commerce" ? enhanceCommerceError(usageError, parsed.body, requestId) : usageError;
|
|
727
877
|
}
|
|
728
|
-
|
|
729
|
-
if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && parsed.reason === "token_expired") {
|
|
878
|
+
if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
|
|
730
879
|
hasRetried401 = true;
|
|
731
880
|
try {
|
|
732
881
|
const newToken = await onUnauthorized();
|
|
@@ -748,13 +897,18 @@ async function httpFetch(url, options) {
|
|
|
748
897
|
parsed,
|
|
749
898
|
details,
|
|
750
899
|
requestId,
|
|
751
|
-
retryAfter
|
|
900
|
+
retryAfter.seconds,
|
|
901
|
+
errorFamily
|
|
752
902
|
);
|
|
753
903
|
const method2 = (requestInit.method || "GET").toUpperCase();
|
|
754
904
|
const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
|
|
755
|
-
|
|
905
|
+
const responseAllowsRetry = isCommerceSDKError(error) ? error.retryable : true;
|
|
906
|
+
if (attempt < retryConfig.maxRetries && SAFE_METHODS.includes(method2) && !isTerminal && responseAllowsRetry && retryAfter.permitsAutomaticRetry && !NON_RETRYABLE_STATUSES.includes(response.status) && retryConfig.retryableStatuses.includes(response.status)) {
|
|
756
907
|
lastError = error;
|
|
757
|
-
const retryDelay =
|
|
908
|
+
const retryDelay = Math.max(
|
|
909
|
+
retryConfig.retryDelay(attempt),
|
|
910
|
+
(retryAfter.seconds ?? 0) * 1e3
|
|
911
|
+
);
|
|
758
912
|
debugLog(debug, "error", `Retrying in ${retryDelay}ms...`, error);
|
|
759
913
|
await delay(retryDelay);
|
|
760
914
|
continue;
|
|
@@ -824,87 +978,45 @@ async function httpFetch(url, options) {
|
|
|
824
978
|
throw lastError ?? new NetworkError("Request failed after retries");
|
|
825
979
|
}
|
|
826
980
|
|
|
827
|
-
// src/core/api/endpoints.ts
|
|
828
|
-
var COMMERCE_ENDPOINTS = {
|
|
829
|
-
orders: {
|
|
830
|
-
create: "/api/orders/create",
|
|
831
|
-
update: "/api/orders/update",
|
|
832
|
-
confirmPayment: "/api/orders/confirm-payment",
|
|
833
|
-
byPayment: "/api/orders/by-payment",
|
|
834
|
-
cancel: "/api/orders/cancel",
|
|
835
|
-
resolveCancelRefund: "/api/orders/resolve-cancel-refund",
|
|
836
|
-
checkout: "/api/orders/checkout",
|
|
837
|
-
createFulfillment: "/api/orders/create-fulfillment",
|
|
838
|
-
updateFulfillment: "/api/orders/update-fulfillment"
|
|
839
|
-
},
|
|
840
|
-
transactions: {
|
|
841
|
-
update: "/api/transactions/update"
|
|
842
|
-
},
|
|
843
|
-
returns: {
|
|
844
|
-
create: "/api/returns/create",
|
|
845
|
-
update: "/api/returns/update",
|
|
846
|
-
returnRefund: "/api/returns/return-refund"
|
|
847
|
-
},
|
|
848
|
-
fulfillmentOrders: {
|
|
849
|
-
prepare: "/api/fulfillment-orders/prepare-fulfillment-order"
|
|
850
|
-
},
|
|
851
|
-
fulfillments: {
|
|
852
|
-
bulkImport: "/api/fulfillments/bulk-import"
|
|
853
|
-
},
|
|
854
|
-
carts: {
|
|
855
|
-
mine: "/api/carts/mine",
|
|
856
|
-
merge: "/api/carts/merge",
|
|
857
|
-
addItem: "/api/carts/add-item",
|
|
858
|
-
updateItem: "/api/carts/update-item",
|
|
859
|
-
removeItem: "/api/carts/remove-item",
|
|
860
|
-
applyDiscount: "/api/carts/apply-discount",
|
|
861
|
-
removeDiscount: "/api/carts/remove-discount",
|
|
862
|
-
clear: "/api/carts/clear"
|
|
863
|
-
},
|
|
864
|
-
products: {
|
|
865
|
-
stockCheck: "/api/products/stock-check",
|
|
866
|
-
stockSnapshot: "/api/products/stock",
|
|
867
|
-
listingGroups: "/api/products/listing-groups",
|
|
868
|
-
listingGroupsCatalog: "/api/products/listing-groups/catalog",
|
|
869
|
-
listingGroupsQuery: "/api/products/listing-groups/query",
|
|
870
|
-
listingGroupsQueryCatalog: "/api/products/listing-groups/query/catalog",
|
|
871
|
-
detail: "/api/products/detail",
|
|
872
|
-
detailCatalog: "/api/products/detail/catalog",
|
|
873
|
-
upsert: "/api/products/upsert"
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
|
-
var COMMERCE_ENDPOINT_PATHS = Object.values(
|
|
877
|
-
COMMERCE_ENDPOINTS
|
|
878
|
-
).flatMap((group) => Object.values(group));
|
|
879
|
-
var MEMBERSHIP_ENDPOINTS = {
|
|
880
|
-
subscribe: "/api/memberships/subscribe",
|
|
881
|
-
cancel: (id) => `/api/memberships/${id}/cancel`,
|
|
882
|
-
me: "/api/memberships/me"
|
|
883
|
-
};
|
|
884
|
-
|
|
885
981
|
// src/core/internal/utils/query-string.ts
|
|
886
|
-
function
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
982
|
+
function normalizedMarket(value) {
|
|
983
|
+
const market = value?.trim();
|
|
984
|
+
return market || void 0;
|
|
985
|
+
}
|
|
986
|
+
function appendProductLocaleSearchParams(search, options) {
|
|
987
|
+
if (options?.locale) search.set("locale", options.locale);
|
|
988
|
+
if (options?.fallbackLocale !== void 0) {
|
|
989
|
+
search.set(
|
|
990
|
+
"fallbackLocale",
|
|
991
|
+
options.fallbackLocale === false ? "none" : options.fallbackLocale
|
|
992
|
+
);
|
|
892
993
|
}
|
|
893
|
-
return `${COMMERCE_ENDPOINTS.products.detail}?${search}`;
|
|
894
994
|
}
|
|
895
|
-
function
|
|
995
|
+
function productDetailSearchParams(params) {
|
|
896
996
|
const search = new URLSearchParams();
|
|
897
997
|
if ("slug" in params) {
|
|
898
998
|
search.set("slug", params.slug);
|
|
899
999
|
} else {
|
|
900
1000
|
search.set("id", params.id);
|
|
901
1001
|
}
|
|
902
|
-
|
|
1002
|
+
const market = normalizedMarket(params.market);
|
|
1003
|
+
if (market) search.set("market", market);
|
|
1004
|
+
appendProductLocaleSearchParams(search, params);
|
|
1005
|
+
return search.toString();
|
|
903
1006
|
}
|
|
904
|
-
function
|
|
905
|
-
|
|
1007
|
+
function listingGroupsSearchParams(params) {
|
|
1008
|
+
const ids = params.productIds.map(encodeURIComponent).join(",");
|
|
1009
|
+
const search = new URLSearchParams();
|
|
1010
|
+
const market = normalizedMarket(params.market);
|
|
1011
|
+
if (market) search.set("market", market);
|
|
1012
|
+
appendProductLocaleSearchParams(search, params);
|
|
1013
|
+
const query = search.toString();
|
|
1014
|
+
return `ids=${ids}${query ? `&${query}` : ""}`;
|
|
906
1015
|
}
|
|
907
1016
|
function appendListingGroupsQuerySearchParams(search, options) {
|
|
1017
|
+
const market = normalizedMarket(options?.market);
|
|
1018
|
+
if (market) search.set("market", market);
|
|
1019
|
+
appendProductLocaleSearchParams(search, options);
|
|
908
1020
|
if (options?.page != null) search.set("page", String(options.page));
|
|
909
1021
|
if (options?.limit != null) search.set("limit", String(options.limit));
|
|
910
1022
|
if (options?.sort != null) {
|
|
@@ -915,20 +1027,13 @@ function appendListingGroupsQuerySearchParams(search, options) {
|
|
|
915
1027
|
search.set("whereJson", JSON.stringify(options.where));
|
|
916
1028
|
}
|
|
917
1029
|
}
|
|
918
|
-
function
|
|
1030
|
+
function listingPageSearchParams(options) {
|
|
919
1031
|
const search = new URLSearchParams();
|
|
920
1032
|
appendListingGroupsQuerySearchParams(search, options);
|
|
921
|
-
|
|
922
|
-
return `${COMMERCE_ENDPOINTS.products.listingGroupsQuery}${query ? `?${query}` : ""}`;
|
|
923
|
-
}
|
|
924
|
-
function listingGroupsQueryCatalogUrl(options) {
|
|
925
|
-
const search = new URLSearchParams();
|
|
926
|
-
appendListingGroupsQuerySearchParams(search, options);
|
|
927
|
-
const query = search.toString();
|
|
928
|
-
return `${COMMERCE_ENDPOINTS.products.listingGroupsQueryCatalog}${query ? `?${query}` : ""}`;
|
|
1033
|
+
return search.toString();
|
|
929
1034
|
}
|
|
930
|
-
function
|
|
931
|
-
return
|
|
1035
|
+
function stockSnapshotSearchParams(params) {
|
|
1036
|
+
return `variantIds=${params.variantIds.map(encodeURIComponent).join(",")}`;
|
|
932
1037
|
}
|
|
933
1038
|
|
|
934
1039
|
// src/core/collection/http-client.ts
|
|
@@ -971,10 +1076,15 @@ var HttpClient = class {
|
|
|
971
1076
|
throw err;
|
|
972
1077
|
}
|
|
973
1078
|
}
|
|
974
|
-
buildUrl(
|
|
975
|
-
if (!options) return
|
|
976
|
-
const
|
|
977
|
-
|
|
1079
|
+
buildUrl(endpoint2, options) {
|
|
1080
|
+
if (!options) return endpoint2;
|
|
1081
|
+
const { fallbackLocale, ...rest } = options;
|
|
1082
|
+
const queryOptions = fallbackLocale === void 0 ? rest : {
|
|
1083
|
+
...rest,
|
|
1084
|
+
"fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
|
|
1085
|
+
};
|
|
1086
|
+
const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
|
|
1087
|
+
return queryString ? `${endpoint2}${queryString}` : endpoint2;
|
|
978
1088
|
}
|
|
979
1089
|
assertJsonResponse(response) {
|
|
980
1090
|
const contentType = response.headers.get("content-type");
|
|
@@ -1123,39 +1233,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1123
1233
|
from(collection) {
|
|
1124
1234
|
return new ReadOnlyCollectionQueryBuilder(this, collection);
|
|
1125
1235
|
}
|
|
1126
|
-
async requestFind(
|
|
1127
|
-
const url = this.buildUrl(
|
|
1236
|
+
async requestFind(endpoint2, options) {
|
|
1237
|
+
const url = this.buildUrl(endpoint2, options);
|
|
1128
1238
|
const response = await this.fetchWithTracking(url, {
|
|
1129
1239
|
...this.defaultOptions,
|
|
1130
1240
|
method: "GET"
|
|
1131
1241
|
});
|
|
1132
1242
|
return this.parseFindResponse(response);
|
|
1133
1243
|
}
|
|
1134
|
-
async requestFindEndpoint(
|
|
1135
|
-
const response = await this.fetchWithTracking(
|
|
1244
|
+
async requestFindEndpoint(endpoint2, data) {
|
|
1245
|
+
const response = await this.fetchWithTracking(endpoint2, {
|
|
1136
1246
|
...this.defaultOptions,
|
|
1137
1247
|
method: "POST",
|
|
1138
1248
|
body: data ? JSON.stringify(data) : void 0
|
|
1139
1249
|
});
|
|
1140
1250
|
return this.parseFindResponse(response);
|
|
1141
1251
|
}
|
|
1142
|
-
async requestFindEndpointGet(
|
|
1143
|
-
const response = await this.fetchWithTracking(
|
|
1252
|
+
async requestFindEndpointGet(endpoint2) {
|
|
1253
|
+
const response = await this.fetchWithTracking(endpoint2, {
|
|
1144
1254
|
...this.defaultOptions,
|
|
1145
1255
|
method: "GET"
|
|
1146
1256
|
});
|
|
1147
1257
|
return this.parseFindResponse(response);
|
|
1148
1258
|
}
|
|
1149
|
-
async requestFindById(
|
|
1150
|
-
const url = this.buildUrl(
|
|
1259
|
+
async requestFindById(endpoint2, options) {
|
|
1260
|
+
const url = this.buildUrl(endpoint2, options);
|
|
1151
1261
|
const response = await this.fetchWithTracking(url, {
|
|
1152
1262
|
...this.defaultOptions,
|
|
1153
1263
|
method: "GET"
|
|
1154
1264
|
});
|
|
1155
1265
|
return this.parseDocumentResponse(response);
|
|
1156
1266
|
}
|
|
1157
|
-
async requestCount(
|
|
1158
|
-
const url = this.buildUrl(
|
|
1267
|
+
async requestCount(endpoint2, options) {
|
|
1268
|
+
const url = this.buildUrl(endpoint2, options);
|
|
1159
1269
|
const response = await this.fetchWithTracking(url, {
|
|
1160
1270
|
...this.defaultOptions,
|
|
1161
1271
|
method: "GET"
|
|
@@ -1165,53 +1275,339 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1165
1275
|
};
|
|
1166
1276
|
|
|
1167
1277
|
// src/core/api/parse-response.ts
|
|
1168
|
-
async function parseApiResponse(response,
|
|
1169
|
-
|
|
1278
|
+
async function parseApiResponse(response, endpoint2, options = {}) {
|
|
1279
|
+
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
1280
|
+
return void 0;
|
|
1281
|
+
}
|
|
1282
|
+
let parsed;
|
|
1170
1283
|
try {
|
|
1171
|
-
|
|
1284
|
+
parsed = await response.json();
|
|
1172
1285
|
} catch {
|
|
1173
1286
|
throw createApiError(
|
|
1174
|
-
`Invalid JSON response from ${
|
|
1287
|
+
`Invalid JSON response from ${endpoint2}`,
|
|
1175
1288
|
response.status,
|
|
1176
1289
|
void 0,
|
|
1177
1290
|
"Server returned an invalid response.",
|
|
1178
1291
|
"Check if the API endpoint is available."
|
|
1179
1292
|
);
|
|
1180
1293
|
}
|
|
1294
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
1295
|
+
return parsed;
|
|
1296
|
+
}
|
|
1297
|
+
const data = parsed;
|
|
1181
1298
|
if (data.error) {
|
|
1182
1299
|
const errorMessage = typeof data.error === "string" ? data.error : "Unknown API error";
|
|
1183
1300
|
const reason = typeof data.reason === "string" ? data.reason : void 0;
|
|
1184
1301
|
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1302
|
+
const retryAfter = parseRetryAfter(response).seconds;
|
|
1303
|
+
let error;
|
|
1187
1304
|
if (reason === "validation_failed") {
|
|
1188
|
-
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
|
|
1305
|
+
error = createValidationError(errorMessage, data, errorMessage);
|
|
1306
|
+
} else if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
|
|
1307
|
+
error = createAuthError(errorMessage, data, errorMessage);
|
|
1308
|
+
} else if (reason === "forbidden") {
|
|
1309
|
+
error = createPermissionError(errorMessage, data, errorMessage);
|
|
1310
|
+
} else if (reason === "rate_limit_exceeded") {
|
|
1311
|
+
error = createRateLimitError(errorMessage, retryAfter, data, errorMessage);
|
|
1312
|
+
} else if (reason === "not_found") {
|
|
1313
|
+
error = createNotFoundError(errorMessage, data, errorMessage);
|
|
1314
|
+
} else if (reason === "conflict") {
|
|
1315
|
+
error = createConflictError(errorMessage, data, errorMessage);
|
|
1316
|
+
} else {
|
|
1317
|
+
error = createApiError(
|
|
1318
|
+
errorMessage,
|
|
1319
|
+
response.status,
|
|
1320
|
+
data,
|
|
1321
|
+
errorMessage,
|
|
1322
|
+
"An error occurred while processing the request."
|
|
1323
|
+
);
|
|
1192
1324
|
}
|
|
1193
|
-
|
|
1194
|
-
|
|
1325
|
+
const withRequestId = attachRequestId(error, requestId);
|
|
1326
|
+
if (retryAfter !== void 0) Object.assign(withRequestId, { retryAfter });
|
|
1327
|
+
throw options.errorFamily === "commerce" ? enhanceCommerceError(withRequestId, data, requestId) : withRequestId;
|
|
1328
|
+
}
|
|
1329
|
+
return data;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
// ../../internal/http-contracts/src/index.ts
|
|
1333
|
+
var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
|
|
1334
|
+
var operation = (collection, method, path) => Object.freeze({
|
|
1335
|
+
[operationBrand]: true,
|
|
1336
|
+
collection,
|
|
1337
|
+
method,
|
|
1338
|
+
path
|
|
1339
|
+
});
|
|
1340
|
+
var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
1341
|
+
products: {
|
|
1342
|
+
detail: operation("products", "get", "/detail"),
|
|
1343
|
+
detailCatalog: operation("products", "get", "/detail/catalog"),
|
|
1344
|
+
listingGroups: operation("products", "get", "/listing-groups"),
|
|
1345
|
+
listingGroupsCatalog: operation(
|
|
1346
|
+
"products",
|
|
1347
|
+
"get",
|
|
1348
|
+
"/listing-groups/catalog"
|
|
1349
|
+
),
|
|
1350
|
+
listingGroupsQuery: operation("products", "post", "/listing-groups/query"),
|
|
1351
|
+
listingGroupsQueryGet: operation(
|
|
1352
|
+
"products",
|
|
1353
|
+
"get",
|
|
1354
|
+
"/listing-groups/query"
|
|
1355
|
+
),
|
|
1356
|
+
listingGroupsQueryCatalog: operation(
|
|
1357
|
+
"products",
|
|
1358
|
+
"get",
|
|
1359
|
+
"/listing-groups/query/catalog"
|
|
1360
|
+
),
|
|
1361
|
+
stockCheck: operation("products", "post", "/stock-check"),
|
|
1362
|
+
stockSnapshot: operation("products", "get", "/stock"),
|
|
1363
|
+
upsert: operation("products", "post", "/upsert")
|
|
1364
|
+
},
|
|
1365
|
+
orders: {
|
|
1366
|
+
create: operation("orders", "post", "/create"),
|
|
1367
|
+
update: operation("orders", "post", "/update"),
|
|
1368
|
+
confirmPayment: operation("orders", "post", "/confirm-payment"),
|
|
1369
|
+
byPayment: operation("orders", "get", "/by-payment"),
|
|
1370
|
+
cancel: operation("orders", "post", "/cancel"),
|
|
1371
|
+
resolveCancelRefund: operation("orders", "post", "/resolve-cancel-refund"),
|
|
1372
|
+
checkout: operation("orders", "post", "/checkout"),
|
|
1373
|
+
createFulfillment: operation("orders", "post", "/create-fulfillment"),
|
|
1374
|
+
updateFulfillment: operation("orders", "post", "/update-fulfillment")
|
|
1375
|
+
},
|
|
1376
|
+
checkouts: {
|
|
1377
|
+
detail: operation("checkouts", "post", "/detail"),
|
|
1378
|
+
query: operation("checkouts", "post", "/query")
|
|
1379
|
+
},
|
|
1380
|
+
transactions: {
|
|
1381
|
+
update: operation("transactions", "post", "/update")
|
|
1382
|
+
},
|
|
1383
|
+
returns: {
|
|
1384
|
+
create: operation("returns", "post", "/create"),
|
|
1385
|
+
update: operation("returns", "post", "/update"),
|
|
1386
|
+
returnRefund: operation("returns", "post", "/return-refund")
|
|
1387
|
+
},
|
|
1388
|
+
fulfillmentOrders: {
|
|
1389
|
+
prepare: operation(
|
|
1390
|
+
"fulfillment-orders",
|
|
1391
|
+
"post",
|
|
1392
|
+
"/prepare-fulfillment-order"
|
|
1393
|
+
)
|
|
1394
|
+
},
|
|
1395
|
+
fulfillments: {
|
|
1396
|
+
bulkImport: operation("fulfillments", "post", "/bulk-import")
|
|
1397
|
+
},
|
|
1398
|
+
carts: {
|
|
1399
|
+
create: operation("carts", "post", "/create"),
|
|
1400
|
+
retrieve: operation("carts", "post", "/retrieve"),
|
|
1401
|
+
mine: operation("carts", "post", "/mine"),
|
|
1402
|
+
merge: operation("carts", "post", "/merge"),
|
|
1403
|
+
addItem: operation("carts", "post", "/add-item"),
|
|
1404
|
+
updateItem: operation("carts", "post", "/update-item"),
|
|
1405
|
+
removeItem: operation("carts", "post", "/remove-item"),
|
|
1406
|
+
updateDiscountCodes: operation("carts", "post", "/update-discount-codes"),
|
|
1407
|
+
updateAttributes: operation("carts", "post", "/update-attributes"),
|
|
1408
|
+
clear: operation("carts", "post", "/clear")
|
|
1409
|
+
},
|
|
1410
|
+
paymentSessions: {
|
|
1411
|
+
create: operation("payment-sessions", "post", "/create"),
|
|
1412
|
+
retrieve: operation("payment-sessions", "post", "/retrieve"),
|
|
1413
|
+
cancel: operation("payment-sessions", "post", "/cancel"),
|
|
1414
|
+
server: {
|
|
1415
|
+
create: operation("payment-sessions", "post", "/server/create"),
|
|
1416
|
+
retrieve: operation("payment-sessions", "post", "/server/retrieve"),
|
|
1417
|
+
cancel: operation("payment-sessions", "post", "/server/cancel"),
|
|
1418
|
+
confirm: operation("payment-sessions", "post", "/server/confirm")
|
|
1419
|
+
},
|
|
1420
|
+
custom: {
|
|
1421
|
+
create: operation("orders", "post", "/custom-payment-sessions"),
|
|
1422
|
+
confirm: operation("orders", "post", "/custom-payment-sessions/confirm")
|
|
1195
1423
|
}
|
|
1196
|
-
|
|
1197
|
-
|
|
1424
|
+
},
|
|
1425
|
+
shippingPolicies: {
|
|
1426
|
+
calculate: operation("shipping-policies", "post", "/calculate")
|
|
1427
|
+
},
|
|
1428
|
+
discounts: {
|
|
1429
|
+
validate: operation("discounts", "post", "/validate")
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
1433
|
+
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
1434
|
+
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
1435
|
+
me: operation(null, "get", "/memberships/me")
|
|
1436
|
+
};
|
|
1437
|
+
var EVENTS_ENDPOINT_OPERATIONS = {
|
|
1438
|
+
occurrences: {
|
|
1439
|
+
range: operation("event-occurrences", "get", "/range"),
|
|
1440
|
+
admissionAvailability: operation(
|
|
1441
|
+
"event-occurrences",
|
|
1442
|
+
"get",
|
|
1443
|
+
"/admission-availability"
|
|
1444
|
+
)
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
function resolveOperationTemplate(descriptor) {
|
|
1448
|
+
return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
|
|
1449
|
+
}
|
|
1450
|
+
function resolveOperationPath(descriptor, options) {
|
|
1451
|
+
const path = resolveOperationTemplate(descriptor).replace(
|
|
1452
|
+
/:([A-Za-z][A-Za-z0-9_]*)/g,
|
|
1453
|
+
(_, key) => {
|
|
1454
|
+
const value = options?.pathParams?.[key];
|
|
1455
|
+
if (value === void 0) {
|
|
1456
|
+
throw new TypeError(`Missing path parameter: ${key}`);
|
|
1457
|
+
}
|
|
1458
|
+
return encodeURIComponent(value);
|
|
1198
1459
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1460
|
+
);
|
|
1461
|
+
const unresolved = path.match(/:([A-Za-z][A-Za-z0-9_]*)/);
|
|
1462
|
+
if (unresolved) {
|
|
1463
|
+
throw new TypeError(`Missing path parameter: ${unresolved[1]}`);
|
|
1464
|
+
}
|
|
1465
|
+
const query = options?.query?.toString().replace(/^\?/, "");
|
|
1466
|
+
return query ? `${path}?${query}` : path;
|
|
1467
|
+
}
|
|
1468
|
+
function resolveOperationMethod(descriptor) {
|
|
1469
|
+
return descriptor.method.toUpperCase();
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
// src/core/api/endpoints.ts
|
|
1473
|
+
var endpoint = (method, path) => ({ method, path });
|
|
1474
|
+
var sharedEndpoint = (descriptor) => descriptor;
|
|
1475
|
+
function resolveOperationMethod2(descriptor) {
|
|
1476
|
+
return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
|
|
1477
|
+
}
|
|
1478
|
+
function resolveOperationPath2(descriptor, options) {
|
|
1479
|
+
if ("collection" in descriptor) {
|
|
1480
|
+
return resolveOperationPath(descriptor, options);
|
|
1481
|
+
}
|
|
1482
|
+
const query = options?.query?.toString().replace(/^\?/, "");
|
|
1483
|
+
return query ? `${descriptor.path}?${query}` : descriptor.path;
|
|
1484
|
+
}
|
|
1485
|
+
var COMMERCE_ENDPOINTS = {
|
|
1486
|
+
products: {
|
|
1487
|
+
detail: endpoint("GET", "/api/products/detail"),
|
|
1488
|
+
detailCatalog: endpoint("GET", "/api/products/detail/catalog"),
|
|
1489
|
+
listingGroups: endpoint("GET", "/api/products/listing-groups"),
|
|
1490
|
+
listingGroupsCatalog: endpoint(
|
|
1491
|
+
"GET",
|
|
1492
|
+
"/api/products/listing-groups/catalog"
|
|
1493
|
+
),
|
|
1494
|
+
listingGroupsQuery: endpoint("GET", "/api/products/listing-groups/query"),
|
|
1495
|
+
listingGroupsQueryCatalog: endpoint(
|
|
1496
|
+
"GET",
|
|
1497
|
+
"/api/products/listing-groups/query/catalog"
|
|
1498
|
+
),
|
|
1499
|
+
stockCheck: endpoint("POST", "/api/products/stock-check"),
|
|
1500
|
+
stockSnapshot: endpoint("GET", "/api/products/stock"),
|
|
1501
|
+
upsert: endpoint("POST", "/api/products/upsert")
|
|
1502
|
+
},
|
|
1503
|
+
orders: {
|
|
1504
|
+
update: endpoint("POST", "/api/orders/update"),
|
|
1505
|
+
byPayment: endpoint("GET", "/api/orders/by-payment"),
|
|
1506
|
+
cancel: endpoint("POST", "/api/orders/cancel"),
|
|
1507
|
+
resolveCancelRefund: endpoint("POST", "/api/orders/resolve-cancel-refund"),
|
|
1508
|
+
createFulfillment: endpoint("POST", "/api/orders/create-fulfillment"),
|
|
1509
|
+
updateFulfillment: endpoint("POST", "/api/orders/update-fulfillment")
|
|
1510
|
+
},
|
|
1511
|
+
checkouts: {
|
|
1512
|
+
create: endpoint("POST", "/api/orders/checkout"),
|
|
1513
|
+
retrieve: endpoint("POST", "/api/checkouts/detail"),
|
|
1514
|
+
server: {
|
|
1515
|
+
create: endpoint("POST", "/api/orders/checkout"),
|
|
1516
|
+
retrieve: endpoint("POST", "/api/checkouts/detail"),
|
|
1517
|
+
query: endpoint("POST", "/api/checkouts/query")
|
|
1201
1518
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1519
|
+
},
|
|
1520
|
+
returns: {
|
|
1521
|
+
create: endpoint("POST", "/api/returns/create"),
|
|
1522
|
+
update: endpoint("POST", "/api/returns/update"),
|
|
1523
|
+
returnRefund: endpoint("POST", "/api/returns/return-refund")
|
|
1524
|
+
},
|
|
1525
|
+
fulfillmentOrders: {
|
|
1526
|
+
prepare: endpoint(
|
|
1527
|
+
"POST",
|
|
1528
|
+
"/api/fulfillment-orders/prepare-fulfillment-order"
|
|
1529
|
+
)
|
|
1530
|
+
},
|
|
1531
|
+
fulfillments: {
|
|
1532
|
+
bulkImport: endpoint("POST", "/api/fulfillments/bulk-import")
|
|
1533
|
+
},
|
|
1534
|
+
carts: {
|
|
1535
|
+
create: endpoint("POST", "/api/carts/create"),
|
|
1536
|
+
retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
|
|
1537
|
+
mine: endpoint("POST", "/api/carts/mine"),
|
|
1538
|
+
merge: endpoint("POST", "/api/carts/merge"),
|
|
1539
|
+
server: {
|
|
1540
|
+
// Server credentials are an authorization lane, not a second Cart
|
|
1541
|
+
// transport. These must stay bound to the registered shared operations.
|
|
1542
|
+
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
|
|
1543
|
+
retrieve: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.retrieve),
|
|
1544
|
+
mine: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.mine),
|
|
1545
|
+
merge: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.merge),
|
|
1546
|
+
addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
|
|
1547
|
+
updateItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.updateItem),
|
|
1548
|
+
removeItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.removeItem),
|
|
1549
|
+
updateDiscountCodes: sharedEndpoint(
|
|
1550
|
+
COMMERCE_ENDPOINT_OPERATIONS.carts.updateDiscountCodes
|
|
1551
|
+
),
|
|
1552
|
+
updateAttributes: sharedEndpoint(
|
|
1553
|
+
COMMERCE_ENDPOINT_OPERATIONS.carts.updateAttributes
|
|
1554
|
+
),
|
|
1555
|
+
clear: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.clear)
|
|
1556
|
+
},
|
|
1557
|
+
addItem: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.addItem),
|
|
1558
|
+
updateItem: endpoint("POST", "/api/carts/update-item"),
|
|
1559
|
+
removeItem: endpoint("POST", "/api/carts/remove-item"),
|
|
1560
|
+
updateDiscountCodes: endpoint("POST", "/api/carts/update-discount-codes"),
|
|
1561
|
+
updateAttributes: endpoint("POST", "/api/carts/update-attributes"),
|
|
1562
|
+
clear: endpoint("POST", "/api/carts/clear")
|
|
1563
|
+
},
|
|
1564
|
+
paymentSessions: {
|
|
1565
|
+
create: endpoint("POST", "/api/payment-sessions/create"),
|
|
1566
|
+
retrieve: endpoint("POST", "/api/payment-sessions/retrieve"),
|
|
1567
|
+
cancel: endpoint("POST", "/api/payment-sessions/cancel"),
|
|
1568
|
+
server: {
|
|
1569
|
+
create: endpoint("POST", "/api/payment-sessions/server/create"),
|
|
1570
|
+
retrieve: endpoint("POST", "/api/payment-sessions/server/retrieve"),
|
|
1571
|
+
cancel: endpoint("POST", "/api/payment-sessions/server/cancel"),
|
|
1572
|
+
confirm: endpoint("POST", "/api/payment-sessions/server/confirm")
|
|
1204
1573
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
);
|
|
1574
|
+
},
|
|
1575
|
+
shippingPolicies: {
|
|
1576
|
+
calculate: endpoint("POST", "/api/shipping-policies/calculate")
|
|
1209
1577
|
}
|
|
1210
|
-
|
|
1578
|
+
};
|
|
1579
|
+
function isCommerceEndpointDescriptor(value) {
|
|
1580
|
+
if (!value || typeof value !== "object") return false;
|
|
1581
|
+
const candidate = value;
|
|
1582
|
+
return typeof candidate.method === "string" && typeof candidate.path === "string";
|
|
1583
|
+
}
|
|
1584
|
+
function flattenEndpointPaths(value) {
|
|
1585
|
+
if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
|
|
1586
|
+
if (!value || typeof value !== "object") return [];
|
|
1587
|
+
return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
|
|
1588
|
+
}
|
|
1589
|
+
function flattenEndpointDescriptors(value) {
|
|
1590
|
+
if (isCommerceEndpointDescriptor(value)) return [value];
|
|
1591
|
+
if (!value || typeof value !== "object") return [];
|
|
1592
|
+
return Object.values(value).flatMap(
|
|
1593
|
+
(entry) => flattenEndpointDescriptors(entry)
|
|
1594
|
+
);
|
|
1211
1595
|
}
|
|
1596
|
+
var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
|
|
1597
|
+
var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
|
|
1598
|
+
var MEMBERSHIP_ENDPOINTS = {
|
|
1599
|
+
subscribe: "/api/memberships/subscribe",
|
|
1600
|
+
cancel: (id) => `/api/memberships/${id}/cancel`,
|
|
1601
|
+
me: "/api/memberships/me"
|
|
1602
|
+
};
|
|
1603
|
+
var MEMBERSHIP_ENDPOINT_PATHS = [
|
|
1604
|
+
MEMBERSHIP_ENDPOINTS.subscribe,
|
|
1605
|
+
MEMBERSHIP_ENDPOINTS.cancel(":id"),
|
|
1606
|
+
MEMBERSHIP_ENDPOINTS.me
|
|
1607
|
+
];
|
|
1212
1608
|
|
|
1213
1609
|
// src/core/api/customer-scoped-api.ts
|
|
1214
|
-
var
|
|
1610
|
+
var CustomerScopedTransport = class {
|
|
1215
1611
|
constructor(apiName, options) {
|
|
1216
1612
|
if (options.requiresCredential !== false && !options.secretKey && !options.customerToken) {
|
|
1217
1613
|
throw createConfigError(
|
|
@@ -1229,10 +1625,10 @@ var CustomerScopedApi = class {
|
|
|
1229
1625
|
this.onUnauthorized = options.onUnauthorized;
|
|
1230
1626
|
this.onRequestId = options.onRequestId;
|
|
1231
1627
|
}
|
|
1232
|
-
async request(
|
|
1628
|
+
async request(endpoint2, options) {
|
|
1233
1629
|
const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
|
|
1234
1630
|
try {
|
|
1235
|
-
const response = await httpFetch(
|
|
1631
|
+
const response = await httpFetch(endpoint2, {
|
|
1236
1632
|
method: options.method,
|
|
1237
1633
|
apiUrl: this.apiUrl,
|
|
1238
1634
|
publishableKey: this.publishableKey,
|
|
@@ -1242,10 +1638,13 @@ var CustomerScopedApi = class {
|
|
|
1242
1638
|
...options.body !== void 0 && {
|
|
1243
1639
|
body: JSON.stringify(options.body)
|
|
1244
1640
|
},
|
|
1245
|
-
...options.headers && { headers: options.headers }
|
|
1641
|
+
...options.headers && { headers: options.headers },
|
|
1642
|
+
...options.errorFamily && { errorFamily: options.errorFamily }
|
|
1246
1643
|
});
|
|
1247
1644
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
1248
|
-
return parseApiResponse(response,
|
|
1645
|
+
return parseApiResponse(response, endpoint2, {
|
|
1646
|
+
errorFamily: options.errorFamily
|
|
1647
|
+
});
|
|
1249
1648
|
} catch (err) {
|
|
1250
1649
|
const id = err instanceof SDKError ? err.requestId ?? null : null;
|
|
1251
1650
|
this.onRequestId?.(id);
|
|
@@ -1253,6 +1652,26 @@ var CustomerScopedApi = class {
|
|
|
1253
1652
|
}
|
|
1254
1653
|
}
|
|
1255
1654
|
};
|
|
1655
|
+
var CustomerScopedApi = class {
|
|
1656
|
+
constructor(apiName, options) {
|
|
1657
|
+
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1658
|
+
}
|
|
1659
|
+
requestEndpoint(endpoint2, body, options) {
|
|
1660
|
+
return this.transport.request(resolveOperationPath2(endpoint2, options), {
|
|
1661
|
+
method: resolveOperationMethod2(endpoint2),
|
|
1662
|
+
body,
|
|
1663
|
+
headers: options?.headers
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
var RawCustomerScopedApi = class {
|
|
1668
|
+
constructor(apiName, options) {
|
|
1669
|
+
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1670
|
+
}
|
|
1671
|
+
request(endpoint2, options) {
|
|
1672
|
+
return this.transport.request(endpoint2, options);
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1256
1675
|
|
|
1257
1676
|
// src/core/community/community-client.ts
|
|
1258
1677
|
var DEFAULT_POST_LIST_SORT = "-lastActivityAt";
|
|
@@ -1263,7 +1682,7 @@ function unwrapPayloadDoc(value) {
|
|
|
1263
1682
|
}
|
|
1264
1683
|
return value;
|
|
1265
1684
|
}
|
|
1266
|
-
var CommunityClient = class extends
|
|
1685
|
+
var CommunityClient = class extends RawCustomerScopedApi {
|
|
1267
1686
|
constructor(options) {
|
|
1268
1687
|
super("CommunityClient", { ...options, requiresCredential: false });
|
|
1269
1688
|
}
|
|
@@ -1307,11 +1726,11 @@ var CommunityClient = class extends CustomerScopedApi {
|
|
|
1307
1726
|
if (params.page !== void 0) urlParams.set("page", String(params.page));
|
|
1308
1727
|
return `/api/comments/public?${urlParams.toString()}`;
|
|
1309
1728
|
}
|
|
1310
|
-
async execute(
|
|
1311
|
-
return this.request(
|
|
1729
|
+
async execute(endpoint2, method, body) {
|
|
1730
|
+
return this.request(endpoint2, { method, body });
|
|
1312
1731
|
}
|
|
1313
|
-
async executeDoc(
|
|
1314
|
-
const response = await this.execute(
|
|
1732
|
+
async executeDoc(endpoint2, method, body) {
|
|
1733
|
+
const response = await this.execute(endpoint2, method, body);
|
|
1315
1734
|
return unwrapPayloadDoc(response);
|
|
1316
1735
|
}
|
|
1317
1736
|
createPost(params) {
|
|
@@ -1547,56 +1966,1538 @@ var CommunityClient = class extends CustomerScopedApi {
|
|
|
1547
1966
|
body
|
|
1548
1967
|
);
|
|
1549
1968
|
}
|
|
1550
|
-
};
|
|
1551
|
-
|
|
1552
|
-
// src/core/content/content-client.ts
|
|
1553
|
-
var PublicContentApi = class extends
|
|
1554
|
-
get(
|
|
1555
|
-
return this.request(
|
|
1556
|
-
}
|
|
1557
|
-
};
|
|
1558
|
-
function appendCommonParams(search, options, defaultSort) {
|
|
1559
|
-
search.set("sort", options?.sort ?? defaultSort);
|
|
1560
|
-
if (options?.page != null) search.set("page", String(options.page));
|
|
1561
|
-
if (options?.limit != null) search.set("limit", String(options.limit));
|
|
1562
|
-
}
|
|
1563
|
-
function linksListPath(options) {
|
|
1564
|
-
const search = new URLSearchParams();
|
|
1565
|
-
appendCommonParams(search, options, "-publishedAt,-createdAt");
|
|
1566
|
-
if (options?.categoryId) search.set("categoryId", options.categoryId);
|
|
1567
|
-
if (options?.categorySlug) {
|
|
1568
|
-
search.set("categorySlug", options.categorySlug);
|
|
1569
|
-
}
|
|
1570
|
-
if (options?.tagId) search.set("tagId", options.tagId);
|
|
1571
|
-
if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
|
|
1572
|
-
if (options?.featured != null)
|
|
1573
|
-
|
|
1574
|
-
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
if (options?.
|
|
1580
|
-
|
|
1969
|
+
};
|
|
1970
|
+
|
|
1971
|
+
// src/core/content/content-client.ts
|
|
1972
|
+
var PublicContentApi = class extends RawCustomerScopedApi {
|
|
1973
|
+
get(endpoint2) {
|
|
1974
|
+
return this.request(endpoint2, { method: "GET" });
|
|
1975
|
+
}
|
|
1976
|
+
};
|
|
1977
|
+
function appendCommonParams(search, options, defaultSort) {
|
|
1978
|
+
search.set("sort", options?.sort ?? defaultSort);
|
|
1979
|
+
if (options?.page != null) search.set("page", String(options.page));
|
|
1980
|
+
if (options?.limit != null) search.set("limit", String(options.limit));
|
|
1981
|
+
}
|
|
1982
|
+
function linksListPath(options) {
|
|
1983
|
+
const search = new URLSearchParams();
|
|
1984
|
+
appendCommonParams(search, options, "-publishedAt,-createdAt");
|
|
1985
|
+
if (options?.categoryId) search.set("categoryId", options.categoryId);
|
|
1986
|
+
if (options?.categorySlug) {
|
|
1987
|
+
search.set("categorySlug", options.categorySlug);
|
|
1988
|
+
}
|
|
1989
|
+
if (options?.tagId) search.set("tagId", options.tagId);
|
|
1990
|
+
if (options?.tagSlug) search.set("tagSlug", options.tagSlug);
|
|
1991
|
+
if (options?.featured != null)
|
|
1992
|
+
search.set("featured", String(options.featured));
|
|
1993
|
+
return `/api/links/storefront?${search}`;
|
|
1994
|
+
}
|
|
1995
|
+
function galleryItemsListPath(options) {
|
|
1996
|
+
const search = new URLSearchParams();
|
|
1997
|
+
appendCommonParams(search, options, "manual");
|
|
1998
|
+
if (options?.galleryId) search.set("galleryId", options.galleryId);
|
|
1999
|
+
if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
|
|
2000
|
+
return `/api/gallery-items/storefront?${search}`;
|
|
2001
|
+
}
|
|
2002
|
+
var ContentClient = class {
|
|
2003
|
+
constructor(options) {
|
|
2004
|
+
const api = new PublicContentApi("ContentClient", {
|
|
2005
|
+
publishableKey: options.publishableKey,
|
|
2006
|
+
apiUrl: options.apiUrl,
|
|
2007
|
+
onRequestId: options.onRequestId,
|
|
2008
|
+
requiresCredential: false
|
|
2009
|
+
});
|
|
2010
|
+
this.links = {
|
|
2011
|
+
list: (params) => api.get(linksListPath(params))
|
|
2012
|
+
};
|
|
2013
|
+
this.galleryItems = {
|
|
2014
|
+
list: (params) => api.get(
|
|
2015
|
+
galleryItemsListPath(params)
|
|
2016
|
+
)
|
|
2017
|
+
};
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
|
|
2021
|
+
// src/core/api/canonical-response.ts
|
|
2022
|
+
var CART_STATUSES = ["active", "completed", "abandoned"];
|
|
2023
|
+
var MAX_CART_LINE_QUANTITY = 99;
|
|
2024
|
+
var MAX_COMMERCE_SHORT_TEXT_LENGTH = 200;
|
|
2025
|
+
var MAX_COMMERCE_ADDRESS_LENGTH = 500;
|
|
2026
|
+
var MAX_COMMERCE_EMAIL_LENGTH = 254;
|
|
2027
|
+
var MAX_COMMERCE_PHONE_LENGTH = 32;
|
|
2028
|
+
var MAX_COMMERCE_POSTAL_CODE_LENGTH = 32;
|
|
2029
|
+
var MAX_COMMERCE_EXTENSION_VALUE_LENGTH = 500;
|
|
2030
|
+
var MAX_COMMERCE_RESOURCE_ID_LENGTH = 255;
|
|
2031
|
+
var MAX_COMMERCE_CAPABILITY_LENGTH = 512;
|
|
2032
|
+
var MAX_CART_DISCOUNT_CODE_LENGTH = 128;
|
|
2033
|
+
var ORDER_FINANCIAL_STATUSES = [
|
|
2034
|
+
"pending",
|
|
2035
|
+
"authorized",
|
|
2036
|
+
"expired",
|
|
2037
|
+
"partially_paid",
|
|
2038
|
+
"paid",
|
|
2039
|
+
"canceled",
|
|
2040
|
+
"partially_refunded",
|
|
2041
|
+
"refunded",
|
|
2042
|
+
"reconciliation_required"
|
|
2043
|
+
];
|
|
2044
|
+
var ORDER_FULFILLMENT_STATUSES = [
|
|
2045
|
+
"unfulfilled",
|
|
2046
|
+
"in_progress",
|
|
2047
|
+
"on_hold",
|
|
2048
|
+
"partially_fulfilled",
|
|
2049
|
+
"shipped",
|
|
2050
|
+
"fulfilled",
|
|
2051
|
+
"canceled"
|
|
2052
|
+
];
|
|
2053
|
+
var ORDER_RETURN_STATUSES = [
|
|
2054
|
+
"no_return",
|
|
2055
|
+
"return_requested",
|
|
2056
|
+
"in_progress",
|
|
2057
|
+
"returned"
|
|
2058
|
+
];
|
|
2059
|
+
var ORDER_CONFIRMATION_STATUSES = ["unconfirmed", "confirmed"];
|
|
2060
|
+
var ORDER_PRIMARY_DISPLAY_STATUSES = [
|
|
2061
|
+
"pending",
|
|
2062
|
+
"paid",
|
|
2063
|
+
"canceled",
|
|
2064
|
+
"refunded",
|
|
2065
|
+
"preparing",
|
|
2066
|
+
"shipped",
|
|
2067
|
+
"delivered",
|
|
2068
|
+
"confirmed"
|
|
2069
|
+
];
|
|
2070
|
+
var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
|
|
2071
|
+
var ABANDONED_REASONS = ["expired", "customer", "operator"];
|
|
2072
|
+
var PAYMENT_PROVIDERS = ["toss"];
|
|
2073
|
+
var PAYMENT_PROVIDER_STATUSES = [
|
|
2074
|
+
"requires_payment_method",
|
|
2075
|
+
"requires_action",
|
|
2076
|
+
"requires_confirmation",
|
|
2077
|
+
"initializing",
|
|
2078
|
+
"processing",
|
|
2079
|
+
"authorized",
|
|
2080
|
+
"canceling",
|
|
2081
|
+
"unknown",
|
|
2082
|
+
"captured",
|
|
2083
|
+
"failed",
|
|
2084
|
+
"canceled"
|
|
2085
|
+
];
|
|
2086
|
+
var PAYMENT_FAILURE_REASONS = [
|
|
2087
|
+
"payment_declined",
|
|
2088
|
+
"authentication_failed",
|
|
2089
|
+
"authorization_expired",
|
|
2090
|
+
"payment_method_unavailable",
|
|
2091
|
+
"provider_terminal_failure",
|
|
2092
|
+
"unknown_provider_terminal_failure"
|
|
2093
|
+
];
|
|
2094
|
+
var CART_WARNING_CODES = [
|
|
2095
|
+
"DISCOUNT_CODE_NOT_HONOURED",
|
|
2096
|
+
"DISCOUNT_CURRENTLY_INACTIVE",
|
|
2097
|
+
"DISCOUNT_CUSTOMER_NOT_ELIGIBLE",
|
|
2098
|
+
"DISCOUNT_CUSTOMER_USAGE_LIMIT_REACHED",
|
|
2099
|
+
"DISCOUNT_ELIGIBLE_CUSTOMER_MISSING",
|
|
2100
|
+
"DISCOUNT_NO_ENTITLED_LINE_ITEMS",
|
|
2101
|
+
"DISCOUNT_NO_ENTITLED_SHIPPING_LINES",
|
|
2102
|
+
"DISCOUNT_NOT_FOUND",
|
|
2103
|
+
"DISCOUNT_PURCHASE_NOT_IN_RANGE",
|
|
2104
|
+
"DISCOUNT_USAGE_LIMIT_REACHED",
|
|
2105
|
+
"MERCHANDISE_NOT_ENOUGH_STOCK",
|
|
2106
|
+
"MERCHANDISE_OUT_OF_STOCK"
|
|
2107
|
+
];
|
|
2108
|
+
function invalidCanonicalResponse(resource, details) {
|
|
2109
|
+
throw createApiError(
|
|
2110
|
+
`Invalid canonical ${resource} response.`,
|
|
2111
|
+
502,
|
|
2112
|
+
{ resource, ...details },
|
|
2113
|
+
`The server returned an incompatible ${resource} response.`,
|
|
2114
|
+
"Verify that the Console commerce contract is deployed before using this SDK version."
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
function fail(resource, path, expected) {
|
|
2118
|
+
invalidCanonicalResponse(resource, { path, expected });
|
|
2119
|
+
}
|
|
2120
|
+
function record(value, resource, path) {
|
|
2121
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2122
|
+
fail(resource, path, "object");
|
|
2123
|
+
}
|
|
2124
|
+
return value;
|
|
2125
|
+
}
|
|
2126
|
+
function exact(value, required, optional, resource, path) {
|
|
2127
|
+
for (const key of required) {
|
|
2128
|
+
if (!(key in value)) fail(resource, `${path}.${key}`, "required field");
|
|
2129
|
+
}
|
|
2130
|
+
const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
|
|
2131
|
+
const unexpected = Object.keys(value).find((key) => !allowed.has(key));
|
|
2132
|
+
if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
|
|
2133
|
+
}
|
|
2134
|
+
function string(value, resource, path) {
|
|
2135
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2136
|
+
fail(resource, path, "non-empty string");
|
|
2137
|
+
}
|
|
2138
|
+
return value;
|
|
2139
|
+
}
|
|
2140
|
+
function boundedString(value, maxLength, resource, path, allowEmpty = false) {
|
|
2141
|
+
if (typeof value !== "string" || !allowEmpty && value.length === 0 || value.length > maxLength) {
|
|
2142
|
+
fail(
|
|
2143
|
+
resource,
|
|
2144
|
+
path,
|
|
2145
|
+
`${allowEmpty ? "" : "non-empty "}string of at most ${maxLength} characters`
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
return value;
|
|
2149
|
+
}
|
|
2150
|
+
function nullableString(value, resource, path) {
|
|
2151
|
+
if (value !== null && typeof value !== "string") {
|
|
2152
|
+
fail(resource, path, "string or null");
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
function cartLineQuantity(value, resource, path) {
|
|
2156
|
+
const quantity = positiveInteger(value, resource, path);
|
|
2157
|
+
if (quantity > MAX_CART_LINE_QUANTITY) {
|
|
2158
|
+
fail(resource, path, `integer between 1 and ${MAX_CART_LINE_QUANTITY}`);
|
|
2159
|
+
}
|
|
2160
|
+
return quantity;
|
|
2161
|
+
}
|
|
2162
|
+
function boolean(value, resource, path) {
|
|
2163
|
+
if (typeof value !== "boolean") fail(resource, path, "boolean");
|
|
2164
|
+
}
|
|
2165
|
+
function safeMinor(value, resource, path) {
|
|
2166
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
2167
|
+
fail(resource, path, "non-negative safe integer");
|
|
2168
|
+
}
|
|
2169
|
+
return value;
|
|
2170
|
+
}
|
|
2171
|
+
function positiveInteger(value, resource, path) {
|
|
2172
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
2173
|
+
fail(resource, path, "positive safe integer");
|
|
2174
|
+
}
|
|
2175
|
+
return value;
|
|
2176
|
+
}
|
|
2177
|
+
function enumValue(value, values, resource, path) {
|
|
2178
|
+
if (typeof value !== "string" || !values.includes(value)) {
|
|
2179
|
+
fail(resource, path, values.join(" | "));
|
|
2180
|
+
}
|
|
2181
|
+
return value;
|
|
2182
|
+
}
|
|
2183
|
+
function timestamp(value, resource, path) {
|
|
2184
|
+
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(value) || !Number.isFinite(Date.parse(value))) {
|
|
2185
|
+
fail(resource, path, "ISO 8601 timestamp with offset");
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
function currency(value, resource, path) {
|
|
2189
|
+
if (typeof value !== "string" || !/^[A-Z]{3}$/.test(value)) {
|
|
2190
|
+
fail(resource, path, "three-letter uppercase currency code");
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
function array(value, resource, path) {
|
|
2194
|
+
if (!Array.isArray(value)) fail(resource, path, "array");
|
|
2195
|
+
return value;
|
|
2196
|
+
}
|
|
2197
|
+
function optionalNullableNumber(value, resource, path) {
|
|
2198
|
+
if (value !== void 0 && value !== null && typeof value !== "number") {
|
|
2199
|
+
fail(resource, path, "number or null");
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
function validateMediaSize(value, resource, path) {
|
|
2203
|
+
const item = record(value, resource, path);
|
|
2204
|
+
exact(
|
|
2205
|
+
item,
|
|
2206
|
+
[],
|
|
2207
|
+
["width", "height", "mimeType", "filename", "url"],
|
|
2208
|
+
resource,
|
|
2209
|
+
path
|
|
2210
|
+
);
|
|
2211
|
+
optionalNullableNumber(item.width, resource, `${path}.width`);
|
|
2212
|
+
optionalNullableNumber(item.height, resource, `${path}.height`);
|
|
2213
|
+
for (const key of ["mimeType", "filename", "url"]) {
|
|
2214
|
+
if (item[key] !== void 0)
|
|
2215
|
+
nullableString(item[key], resource, `${path}.${key}`);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
function validateMedia(value, resource, path) {
|
|
2219
|
+
if (typeof value === "string") return;
|
|
2220
|
+
const media = record(value, resource, path);
|
|
2221
|
+
exact(
|
|
2222
|
+
media,
|
|
2223
|
+
[],
|
|
2224
|
+
["id", "alt", "width", "height", "mimeType", "filename", "url", "sizes"],
|
|
2225
|
+
resource,
|
|
2226
|
+
path
|
|
2227
|
+
);
|
|
2228
|
+
if (media.id !== void 0 && media.id !== null && typeof media.id !== "string" && typeof media.id !== "number") {
|
|
2229
|
+
fail(resource, `${path}.id`, "string, number, or null");
|
|
2230
|
+
}
|
|
2231
|
+
for (const key of ["alt", "mimeType", "filename", "url"]) {
|
|
2232
|
+
if (media[key] !== void 0)
|
|
2233
|
+
nullableString(media[key], resource, `${path}.${key}`);
|
|
2234
|
+
}
|
|
2235
|
+
optionalNullableNumber(media.width, resource, `${path}.width`);
|
|
2236
|
+
optionalNullableNumber(media.height, resource, `${path}.height`);
|
|
2237
|
+
if (media.sizes !== void 0) {
|
|
2238
|
+
const sizes = record(media.sizes, resource, `${path}.sizes`);
|
|
2239
|
+
Object.entries(sizes).forEach(
|
|
2240
|
+
([key, size]) => validateMediaSize(size, resource, `${path}.sizes.${key}`)
|
|
2241
|
+
);
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
function validateReference(value, resource, path) {
|
|
2245
|
+
const ref = record(value, resource, path);
|
|
2246
|
+
exact(ref, ["id", "title", "handle", "image"], [], resource, path);
|
|
2247
|
+
string(ref.id, resource, `${path}.id`);
|
|
2248
|
+
string(ref.title, resource, `${path}.title`);
|
|
2249
|
+
if (ref.handle !== null) string(ref.handle, resource, `${path}.handle`);
|
|
2250
|
+
if (ref.image !== null) validateMedia(ref.image, resource, `${path}.image`);
|
|
2251
|
+
}
|
|
2252
|
+
function validateAdmission(value, resource, path) {
|
|
2253
|
+
const admission = record(value, resource, path);
|
|
2254
|
+
exact(
|
|
2255
|
+
admission,
|
|
2256
|
+
["eventId", "occurrenceId", "admissionTypeId"],
|
|
2257
|
+
[],
|
|
2258
|
+
resource,
|
|
2259
|
+
path
|
|
2260
|
+
);
|
|
2261
|
+
string(admission.eventId, resource, `${path}.eventId`);
|
|
2262
|
+
string(admission.occurrenceId, resource, `${path}.occurrenceId`);
|
|
2263
|
+
string(admission.admissionTypeId, resource, `${path}.admissionTypeId`);
|
|
2264
|
+
}
|
|
2265
|
+
function compareAdmissions(left, right) {
|
|
2266
|
+
for (const field of ["eventId", "occurrenceId", "admissionTypeId"]) {
|
|
2267
|
+
if (left[field] < right[field]) return -1;
|
|
2268
|
+
if (left[field] > right[field]) return 1;
|
|
2269
|
+
}
|
|
2270
|
+
return 0;
|
|
2271
|
+
}
|
|
2272
|
+
function validateAdmissions(value, resource, path) {
|
|
2273
|
+
const admissions = array(value, resource, path);
|
|
2274
|
+
if (admissions.length > 32) fail(resource, path, "at most 32 admissions");
|
|
2275
|
+
let prior;
|
|
2276
|
+
admissions.forEach((admission, index) => {
|
|
2277
|
+
validateAdmission(admission, resource, `${path}[${index}]`);
|
|
2278
|
+
const item = admission;
|
|
2279
|
+
const comparison = prior ? compareAdmissions(item, prior) : void 0;
|
|
2280
|
+
if (comparison !== void 0 && comparison <= 0) {
|
|
2281
|
+
fail(resource, `${path}[${index}]`, "unique canonical-sorted admissions");
|
|
2282
|
+
}
|
|
2283
|
+
prior = item;
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
function validateAttributes(value, resource, path) {
|
|
2287
|
+
const attributes = array(value, resource, path);
|
|
2288
|
+
if (attributes.length > 50) fail(resource, path, "at most 50 attributes");
|
|
2289
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2290
|
+
attributes.forEach((value2, index) => {
|
|
2291
|
+
const itemPath = `${path}[${index}]`;
|
|
2292
|
+
const attribute = record(value2, resource, itemPath);
|
|
2293
|
+
exact(attribute, ["key", "value"], [], resource, itemPath);
|
|
2294
|
+
const key = string(attribute.key, resource, `${itemPath}.key`);
|
|
2295
|
+
if (key.length > 40 || key.startsWith("__") || keys.has(key)) {
|
|
2296
|
+
fail(
|
|
2297
|
+
resource,
|
|
2298
|
+
`${itemPath}.key`,
|
|
2299
|
+
"unique, non-reserved key of at most 40 characters"
|
|
2300
|
+
);
|
|
2301
|
+
}
|
|
2302
|
+
keys.add(key);
|
|
2303
|
+
if (typeof attribute.value !== "string" || attribute.value.length > 500) {
|
|
2304
|
+
fail(resource, `${itemPath}.value`, "string of at most 500 characters");
|
|
2305
|
+
}
|
|
2306
|
+
});
|
|
2307
|
+
}
|
|
2308
|
+
function validateCustomer(value, resource, path) {
|
|
2309
|
+
const customer = record(value, resource, path);
|
|
2310
|
+
exact(customer, ["email"], ["name", "phone"], resource, path);
|
|
2311
|
+
const email = boundedString(
|
|
2312
|
+
customer.email,
|
|
2313
|
+
MAX_COMMERCE_EMAIL_LENGTH,
|
|
2314
|
+
resource,
|
|
2315
|
+
`${path}.email`
|
|
2316
|
+
);
|
|
2317
|
+
if (!/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9-]*\.)+[A-Za-z]{2,}$/.test(
|
|
2318
|
+
email
|
|
2319
|
+
)) {
|
|
2320
|
+
fail(resource, `${path}.email`, "email address");
|
|
2321
|
+
}
|
|
2322
|
+
if (customer.name !== void 0)
|
|
2323
|
+
boundedString(
|
|
2324
|
+
customer.name,
|
|
2325
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
2326
|
+
resource,
|
|
2327
|
+
`${path}.name`
|
|
2328
|
+
);
|
|
2329
|
+
if (customer.phone !== void 0)
|
|
2330
|
+
boundedString(
|
|
2331
|
+
customer.phone,
|
|
2332
|
+
MAX_COMMERCE_PHONE_LENGTH,
|
|
2333
|
+
resource,
|
|
2334
|
+
`${path}.phone`
|
|
2335
|
+
);
|
|
2336
|
+
}
|
|
2337
|
+
function validateShippingAddress(value, resource, path) {
|
|
2338
|
+
const address = record(value, resource, path);
|
|
2339
|
+
exact(
|
|
2340
|
+
address,
|
|
2341
|
+
["recipientName", "phone", "postalCode", "address", "detailAddress"],
|
|
2342
|
+
["countryCode", "regionCode", "deliveryMessage"],
|
|
2343
|
+
resource,
|
|
2344
|
+
path
|
|
2345
|
+
);
|
|
2346
|
+
boundedString(
|
|
2347
|
+
address.recipientName,
|
|
2348
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
2349
|
+
resource,
|
|
2350
|
+
`${path}.recipientName`
|
|
2351
|
+
);
|
|
2352
|
+
boundedString(
|
|
2353
|
+
address.phone,
|
|
2354
|
+
MAX_COMMERCE_PHONE_LENGTH,
|
|
2355
|
+
resource,
|
|
2356
|
+
`${path}.phone`
|
|
2357
|
+
);
|
|
2358
|
+
boundedString(
|
|
2359
|
+
address.postalCode,
|
|
2360
|
+
MAX_COMMERCE_POSTAL_CODE_LENGTH,
|
|
2361
|
+
resource,
|
|
2362
|
+
`${path}.postalCode`
|
|
2363
|
+
);
|
|
2364
|
+
for (const key of ["address", "detailAddress"]) {
|
|
2365
|
+
boundedString(
|
|
2366
|
+
address[key],
|
|
2367
|
+
MAX_COMMERCE_ADDRESS_LENGTH,
|
|
2368
|
+
resource,
|
|
2369
|
+
`${path}.${key}`
|
|
2370
|
+
);
|
|
2371
|
+
}
|
|
2372
|
+
if (address.countryCode !== void 0) {
|
|
2373
|
+
if (typeof address.countryCode !== "string" || address.countryCode.trim().length !== 2) {
|
|
2374
|
+
fail(resource, `${path}.countryCode`, "two-letter country code");
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
if (address.regionCode !== void 0) {
|
|
2378
|
+
if (typeof address.regionCode !== "string" || address.regionCode.trim().length === 0 || address.regionCode.trim().length > 64) {
|
|
2379
|
+
fail(
|
|
2380
|
+
resource,
|
|
2381
|
+
`${path}.regionCode`,
|
|
2382
|
+
"trimmed string of at most 64 characters"
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
if (address.deliveryMessage !== void 0) {
|
|
2387
|
+
boundedString(
|
|
2388
|
+
address.deliveryMessage,
|
|
2389
|
+
MAX_COMMERCE_EXTENSION_VALUE_LENGTH,
|
|
2390
|
+
resource,
|
|
2391
|
+
`${path}.deliveryMessage`,
|
|
2392
|
+
true
|
|
2393
|
+
);
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
function validateOrderReference(value, resource, path) {
|
|
2397
|
+
const order = record(value, resource, path);
|
|
2398
|
+
exact(order, ["id", "orderNumber"], [], resource, path);
|
|
2399
|
+
string(order.id, resource, `${path}.id`);
|
|
2400
|
+
string(order.orderNumber, resource, `${path}.orderNumber`);
|
|
2401
|
+
}
|
|
2402
|
+
function validateIntegrationMetadata(value, resource, path) {
|
|
2403
|
+
const metadata = record(value, resource, path);
|
|
2404
|
+
if (Object.keys(metadata).length > 50)
|
|
2405
|
+
fail(resource, path, "at most 50 entries");
|
|
2406
|
+
Object.entries(metadata).forEach(([key, entry]) => {
|
|
2407
|
+
if (!key || key.length > 40 || key.includes("[") || key.includes("]")) {
|
|
2408
|
+
fail(resource, `${path}.${key}`, "valid metadata key");
|
|
2409
|
+
}
|
|
2410
|
+
if (typeof entry !== "string" || entry.length > 500) {
|
|
2411
|
+
fail(resource, `${path}.${key}`, "string of at most 500 characters");
|
|
2412
|
+
}
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
function validateCartItem(value, resource, path) {
|
|
2416
|
+
const item = record(value, resource, path);
|
|
2417
|
+
exact(
|
|
2418
|
+
item,
|
|
2419
|
+
[
|
|
2420
|
+
"id",
|
|
2421
|
+
"product",
|
|
2422
|
+
"variant",
|
|
2423
|
+
"admissions",
|
|
2424
|
+
"quantity",
|
|
2425
|
+
"unitPriceMinor",
|
|
2426
|
+
"discountMinor",
|
|
2427
|
+
"estimatedLineTotalMinor",
|
|
2428
|
+
"requiresShipping"
|
|
2429
|
+
],
|
|
2430
|
+
[],
|
|
2431
|
+
resource,
|
|
2432
|
+
path
|
|
2433
|
+
);
|
|
2434
|
+
string(item.id, resource, `${path}.id`);
|
|
2435
|
+
validateReference(item.product, resource, `${path}.product`);
|
|
2436
|
+
validateReference(item.variant, resource, `${path}.variant`);
|
|
2437
|
+
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2438
|
+
cartLineQuantity(item.quantity, resource, `${path}.quantity`);
|
|
2439
|
+
const unitPrice = safeMinor(
|
|
2440
|
+
item.unitPriceMinor,
|
|
2441
|
+
resource,
|
|
2442
|
+
`${path}.unitPriceMinor`
|
|
2443
|
+
);
|
|
2444
|
+
const discount = safeMinor(
|
|
2445
|
+
item.discountMinor,
|
|
2446
|
+
resource,
|
|
2447
|
+
`${path}.discountMinor`
|
|
2448
|
+
);
|
|
2449
|
+
const estimatedLineTotal = safeMinor(
|
|
2450
|
+
item.estimatedLineTotalMinor,
|
|
2451
|
+
resource,
|
|
2452
|
+
`${path}.estimatedLineTotalMinor`
|
|
2453
|
+
);
|
|
2454
|
+
const quantity = item.quantity;
|
|
2455
|
+
const expectedLineTotal = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
|
|
2456
|
+
if (expectedLineTotal < 0n || BigInt(estimatedLineTotal) !== expectedLineTotal) {
|
|
2457
|
+
fail(
|
|
2458
|
+
resource,
|
|
2459
|
+
`${path}.estimatedLineTotalMinor`,
|
|
2460
|
+
"unitPriceMinor * quantity - discountMinor"
|
|
2461
|
+
);
|
|
2462
|
+
}
|
|
2463
|
+
boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
|
|
2464
|
+
}
|
|
2465
|
+
function validatePublicCart(value, resource = "Cart") {
|
|
2466
|
+
const cart = record(value, resource, "$");
|
|
2467
|
+
exact(
|
|
2468
|
+
cart,
|
|
2469
|
+
[
|
|
2470
|
+
"id",
|
|
2471
|
+
"status",
|
|
2472
|
+
"revision",
|
|
2473
|
+
"currency",
|
|
2474
|
+
"market",
|
|
2475
|
+
"subtotalMinor",
|
|
2476
|
+
"discountMinor",
|
|
2477
|
+
"estimatedTotalMinor",
|
|
2478
|
+
"discountCodes",
|
|
2479
|
+
"attributes",
|
|
2480
|
+
"items",
|
|
2481
|
+
"expiresAt",
|
|
2482
|
+
"createdAt",
|
|
2483
|
+
"updatedAt"
|
|
2484
|
+
],
|
|
2485
|
+
[],
|
|
2486
|
+
resource,
|
|
2487
|
+
"$"
|
|
2488
|
+
);
|
|
2489
|
+
string(cart.id, resource, "$.id");
|
|
2490
|
+
enumValue(cart.status, CART_STATUSES, resource, "$.status");
|
|
2491
|
+
safeMinor(cart.revision, resource, "$.revision");
|
|
2492
|
+
currency(cart.currency, resource, "$.currency");
|
|
2493
|
+
const market = record(cart.market, resource, "$.market");
|
|
2494
|
+
exact(market, ["id", "handle", "name"], [], resource, "$.market");
|
|
2495
|
+
for (const key of ["id", "handle", "name"])
|
|
2496
|
+
string(market[key], resource, `$.market.${key}`);
|
|
2497
|
+
const subtotal = safeMinor(cart.subtotalMinor, resource, "$.subtotalMinor");
|
|
2498
|
+
const discount = safeMinor(cart.discountMinor, resource, "$.discountMinor");
|
|
2499
|
+
const estimatedTotal = safeMinor(
|
|
2500
|
+
cart.estimatedTotalMinor,
|
|
2501
|
+
resource,
|
|
2502
|
+
"$.estimatedTotalMinor"
|
|
2503
|
+
);
|
|
2504
|
+
array(cart.discountCodes, resource, "$.discountCodes").forEach(
|
|
2505
|
+
(value2, index) => {
|
|
2506
|
+
const itemPath = `$.discountCodes[${index}]`;
|
|
2507
|
+
const code = record(value2, resource, itemPath);
|
|
2508
|
+
exact(code, ["code", "applicable"], [], resource, itemPath);
|
|
2509
|
+
boundedString(
|
|
2510
|
+
code.code,
|
|
2511
|
+
MAX_CART_DISCOUNT_CODE_LENGTH,
|
|
2512
|
+
resource,
|
|
2513
|
+
`${itemPath}.code`
|
|
2514
|
+
);
|
|
2515
|
+
boolean(code.applicable, resource, `${itemPath}.applicable`);
|
|
2516
|
+
}
|
|
2517
|
+
);
|
|
2518
|
+
validateAttributes(cart.attributes, resource, "$.attributes");
|
|
2519
|
+
const items = array(cart.items, resource, "$.items");
|
|
2520
|
+
items.forEach(
|
|
2521
|
+
(item, index) => validateCartItem(item, resource, `$.items[${index}]`)
|
|
2522
|
+
);
|
|
2523
|
+
const expectedSubtotal = items.reduce((total, value2) => {
|
|
2524
|
+
const item = value2;
|
|
2525
|
+
return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
|
|
2526
|
+
}, 0n);
|
|
2527
|
+
const expectedDiscount = items.reduce((total, value2) => {
|
|
2528
|
+
const item = value2;
|
|
2529
|
+
return total + BigInt(item.discountMinor);
|
|
2530
|
+
}, 0n);
|
|
2531
|
+
if (BigInt(subtotal) !== expectedSubtotal) {
|
|
2532
|
+
fail(resource, "$.subtotalMinor", "sum of undiscounted cart line totals");
|
|
2533
|
+
}
|
|
2534
|
+
if (BigInt(discount) !== expectedDiscount) {
|
|
2535
|
+
fail(resource, "$.discountMinor", "sum of cart line discounts");
|
|
2536
|
+
}
|
|
2537
|
+
if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
|
|
2538
|
+
fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
|
|
2539
|
+
}
|
|
2540
|
+
timestamp(cart.expiresAt, resource, "$.expiresAt");
|
|
2541
|
+
timestamp(cart.createdAt, resource, "$.createdAt");
|
|
2542
|
+
timestamp(cart.updatedAt, resource, "$.updatedAt");
|
|
2543
|
+
return value;
|
|
2544
|
+
}
|
|
2545
|
+
function validateWarnings(value, resource, path) {
|
|
2546
|
+
array(value, resource, path).forEach((value2, index) => {
|
|
2547
|
+
const itemPath = `${path}[${index}]`;
|
|
2548
|
+
const warning = record(value2, resource, itemPath);
|
|
2549
|
+
exact(warning, ["code", "message", "target"], [], resource, itemPath);
|
|
2550
|
+
enumValue(warning.code, CART_WARNING_CODES, resource, `${itemPath}.code`);
|
|
2551
|
+
string(warning.message, resource, `${itemPath}.message`);
|
|
2552
|
+
string(warning.target, resource, `${itemPath}.target`);
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
function validateCartMutationResult(value) {
|
|
2556
|
+
const result = record(value, "Cart mutation result", "$");
|
|
2557
|
+
exact(result, ["cart", "warnings"], [], "Cart mutation result", "$");
|
|
2558
|
+
validatePublicCart(result.cart);
|
|
2559
|
+
validateWarnings(result.warnings, "Cart mutation result", "$.warnings");
|
|
2560
|
+
return value;
|
|
2561
|
+
}
|
|
2562
|
+
function validateCreateCartResult(value) {
|
|
2563
|
+
const result = record(value, "Cart create result", "$");
|
|
2564
|
+
exact(
|
|
2565
|
+
result,
|
|
2566
|
+
["cart", "warnings", "cartToken"],
|
|
2567
|
+
[],
|
|
2568
|
+
"Cart create result",
|
|
2569
|
+
"$"
|
|
2570
|
+
);
|
|
2571
|
+
const cart = record(result.cart, "Cart create result", "$.cart");
|
|
2572
|
+
validatePublicCart(cart);
|
|
2573
|
+
if (cart.revision !== 0) {
|
|
2574
|
+
fail("Cart create result", "$.cart.revision", "0 for a newly created Cart");
|
|
2575
|
+
}
|
|
2576
|
+
validateWarnings(result.warnings, "Cart create result", "$.warnings");
|
|
2577
|
+
boundedString(
|
|
2578
|
+
result.cartToken,
|
|
2579
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
2580
|
+
"Cart create result",
|
|
2581
|
+
"$.cartToken"
|
|
2582
|
+
);
|
|
2583
|
+
return value;
|
|
2584
|
+
}
|
|
2585
|
+
function validateCartMineResult(value) {
|
|
2586
|
+
const result = record(value, "Cart mine result", "$");
|
|
2587
|
+
exact(result, ["cart", "cartToken"], [], "Cart mine result", "$");
|
|
2588
|
+
if (result.cart === null || result.cartToken === null) {
|
|
2589
|
+
if (result.cart !== null || result.cartToken !== null) {
|
|
2590
|
+
fail("Cart mine result", "$", "cart and cartToken must both be null");
|
|
2591
|
+
}
|
|
2592
|
+
} else {
|
|
2593
|
+
validatePublicCart(result.cart);
|
|
2594
|
+
boundedString(
|
|
2595
|
+
result.cartToken,
|
|
2596
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
2597
|
+
"Cart mine result",
|
|
2598
|
+
"$.cartToken"
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
return value;
|
|
2602
|
+
}
|
|
2603
|
+
function validateCartMergeResult(value) {
|
|
2604
|
+
const result = record(value, "Cart merge result", "$");
|
|
2605
|
+
exact(
|
|
2606
|
+
result,
|
|
2607
|
+
["cart", "warnings", "cartToken", "resolution", "merged", "claimed"],
|
|
2608
|
+
[],
|
|
2609
|
+
"Cart merge result",
|
|
2610
|
+
"$"
|
|
2611
|
+
);
|
|
2612
|
+
validatePublicCart(result.cart);
|
|
2613
|
+
validateWarnings(result.warnings, "Cart merge result", "$.warnings");
|
|
2614
|
+
boundedString(
|
|
2615
|
+
result.cartToken,
|
|
2616
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
2617
|
+
"Cart merge result",
|
|
2618
|
+
"$.cartToken"
|
|
2619
|
+
);
|
|
2620
|
+
const resolution = enumValue(
|
|
2621
|
+
result.resolution,
|
|
2622
|
+
["unchanged", "claimed", "merged"],
|
|
2623
|
+
"Cart merge result",
|
|
2624
|
+
"$.resolution"
|
|
2625
|
+
);
|
|
2626
|
+
boolean(result.merged, "Cart merge result", "$.merged");
|
|
2627
|
+
boolean(result.claimed, "Cart merge result", "$.claimed");
|
|
2628
|
+
const expected = resolution === "merged" ? [true, false] : resolution === "claimed" ? [false, true] : [false, false];
|
|
2629
|
+
if (result.merged !== expected[0] || result.claimed !== expected[1]) {
|
|
2630
|
+
fail("Cart merge result", "$", "resolution-consistent merged/claimed flags");
|
|
2631
|
+
}
|
|
2632
|
+
return value;
|
|
2633
|
+
}
|
|
2634
|
+
function validatePublicOrderItem(value, resource, path) {
|
|
2635
|
+
const item = record(value, resource, path);
|
|
2636
|
+
exact(
|
|
2637
|
+
item,
|
|
2638
|
+
[
|
|
2639
|
+
"id",
|
|
2640
|
+
"product",
|
|
2641
|
+
"variant",
|
|
2642
|
+
"productTitle",
|
|
2643
|
+
"variantTitle",
|
|
2644
|
+
"sku",
|
|
2645
|
+
"admissions",
|
|
2646
|
+
"quantity",
|
|
2647
|
+
"unitPriceMinor",
|
|
2648
|
+
"discountMinor",
|
|
2649
|
+
"lineTotalMinor",
|
|
2650
|
+
"requiresShipping"
|
|
2651
|
+
],
|
|
2652
|
+
[],
|
|
2653
|
+
resource,
|
|
2654
|
+
path
|
|
2655
|
+
);
|
|
2656
|
+
string(item.id, resource, `${path}.id`);
|
|
2657
|
+
if (item.product !== null) {
|
|
2658
|
+
validateReference(item.product, resource, `${path}.product`);
|
|
2659
|
+
}
|
|
2660
|
+
if (item.variant !== null) {
|
|
2661
|
+
validateReference(item.variant, resource, `${path}.variant`);
|
|
2662
|
+
}
|
|
2663
|
+
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2664
|
+
nullableString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
2665
|
+
nullableString(item.sku, resource, `${path}.sku`);
|
|
2666
|
+
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2667
|
+
const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
|
|
2668
|
+
const unitPrice = safeMinor(
|
|
2669
|
+
item.unitPriceMinor,
|
|
2670
|
+
resource,
|
|
2671
|
+
`${path}.unitPriceMinor`
|
|
2672
|
+
);
|
|
2673
|
+
const discount = safeMinor(
|
|
2674
|
+
item.discountMinor,
|
|
2675
|
+
resource,
|
|
2676
|
+
`${path}.discountMinor`
|
|
2677
|
+
);
|
|
2678
|
+
const lineTotal = safeMinor(
|
|
2679
|
+
item.lineTotalMinor,
|
|
2680
|
+
resource,
|
|
2681
|
+
`${path}.lineTotalMinor`
|
|
2682
|
+
);
|
|
2683
|
+
const expected = BigInt(unitPrice) * BigInt(quantity) - BigInt(discount);
|
|
2684
|
+
if (expected < 0n || BigInt(lineTotal) !== expected) {
|
|
2685
|
+
fail(
|
|
2686
|
+
resource,
|
|
2687
|
+
`${path}.lineTotalMinor`,
|
|
2688
|
+
"unitPriceMinor * quantity - discountMinor"
|
|
2689
|
+
);
|
|
2690
|
+
}
|
|
2691
|
+
boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
|
|
2692
|
+
}
|
|
2693
|
+
function validatePublicOrderAt(value, resource, path) {
|
|
2694
|
+
const order = record(value, resource, path);
|
|
2695
|
+
exact(
|
|
2696
|
+
order,
|
|
2697
|
+
[
|
|
2698
|
+
"id",
|
|
2699
|
+
"orderNumber",
|
|
2700
|
+
"amounts",
|
|
2701
|
+
"market",
|
|
2702
|
+
"customerSnapshot",
|
|
2703
|
+
"shippingAddress",
|
|
2704
|
+
"attributes",
|
|
2705
|
+
"items",
|
|
2706
|
+
"financialStatus",
|
|
2707
|
+
"fulfillmentStatus",
|
|
2708
|
+
"returnStatus",
|
|
2709
|
+
"confirmationStatus",
|
|
2710
|
+
"primaryDisplayStatus",
|
|
2711
|
+
"placedAt",
|
|
2712
|
+
"createdAt",
|
|
2713
|
+
"updatedAt"
|
|
2714
|
+
],
|
|
2715
|
+
[],
|
|
2716
|
+
resource,
|
|
2717
|
+
path
|
|
2718
|
+
);
|
|
2719
|
+
string(order.id, resource, `${path}.id`);
|
|
2720
|
+
string(order.orderNumber, resource, `${path}.orderNumber`);
|
|
2721
|
+
const amounts = record(order.amounts, resource, `${path}.amounts`);
|
|
2722
|
+
exact(
|
|
2723
|
+
amounts,
|
|
2724
|
+
[
|
|
2725
|
+
"currency",
|
|
2726
|
+
"subtotalMinor",
|
|
2727
|
+
"shippingMinor",
|
|
2728
|
+
"discountMinor",
|
|
2729
|
+
"totalMinor",
|
|
2730
|
+
"refundedMinor",
|
|
2731
|
+
"currentTotalMinor"
|
|
2732
|
+
],
|
|
2733
|
+
[],
|
|
2734
|
+
resource,
|
|
2735
|
+
`${path}.amounts`
|
|
2736
|
+
);
|
|
2737
|
+
currency(amounts.currency, resource, `${path}.amounts.currency`);
|
|
2738
|
+
const subtotal = safeMinor(
|
|
2739
|
+
amounts.subtotalMinor,
|
|
2740
|
+
resource,
|
|
2741
|
+
`${path}.amounts.subtotalMinor`
|
|
2742
|
+
);
|
|
2743
|
+
const shipping = safeMinor(
|
|
2744
|
+
amounts.shippingMinor,
|
|
2745
|
+
resource,
|
|
2746
|
+
`${path}.amounts.shippingMinor`
|
|
2747
|
+
);
|
|
2748
|
+
const discount = safeMinor(
|
|
2749
|
+
amounts.discountMinor,
|
|
2750
|
+
resource,
|
|
2751
|
+
`${path}.amounts.discountMinor`
|
|
2752
|
+
);
|
|
2753
|
+
const total = safeMinor(
|
|
2754
|
+
amounts.totalMinor,
|
|
2755
|
+
resource,
|
|
2756
|
+
`${path}.amounts.totalMinor`
|
|
2757
|
+
);
|
|
2758
|
+
const refunded = safeMinor(
|
|
2759
|
+
amounts.refundedMinor,
|
|
2760
|
+
resource,
|
|
2761
|
+
`${path}.amounts.refundedMinor`
|
|
2762
|
+
);
|
|
2763
|
+
const current = safeMinor(
|
|
2764
|
+
amounts.currentTotalMinor,
|
|
2765
|
+
resource,
|
|
2766
|
+
`${path}.amounts.currentTotalMinor`
|
|
2767
|
+
);
|
|
2768
|
+
const expectedTotal = BigInt(subtotal) + BigInt(shipping) - BigInt(discount);
|
|
2769
|
+
if (expectedTotal < 0n || BigInt(total) !== expectedTotal) {
|
|
2770
|
+
fail(
|
|
2771
|
+
resource,
|
|
2772
|
+
`${path}.amounts.totalMinor`,
|
|
2773
|
+
"subtotalMinor + shippingMinor - discountMinor"
|
|
2774
|
+
);
|
|
2775
|
+
}
|
|
2776
|
+
if (BigInt(total) - BigInt(refunded) < 0n || current !== total - refunded) {
|
|
2777
|
+
fail(
|
|
2778
|
+
resource,
|
|
2779
|
+
`${path}.amounts.currentTotalMinor`,
|
|
2780
|
+
"totalMinor - refundedMinor"
|
|
2781
|
+
);
|
|
2782
|
+
}
|
|
2783
|
+
if (order.market !== null) {
|
|
2784
|
+
const market = record(order.market, resource, `${path}.market`);
|
|
2785
|
+
exact(market, ["id", "handle", "name"], [], resource, `${path}.market`);
|
|
2786
|
+
for (const key of ["id", "handle", "name"]) {
|
|
2787
|
+
string(market[key], resource, `${path}.market.${key}`);
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
validateCustomer(order.customerSnapshot, resource, `${path}.customerSnapshot`);
|
|
2791
|
+
if (order.shippingAddress !== null) {
|
|
2792
|
+
validateShippingAddress(
|
|
2793
|
+
order.shippingAddress,
|
|
2794
|
+
resource,
|
|
2795
|
+
`${path}.shippingAddress`
|
|
2796
|
+
);
|
|
2797
|
+
}
|
|
2798
|
+
validateAttributes(order.attributes, resource, `${path}.attributes`);
|
|
2799
|
+
const items = array(order.items, resource, `${path}.items`);
|
|
2800
|
+
if (items.length === 0) fail(resource, `${path}.items`, "non-empty array");
|
|
2801
|
+
items.forEach(
|
|
2802
|
+
(item, index) => validatePublicOrderItem(item, resource, `${path}.items[${index}]`)
|
|
2803
|
+
);
|
|
2804
|
+
const expectedSubtotal = items.reduce((sum, value2) => {
|
|
2805
|
+
const item = value2;
|
|
2806
|
+
return sum + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
|
|
2807
|
+
}, 0n);
|
|
2808
|
+
const expectedDiscount = items.reduce((sum, value2) => {
|
|
2809
|
+
const item = value2;
|
|
2810
|
+
return sum + BigInt(item.discountMinor);
|
|
2811
|
+
}, 0n);
|
|
2812
|
+
if (BigInt(subtotal) !== expectedSubtotal) {
|
|
2813
|
+
fail(resource, `${path}.amounts.subtotalMinor`, "sum of line subtotals");
|
|
2814
|
+
}
|
|
2815
|
+
if (BigInt(discount) !== expectedDiscount) {
|
|
2816
|
+
fail(resource, `${path}.amounts.discountMinor`, "sum of line discounts");
|
|
2817
|
+
}
|
|
2818
|
+
enumValue(
|
|
2819
|
+
order.financialStatus,
|
|
2820
|
+
ORDER_FINANCIAL_STATUSES,
|
|
2821
|
+
resource,
|
|
2822
|
+
`${path}.financialStatus`
|
|
2823
|
+
);
|
|
2824
|
+
enumValue(
|
|
2825
|
+
order.fulfillmentStatus,
|
|
2826
|
+
ORDER_FULFILLMENT_STATUSES,
|
|
2827
|
+
resource,
|
|
2828
|
+
`${path}.fulfillmentStatus`
|
|
2829
|
+
);
|
|
2830
|
+
enumValue(
|
|
2831
|
+
order.returnStatus,
|
|
2832
|
+
ORDER_RETURN_STATUSES,
|
|
2833
|
+
resource,
|
|
2834
|
+
`${path}.returnStatus`
|
|
2835
|
+
);
|
|
2836
|
+
enumValue(
|
|
2837
|
+
order.confirmationStatus,
|
|
2838
|
+
ORDER_CONFIRMATION_STATUSES,
|
|
2839
|
+
resource,
|
|
2840
|
+
`${path}.confirmationStatus`
|
|
2841
|
+
);
|
|
2842
|
+
enumValue(
|
|
2843
|
+
order.primaryDisplayStatus,
|
|
2844
|
+
ORDER_PRIMARY_DISPLAY_STATUSES,
|
|
2845
|
+
resource,
|
|
2846
|
+
`${path}.primaryDisplayStatus`
|
|
2847
|
+
);
|
|
2848
|
+
timestamp(order.placedAt, resource, `${path}.placedAt`);
|
|
2849
|
+
timestamp(order.createdAt, resource, `${path}.createdAt`);
|
|
2850
|
+
timestamp(order.updatedAt, resource, `${path}.updatedAt`);
|
|
2851
|
+
}
|
|
2852
|
+
function nullablePositiveInteger(value, resource, path) {
|
|
2853
|
+
if (value !== null) positiveInteger(value, resource, path);
|
|
2854
|
+
}
|
|
2855
|
+
function validatePublicOrderList(value) {
|
|
2856
|
+
const resource = "Order list";
|
|
2857
|
+
const result = record(value, resource, "$");
|
|
2858
|
+
exact(
|
|
2859
|
+
result,
|
|
2860
|
+
[
|
|
2861
|
+
"docs",
|
|
2862
|
+
"totalDocs",
|
|
2863
|
+
"limit",
|
|
2864
|
+
"totalPages",
|
|
2865
|
+
"page",
|
|
2866
|
+
"pagingCounter",
|
|
2867
|
+
"hasPrevPage",
|
|
2868
|
+
"hasNextPage",
|
|
2869
|
+
"prevPage",
|
|
2870
|
+
"nextPage"
|
|
2871
|
+
],
|
|
2872
|
+
[],
|
|
2873
|
+
resource,
|
|
2874
|
+
"$"
|
|
2875
|
+
);
|
|
2876
|
+
array(result.docs, resource, "$.docs").forEach(
|
|
2877
|
+
(order, index) => validatePublicOrderAt(order, resource, `$.docs[${index}]`)
|
|
2878
|
+
);
|
|
2879
|
+
safeMinor(result.totalDocs, resource, "$.totalDocs");
|
|
2880
|
+
positiveInteger(result.limit, resource, "$.limit");
|
|
2881
|
+
safeMinor(result.totalPages, resource, "$.totalPages");
|
|
2882
|
+
positiveInteger(result.page, resource, "$.page");
|
|
2883
|
+
positiveInteger(result.pagingCounter, resource, "$.pagingCounter");
|
|
2884
|
+
boolean(result.hasPrevPage, resource, "$.hasPrevPage");
|
|
2885
|
+
boolean(result.hasNextPage, resource, "$.hasNextPage");
|
|
2886
|
+
nullablePositiveInteger(result.prevPage, resource, "$.prevPage");
|
|
2887
|
+
nullablePositiveInteger(result.nextPage, resource, "$.nextPage");
|
|
2888
|
+
return value;
|
|
2889
|
+
}
|
|
2890
|
+
function validateCheckoutItem(value, resource, path) {
|
|
2891
|
+
const item = record(value, resource, path);
|
|
2892
|
+
exact(
|
|
2893
|
+
item,
|
|
2894
|
+
[
|
|
2895
|
+
"id",
|
|
2896
|
+
"product",
|
|
2897
|
+
"variant",
|
|
2898
|
+
"productTitle",
|
|
2899
|
+
"variantTitle",
|
|
2900
|
+
"sku",
|
|
2901
|
+
"admissions",
|
|
2902
|
+
"quantity",
|
|
2903
|
+
"unitPriceMinor",
|
|
2904
|
+
"discountMinor",
|
|
2905
|
+
"lineTotalMinor",
|
|
2906
|
+
"requiresShipping"
|
|
2907
|
+
],
|
|
2908
|
+
[],
|
|
2909
|
+
resource,
|
|
2910
|
+
path
|
|
2911
|
+
);
|
|
2912
|
+
string(item.id, resource, `${path}.id`);
|
|
2913
|
+
validateReference(item.product, resource, `${path}.product`);
|
|
2914
|
+
validateReference(item.variant, resource, `${path}.variant`);
|
|
2915
|
+
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2916
|
+
nullableString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
2917
|
+
nullableString(item.sku, resource, `${path}.sku`);
|
|
2918
|
+
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2919
|
+
cartLineQuantity(item.quantity, resource, `${path}.quantity`);
|
|
2920
|
+
const unitPrice = safeMinor(
|
|
2921
|
+
item.unitPriceMinor,
|
|
2922
|
+
resource,
|
|
2923
|
+
`${path}.unitPriceMinor`
|
|
2924
|
+
);
|
|
2925
|
+
const discount = safeMinor(
|
|
2926
|
+
item.discountMinor,
|
|
2927
|
+
resource,
|
|
2928
|
+
`${path}.discountMinor`
|
|
2929
|
+
);
|
|
2930
|
+
const lineTotal = safeMinor(
|
|
2931
|
+
item.lineTotalMinor,
|
|
2932
|
+
resource,
|
|
2933
|
+
`${path}.lineTotalMinor`
|
|
2934
|
+
);
|
|
2935
|
+
const expectedLineTotal = BigInt(unitPrice) * BigInt(item.quantity) - BigInt(discount);
|
|
2936
|
+
if (expectedLineTotal < 0n || BigInt(lineTotal) !== expectedLineTotal) {
|
|
2937
|
+
fail(
|
|
2938
|
+
resource,
|
|
2939
|
+
`${path}.lineTotalMinor`,
|
|
2940
|
+
"unitPriceMinor * quantity - discountMinor"
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
boolean(item.requiresShipping, resource, `${path}.requiresShipping`);
|
|
2944
|
+
}
|
|
2945
|
+
function validateCheckoutAmounts(value, resource, path) {
|
|
2946
|
+
const amounts = record(value, resource, path);
|
|
2947
|
+
exact(
|
|
2948
|
+
amounts,
|
|
2949
|
+
[
|
|
2950
|
+
"currency",
|
|
2951
|
+
"subtotalMinor",
|
|
2952
|
+
"shippingMinor",
|
|
2953
|
+
"discountMinor",
|
|
2954
|
+
"totalMinor"
|
|
2955
|
+
],
|
|
2956
|
+
[],
|
|
2957
|
+
resource,
|
|
2958
|
+
path
|
|
2959
|
+
);
|
|
2960
|
+
currency(amounts.currency, resource, `${path}.currency`);
|
|
2961
|
+
const subtotal = safeMinor(
|
|
2962
|
+
amounts.subtotalMinor,
|
|
2963
|
+
resource,
|
|
2964
|
+
`${path}.subtotalMinor`
|
|
2965
|
+
);
|
|
2966
|
+
const shipping = safeMinor(
|
|
2967
|
+
amounts.shippingMinor,
|
|
2968
|
+
resource,
|
|
2969
|
+
`${path}.shippingMinor`
|
|
2970
|
+
);
|
|
2971
|
+
const discount = safeMinor(
|
|
2972
|
+
amounts.discountMinor,
|
|
2973
|
+
resource,
|
|
2974
|
+
`${path}.discountMinor`
|
|
2975
|
+
);
|
|
2976
|
+
const total = safeMinor(amounts.totalMinor, resource, `${path}.totalMinor`);
|
|
2977
|
+
if (BigInt(total) !== BigInt(subtotal) + BigInt(shipping) - BigInt(discount)) {
|
|
2978
|
+
fail(
|
|
2979
|
+
resource,
|
|
2980
|
+
`${path}.totalMinor`,
|
|
2981
|
+
"subtotalMinor + shippingMinor - discountMinor"
|
|
2982
|
+
);
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
function validatePaymentSessionReference(value, resource, path) {
|
|
2986
|
+
const session = record(value, resource, path);
|
|
2987
|
+
exact(session, ["id", "provider", "providerStatus"], [], resource, path);
|
|
2988
|
+
string(session.id, resource, `${path}.id`);
|
|
2989
|
+
enumValue(session.provider, PAYMENT_PROVIDERS, resource, `${path}.provider`);
|
|
2990
|
+
enumValue(
|
|
2991
|
+
session.providerStatus,
|
|
2992
|
+
PAYMENT_PROVIDER_STATUSES,
|
|
2993
|
+
resource,
|
|
2994
|
+
`${path}.providerStatus`
|
|
2995
|
+
);
|
|
2996
|
+
}
|
|
2997
|
+
function checkoutVariantKeys(status, placedVia) {
|
|
2998
|
+
const base = [
|
|
2999
|
+
"id",
|
|
3000
|
+
"amounts",
|
|
3001
|
+
"items",
|
|
3002
|
+
"customerSnapshot",
|
|
3003
|
+
"shippingAddress",
|
|
3004
|
+
"attributes",
|
|
3005
|
+
"expiresAt",
|
|
3006
|
+
"createdAt",
|
|
3007
|
+
"updatedAt",
|
|
3008
|
+
"status",
|
|
3009
|
+
"paymentState",
|
|
3010
|
+
"order"
|
|
3011
|
+
];
|
|
3012
|
+
if (status === "open") return { required: base, optional: [] };
|
|
3013
|
+
if (status === "abandoned") {
|
|
3014
|
+
return {
|
|
3015
|
+
required: [...base, "abandonedAt", "abandonedReason"],
|
|
3016
|
+
optional: []
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
return placedVia === "late_capture" ? {
|
|
3020
|
+
required: [
|
|
3021
|
+
...base,
|
|
3022
|
+
"placedAt",
|
|
3023
|
+
"placedVia",
|
|
3024
|
+
"abandonedAt",
|
|
3025
|
+
"abandonedReason"
|
|
3026
|
+
],
|
|
3027
|
+
optional: []
|
|
3028
|
+
} : { required: [...base, "placedAt"], optional: [] };
|
|
3029
|
+
}
|
|
3030
|
+
function validateCheckoutCore(value, resource, list, server) {
|
|
3031
|
+
const checkout = record(value, resource, "$");
|
|
3032
|
+
const status = enumValue(
|
|
3033
|
+
checkout.status,
|
|
3034
|
+
CHECKOUT_STATUSES,
|
|
3035
|
+
resource,
|
|
3036
|
+
"$.status"
|
|
3037
|
+
);
|
|
3038
|
+
const keys = checkoutVariantKeys(status, checkout.placedVia);
|
|
3039
|
+
if (list) {
|
|
3040
|
+
keys.required = keys.required.filter(
|
|
3041
|
+
(key) => !["items", "shippingAddress", "attributes"].includes(key)
|
|
3042
|
+
);
|
|
3043
|
+
keys.required.push("clientReferenceId");
|
|
3044
|
+
} else if (server) {
|
|
3045
|
+
keys.required.push("clientReferenceId", "integrationMetadata");
|
|
3046
|
+
}
|
|
3047
|
+
exact(checkout, keys.required, keys.optional, resource, "$");
|
|
3048
|
+
string(checkout.id, resource, "$.id");
|
|
3049
|
+
validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
|
|
3050
|
+
if (!list) {
|
|
3051
|
+
const items = array(checkout.items, resource, "$.items");
|
|
3052
|
+
if (items.length === 0) fail(resource, "$.items", "non-empty array");
|
|
3053
|
+
items.forEach(
|
|
3054
|
+
(item, index) => validateCheckoutItem(item, resource, `$.items[${index}]`)
|
|
3055
|
+
);
|
|
3056
|
+
const expectedSubtotal = items.reduce((total, value2) => {
|
|
3057
|
+
const item = value2;
|
|
3058
|
+
return total + BigInt(item.unitPriceMinor) * BigInt(item.quantity);
|
|
3059
|
+
}, 0n);
|
|
3060
|
+
const expectedDiscount = items.reduce((total, value2) => {
|
|
3061
|
+
const item = value2;
|
|
3062
|
+
return total + BigInt(item.discountMinor);
|
|
3063
|
+
}, 0n);
|
|
3064
|
+
const amounts = checkout.amounts;
|
|
3065
|
+
if (BigInt(amounts.subtotalMinor) !== expectedSubtotal) {
|
|
3066
|
+
fail(
|
|
3067
|
+
resource,
|
|
3068
|
+
"$.amounts.subtotalMinor",
|
|
3069
|
+
"sum of undiscounted checkout line totals"
|
|
3070
|
+
);
|
|
3071
|
+
}
|
|
3072
|
+
if (BigInt(amounts.discountMinor) !== expectedDiscount) {
|
|
3073
|
+
fail(
|
|
3074
|
+
resource,
|
|
3075
|
+
"$.amounts.discountMinor",
|
|
3076
|
+
"sum of checkout line discounts"
|
|
3077
|
+
);
|
|
3078
|
+
}
|
|
3079
|
+
if (checkout.shippingAddress !== null) {
|
|
3080
|
+
validateShippingAddress(
|
|
3081
|
+
checkout.shippingAddress,
|
|
3082
|
+
resource,
|
|
3083
|
+
"$.shippingAddress"
|
|
3084
|
+
);
|
|
3085
|
+
}
|
|
3086
|
+
validateAttributes(checkout.attributes, resource, "$.attributes");
|
|
3087
|
+
}
|
|
3088
|
+
validateCustomer(checkout.customerSnapshot, resource, "$.customerSnapshot");
|
|
3089
|
+
timestamp(checkout.expiresAt, resource, "$.expiresAt");
|
|
3090
|
+
timestamp(checkout.createdAt, resource, "$.createdAt");
|
|
3091
|
+
timestamp(checkout.updatedAt, resource, "$.updatedAt");
|
|
3092
|
+
const paymentState = record(checkout.paymentState, resource, "$.paymentState");
|
|
3093
|
+
exact(paymentState, ["activePaymentSession"], [], resource, "$.paymentState");
|
|
3094
|
+
if (status === "open") {
|
|
3095
|
+
if (paymentState.activePaymentSession !== null) {
|
|
3096
|
+
validatePaymentSessionReference(
|
|
3097
|
+
paymentState.activePaymentSession,
|
|
3098
|
+
resource,
|
|
3099
|
+
"$.paymentState.activePaymentSession"
|
|
3100
|
+
);
|
|
3101
|
+
}
|
|
3102
|
+
if (checkout.order !== null)
|
|
3103
|
+
fail(resource, "$.order", "null for open Checkout");
|
|
3104
|
+
} else {
|
|
3105
|
+
if (paymentState.activePaymentSession !== null) {
|
|
3106
|
+
fail(
|
|
3107
|
+
resource,
|
|
3108
|
+
"$.paymentState.activePaymentSession",
|
|
3109
|
+
"null for spent Checkout"
|
|
3110
|
+
);
|
|
3111
|
+
}
|
|
3112
|
+
if (status === "placed") {
|
|
3113
|
+
timestamp(checkout.placedAt, resource, "$.placedAt");
|
|
3114
|
+
validateOrderReference(checkout.order, resource, "$.order");
|
|
3115
|
+
if (checkout.placedVia !== void 0 && checkout.placedVia !== "late_capture") {
|
|
3116
|
+
fail(resource, "$.placedVia", "late_capture");
|
|
3117
|
+
}
|
|
3118
|
+
if (checkout.placedVia === "late_capture") {
|
|
3119
|
+
timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
|
|
3120
|
+
enumValue(
|
|
3121
|
+
checkout.abandonedReason,
|
|
3122
|
+
ABANDONED_REASONS,
|
|
3123
|
+
resource,
|
|
3124
|
+
"$.abandonedReason"
|
|
3125
|
+
);
|
|
3126
|
+
}
|
|
3127
|
+
} else {
|
|
3128
|
+
timestamp(checkout.abandonedAt, resource, "$.abandonedAt");
|
|
3129
|
+
enumValue(
|
|
3130
|
+
checkout.abandonedReason,
|
|
3131
|
+
ABANDONED_REASONS,
|
|
3132
|
+
resource,
|
|
3133
|
+
"$.abandonedReason"
|
|
3134
|
+
);
|
|
3135
|
+
if (checkout.order !== null)
|
|
3136
|
+
fail(resource, "$.order", "null for abandoned Checkout");
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
if (list || server) {
|
|
3140
|
+
if (checkout.clientReferenceId !== null) {
|
|
3141
|
+
boundedString(
|
|
3142
|
+
checkout.clientReferenceId,
|
|
3143
|
+
MAX_COMMERCE_RESOURCE_ID_LENGTH,
|
|
3144
|
+
resource,
|
|
3145
|
+
"$.clientReferenceId"
|
|
3146
|
+
);
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
if (server)
|
|
3150
|
+
validateIntegrationMetadata(
|
|
3151
|
+
checkout.integrationMetadata,
|
|
3152
|
+
resource,
|
|
3153
|
+
"$.integrationMetadata"
|
|
3154
|
+
);
|
|
3155
|
+
}
|
|
3156
|
+
function validatePublicCheckout(value) {
|
|
3157
|
+
validateCheckoutCore(value, "Checkout", false, false);
|
|
3158
|
+
return value;
|
|
3159
|
+
}
|
|
3160
|
+
function validateServerCheckout(value) {
|
|
3161
|
+
validateCheckoutCore(value, "Server Checkout", false, true);
|
|
3162
|
+
return value;
|
|
3163
|
+
}
|
|
3164
|
+
function validateCreateCheckoutResult(value, server) {
|
|
3165
|
+
const resource = server ? "Server Checkout create result" : "Checkout create result";
|
|
3166
|
+
const result = record(value, resource, "$");
|
|
3167
|
+
exact(result, ["checkout", "checkoutToken"], [], resource, "$");
|
|
3168
|
+
if (server) validateServerCheckout(result.checkout);
|
|
3169
|
+
else validatePublicCheckout(result.checkout);
|
|
3170
|
+
boundedString(
|
|
3171
|
+
result.checkoutToken,
|
|
3172
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
3173
|
+
resource,
|
|
3174
|
+
"$.checkoutToken"
|
|
3175
|
+
);
|
|
3176
|
+
return value;
|
|
3177
|
+
}
|
|
3178
|
+
function validateCheckoutQueryResult(value) {
|
|
3179
|
+
const result = record(value, "Checkout query result", "$");
|
|
3180
|
+
exact(
|
|
3181
|
+
result,
|
|
3182
|
+
["data", "hasMore", "nextCursor"],
|
|
3183
|
+
[],
|
|
3184
|
+
"Checkout query result",
|
|
3185
|
+
"$"
|
|
3186
|
+
);
|
|
3187
|
+
array(result.data, "Checkout query result", "$.data").forEach(
|
|
3188
|
+
(item) => validateCheckoutCore(item, "Checkout list item", true, false)
|
|
3189
|
+
);
|
|
3190
|
+
boolean(result.hasMore, "Checkout query result", "$.hasMore");
|
|
3191
|
+
if (result.nextCursor !== null)
|
|
3192
|
+
boundedString(
|
|
3193
|
+
result.nextCursor,
|
|
3194
|
+
MAX_COMMERCE_CAPABILITY_LENGTH,
|
|
3195
|
+
"Checkout query result",
|
|
3196
|
+
"$.nextCursor"
|
|
3197
|
+
);
|
|
3198
|
+
if (result.hasMore === true && result.nextCursor === null) {
|
|
3199
|
+
fail(
|
|
3200
|
+
"Checkout query result",
|
|
3201
|
+
"$.nextCursor",
|
|
3202
|
+
"non-null when hasMore is true"
|
|
3203
|
+
);
|
|
3204
|
+
}
|
|
3205
|
+
return value;
|
|
3206
|
+
}
|
|
3207
|
+
function validateMoney(value, resource, path) {
|
|
3208
|
+
const money = record(value, resource, path);
|
|
3209
|
+
exact(money, ["amountMinor", "currency"], [], resource, path);
|
|
3210
|
+
safeMinor(money.amountMinor, resource, `${path}.amountMinor`);
|
|
3211
|
+
currency(money.currency, resource, `${path}.currency`);
|
|
3212
|
+
}
|
|
3213
|
+
function validateCaptureEvidence(value, resource, path) {
|
|
3214
|
+
const evidence = record(value, resource, path);
|
|
3215
|
+
exact(evidence, ["amountMinor", "currency", "observedAt"], [], resource, path);
|
|
3216
|
+
safeMinor(evidence.amountMinor, resource, `${path}.amountMinor`);
|
|
3217
|
+
currency(evidence.currency, resource, `${path}.currency`);
|
|
3218
|
+
timestamp(evidence.observedAt, resource, `${path}.observedAt`);
|
|
3219
|
+
}
|
|
3220
|
+
function validateNoReconciliation(value, resource, path) {
|
|
3221
|
+
const reconciliation = record(value, resource, path);
|
|
3222
|
+
exact(reconciliation, ["status"], [], resource, path);
|
|
3223
|
+
if (reconciliation.status !== "none") fail(resource, `${path}.status`, "none");
|
|
3224
|
+
}
|
|
3225
|
+
function validateRequiredReconciliation(value, allowed, resource, path) {
|
|
3226
|
+
const reconciliation = record(value, resource, path);
|
|
3227
|
+
exact(reconciliation, ["status", "reasons"], [], resource, path);
|
|
3228
|
+
if (reconciliation.status !== "required")
|
|
3229
|
+
fail(resource, `${path}.status`, "required");
|
|
3230
|
+
const reasons = array(reconciliation.reasons, resource, `${path}.reasons`);
|
|
3231
|
+
if (reasons.length === 0) fail(resource, `${path}.reasons`, "non-empty array");
|
|
3232
|
+
let previous = -1;
|
|
3233
|
+
reasons.forEach((reason, index) => {
|
|
3234
|
+
const current = allowed.indexOf(reason);
|
|
3235
|
+
if (current < 0 || current <= previous) {
|
|
3236
|
+
fail(
|
|
3237
|
+
resource,
|
|
3238
|
+
`${path}.reasons[${index}]`,
|
|
3239
|
+
"unique canonical-sorted reconciliation reason"
|
|
3240
|
+
);
|
|
3241
|
+
}
|
|
3242
|
+
previous = current;
|
|
3243
|
+
});
|
|
3244
|
+
}
|
|
3245
|
+
function validateNextAction(value, resource, path) {
|
|
3246
|
+
const action = record(value, resource, path);
|
|
3247
|
+
exact(
|
|
3248
|
+
action,
|
|
3249
|
+
[
|
|
3250
|
+
"type",
|
|
3251
|
+
"clientKey",
|
|
3252
|
+
"paymentMethodVariantKey",
|
|
3253
|
+
"agreementVariantKey",
|
|
3254
|
+
"providerOrderId",
|
|
3255
|
+
"providerCustomerKey",
|
|
3256
|
+
"orderName"
|
|
3257
|
+
],
|
|
3258
|
+
["customerName", "customerEmail"],
|
|
3259
|
+
resource,
|
|
3260
|
+
path
|
|
3261
|
+
);
|
|
3262
|
+
if (action.type !== "toss_widget")
|
|
3263
|
+
fail(resource, `${path}.type`, "toss_widget");
|
|
3264
|
+
for (const key of [
|
|
3265
|
+
"clientKey",
|
|
3266
|
+
"paymentMethodVariantKey",
|
|
3267
|
+
"agreementVariantKey"
|
|
3268
|
+
]) {
|
|
3269
|
+
boundedString(action[key], 255, resource, `${path}.${key}`);
|
|
3270
|
+
}
|
|
3271
|
+
string(action.providerOrderId, resource, `${path}.providerOrderId`);
|
|
3272
|
+
string(action.providerCustomerKey, resource, `${path}.providerCustomerKey`);
|
|
3273
|
+
boundedString(
|
|
3274
|
+
action.orderName,
|
|
3275
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
3276
|
+
resource,
|
|
3277
|
+
`${path}.orderName`
|
|
3278
|
+
);
|
|
3279
|
+
if (!/^[A-Za-z0-9_-]{6,64}$/.test(action.providerOrderId)) {
|
|
3280
|
+
fail(resource, `${path}.providerOrderId`, "valid Toss provider order ID");
|
|
3281
|
+
}
|
|
3282
|
+
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(
|
|
3283
|
+
action.providerCustomerKey
|
|
3284
|
+
)) {
|
|
3285
|
+
fail(resource, `${path}.providerCustomerKey`, "ANONYMOUS or UUIDv4");
|
|
3286
|
+
}
|
|
3287
|
+
if (action.customerName !== void 0)
|
|
3288
|
+
boundedString(
|
|
3289
|
+
action.customerName,
|
|
3290
|
+
MAX_COMMERCE_SHORT_TEXT_LENGTH,
|
|
3291
|
+
resource,
|
|
3292
|
+
`${path}.customerName`
|
|
3293
|
+
);
|
|
3294
|
+
if (action.customerEmail !== void 0)
|
|
3295
|
+
validateCustomer({ email: action.customerEmail }, resource, path);
|
|
3296
|
+
}
|
|
3297
|
+
function validatePublicPaymentSession(value) {
|
|
3298
|
+
const resource = "PaymentSession";
|
|
3299
|
+
const session = record(value, resource, "$");
|
|
3300
|
+
enumValue(session.provider, PAYMENT_PROVIDERS, resource, "$.provider");
|
|
3301
|
+
const status = enumValue(
|
|
3302
|
+
session.providerStatus,
|
|
3303
|
+
PAYMENT_PROVIDER_STATUSES,
|
|
3304
|
+
resource,
|
|
3305
|
+
"$.providerStatus"
|
|
3306
|
+
);
|
|
3307
|
+
const common = [
|
|
3308
|
+
"id",
|
|
3309
|
+
"money",
|
|
3310
|
+
"expiresAt",
|
|
3311
|
+
"sessionRole",
|
|
3312
|
+
"provider",
|
|
3313
|
+
"providerStatus",
|
|
3314
|
+
"presentationStatus",
|
|
3315
|
+
"finalizationStatus",
|
|
3316
|
+
"reconciliation",
|
|
3317
|
+
"order"
|
|
3318
|
+
];
|
|
3319
|
+
const optional = [];
|
|
3320
|
+
if (status === "requires_payment_method" || status === "requires_action")
|
|
3321
|
+
optional.push("nextAction");
|
|
3322
|
+
else if (status === "captured") common.push("providerEvidence");
|
|
3323
|
+
else if (status === "failed") common.push("failure");
|
|
3324
|
+
else if (status === "canceled") common.push("cancellationReason");
|
|
3325
|
+
exact(session, common, optional, resource, "$");
|
|
3326
|
+
string(session.id, resource, "$.id");
|
|
3327
|
+
validateMoney(session.money, resource, "$.money");
|
|
3328
|
+
if (session.expiresAt !== null)
|
|
3329
|
+
timestamp(session.expiresAt, resource, "$.expiresAt");
|
|
3330
|
+
if (status === "requires_payment_method" || status === "requires_action") {
|
|
3331
|
+
if (session.sessionRole === "active") {
|
|
3332
|
+
if (session.presentationStatus !== "actionable" || session.finalizationStatus !== "not_ready") {
|
|
3333
|
+
fail(resource, "$", "actionable active not-ready state");
|
|
3334
|
+
}
|
|
3335
|
+
if (!("nextAction" in session))
|
|
3336
|
+
fail(resource, "$.nextAction", "required field");
|
|
3337
|
+
validateNextAction(session.nextAction, resource, "$.nextAction");
|
|
3338
|
+
} else if (session.sessionRole === "residual") {
|
|
3339
|
+
if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
|
|
3340
|
+
fail(resource, "$", "suppressed residual not-ready state");
|
|
3341
|
+
}
|
|
3342
|
+
if ("nextAction" in session)
|
|
3343
|
+
fail(resource, "$.nextAction", "absent for suppressed state");
|
|
3344
|
+
} else fail(resource, "$.sessionRole", "active | residual");
|
|
3345
|
+
validateNoReconciliation(
|
|
3346
|
+
session.reconciliation,
|
|
3347
|
+
resource,
|
|
3348
|
+
"$.reconciliation"
|
|
3349
|
+
);
|
|
3350
|
+
if (session.order !== null) fail(resource, "$.order", "null");
|
|
3351
|
+
} else if ([
|
|
3352
|
+
"requires_confirmation",
|
|
3353
|
+
"initializing",
|
|
3354
|
+
"processing",
|
|
3355
|
+
"authorized",
|
|
3356
|
+
"canceling"
|
|
3357
|
+
].includes(status)) {
|
|
3358
|
+
enumValue(
|
|
3359
|
+
session.sessionRole,
|
|
3360
|
+
["active", "residual"],
|
|
3361
|
+
resource,
|
|
3362
|
+
"$.sessionRole"
|
|
3363
|
+
);
|
|
3364
|
+
if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
|
|
3365
|
+
fail(resource, "$", "suppressed not-ready state");
|
|
3366
|
+
}
|
|
3367
|
+
validateNoReconciliation(
|
|
3368
|
+
session.reconciliation,
|
|
3369
|
+
resource,
|
|
3370
|
+
"$.reconciliation"
|
|
3371
|
+
);
|
|
3372
|
+
if (session.order !== null) fail(resource, "$.order", "null");
|
|
3373
|
+
} else if (status === "unknown") {
|
|
3374
|
+
enumValue(
|
|
3375
|
+
session.sessionRole,
|
|
3376
|
+
["active", "residual"],
|
|
3377
|
+
resource,
|
|
3378
|
+
"$.sessionRole"
|
|
3379
|
+
);
|
|
3380
|
+
if (session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready") {
|
|
3381
|
+
fail(resource, "$", "suppressed not-ready state");
|
|
3382
|
+
}
|
|
3383
|
+
validateRequiredReconciliation(
|
|
3384
|
+
session.reconciliation,
|
|
3385
|
+
["provider_outcome_unknown"],
|
|
3386
|
+
resource,
|
|
3387
|
+
"$.reconciliation"
|
|
3388
|
+
);
|
|
3389
|
+
if (session.order !== null) fail(resource, "$.order", "null");
|
|
3390
|
+
} else if (status === "captured") {
|
|
3391
|
+
validateCaptureEvidence(
|
|
3392
|
+
session.providerEvidence,
|
|
3393
|
+
resource,
|
|
3394
|
+
"$.providerEvidence"
|
|
3395
|
+
);
|
|
3396
|
+
if (session.presentationStatus !== "suppressed")
|
|
3397
|
+
fail(resource, "$.presentationStatus", "suppressed");
|
|
3398
|
+
if (session.finalizationStatus === "pending") {
|
|
3399
|
+
enumValue(
|
|
3400
|
+
session.sessionRole,
|
|
3401
|
+
["canonical_candidate", "residual"],
|
|
3402
|
+
resource,
|
|
3403
|
+
"$.sessionRole"
|
|
3404
|
+
);
|
|
3405
|
+
if (session.order !== null)
|
|
3406
|
+
fail(resource, "$.order", "null for pending finalization");
|
|
3407
|
+
const reconciliation = record(
|
|
3408
|
+
session.reconciliation,
|
|
3409
|
+
resource,
|
|
3410
|
+
"$.reconciliation"
|
|
3411
|
+
);
|
|
3412
|
+
if (reconciliation.status === "none")
|
|
3413
|
+
validateNoReconciliation(reconciliation, resource, "$.reconciliation");
|
|
3414
|
+
else
|
|
3415
|
+
validateRequiredReconciliation(
|
|
3416
|
+
reconciliation,
|
|
3417
|
+
[
|
|
3418
|
+
"local_commit_ambiguous",
|
|
3419
|
+
"amount_mismatch",
|
|
3420
|
+
"currency_mismatch",
|
|
3421
|
+
"excess_capture_pending_order"
|
|
3422
|
+
],
|
|
3423
|
+
resource,
|
|
3424
|
+
"$.reconciliation"
|
|
3425
|
+
);
|
|
3426
|
+
} else if (session.finalizationStatus === "committed") {
|
|
3427
|
+
validateOrderReference(session.order, resource, "$.order");
|
|
3428
|
+
const reconciliation = record(
|
|
3429
|
+
session.reconciliation,
|
|
3430
|
+
resource,
|
|
3431
|
+
"$.reconciliation"
|
|
3432
|
+
);
|
|
3433
|
+
if (reconciliation.status === "none") {
|
|
3434
|
+
enumValue(
|
|
3435
|
+
session.sessionRole,
|
|
3436
|
+
["canonical", "historical"],
|
|
3437
|
+
resource,
|
|
3438
|
+
"$.sessionRole"
|
|
3439
|
+
);
|
|
3440
|
+
validateNoReconciliation(reconciliation, resource, "$.reconciliation");
|
|
3441
|
+
} else {
|
|
3442
|
+
enumValue(
|
|
3443
|
+
session.sessionRole,
|
|
3444
|
+
["canonical", "residual"],
|
|
3445
|
+
resource,
|
|
3446
|
+
"$.sessionRole"
|
|
3447
|
+
);
|
|
3448
|
+
validateRequiredReconciliation(
|
|
3449
|
+
reconciliation,
|
|
3450
|
+
[
|
|
3451
|
+
"inventory_unavailable",
|
|
3452
|
+
"admission_unavailable",
|
|
3453
|
+
"amount_mismatch",
|
|
3454
|
+
"currency_mismatch",
|
|
3455
|
+
"excess_capture",
|
|
3456
|
+
"late_capture",
|
|
3457
|
+
"cross_checkout_duplicate"
|
|
3458
|
+
],
|
|
3459
|
+
resource,
|
|
3460
|
+
"$.reconciliation"
|
|
3461
|
+
);
|
|
3462
|
+
}
|
|
3463
|
+
} else fail(resource, "$.finalizationStatus", "pending | committed");
|
|
3464
|
+
} else if (status === "failed") {
|
|
3465
|
+
if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
|
|
3466
|
+
fail(resource, "$", "historical suppressed failed state");
|
|
3467
|
+
}
|
|
3468
|
+
validateNoReconciliation(
|
|
3469
|
+
session.reconciliation,
|
|
3470
|
+
resource,
|
|
3471
|
+
"$.reconciliation"
|
|
3472
|
+
);
|
|
3473
|
+
const failure = record(session.failure, resource, "$.failure");
|
|
3474
|
+
exact(failure, ["reason"], ["message"], resource, "$.failure");
|
|
3475
|
+
enumValue(
|
|
3476
|
+
failure.reason,
|
|
3477
|
+
PAYMENT_FAILURE_REASONS,
|
|
3478
|
+
resource,
|
|
3479
|
+
"$.failure.reason"
|
|
3480
|
+
);
|
|
3481
|
+
if (failure.message !== void 0)
|
|
3482
|
+
string(failure.message, resource, "$.failure.message");
|
|
3483
|
+
} else {
|
|
3484
|
+
if (session.sessionRole !== "historical" || session.presentationStatus !== "suppressed" || session.finalizationStatus !== "not_ready" || session.order !== null) {
|
|
3485
|
+
fail(resource, "$", "historical suppressed canceled state");
|
|
3486
|
+
}
|
|
3487
|
+
validateNoReconciliation(
|
|
3488
|
+
session.reconciliation,
|
|
3489
|
+
resource,
|
|
3490
|
+
"$.reconciliation"
|
|
3491
|
+
);
|
|
3492
|
+
enumValue(
|
|
3493
|
+
session.cancellationReason,
|
|
3494
|
+
["expired", "customer", "operator", "provider"],
|
|
3495
|
+
resource,
|
|
3496
|
+
"$.cancellationReason"
|
|
3497
|
+
);
|
|
3498
|
+
}
|
|
3499
|
+
return value;
|
|
1581
3500
|
}
|
|
1582
|
-
var ContentClient = class {
|
|
1583
|
-
constructor(options) {
|
|
1584
|
-
const api = new PublicContentApi("ContentClient", {
|
|
1585
|
-
publishableKey: options.publishableKey,
|
|
1586
|
-
apiUrl: options.apiUrl,
|
|
1587
|
-
onRequestId: options.onRequestId,
|
|
1588
|
-
requiresCredential: false
|
|
1589
|
-
});
|
|
1590
|
-
this.links = {
|
|
1591
|
-
list: (params) => api.get(linksListPath(params))
|
|
1592
|
-
};
|
|
1593
|
-
this.galleryItems = {
|
|
1594
|
-
list: (params) => api.get(
|
|
1595
|
-
galleryItemsListPath(params)
|
|
1596
|
-
)
|
|
1597
|
-
};
|
|
1598
|
-
}
|
|
1599
|
-
};
|
|
1600
3501
|
|
|
1601
3502
|
// src/core/customer/customer-auth.ts
|
|
1602
3503
|
var DEFAULT_TIMEOUT2 = 15e3;
|
|
@@ -1615,8 +3516,10 @@ var CustomerAuth = class {
|
|
|
1615
3516
|
const persist = options?.persist ?? true;
|
|
1616
3517
|
if (persist) {
|
|
1617
3518
|
const key = typeof persist === "string" ? persist : "customer-token";
|
|
3519
|
+
const refreshKey = `${key}:refresh`;
|
|
1618
3520
|
const isBrowser = typeof window !== "undefined";
|
|
1619
3521
|
this.token = isBrowser ? safeGetItem(key) : null;
|
|
3522
|
+
this.refreshTokenValue = isBrowser ? safeGetItem(refreshKey) : null;
|
|
1620
3523
|
this.onTokenChange = isBrowser ? (token) => {
|
|
1621
3524
|
try {
|
|
1622
3525
|
if (token) localStorage.setItem(key, token);
|
|
@@ -1624,9 +3527,18 @@ var CustomerAuth = class {
|
|
|
1624
3527
|
} catch {
|
|
1625
3528
|
}
|
|
1626
3529
|
} : void 0;
|
|
3530
|
+
this.onRefreshTokenChange = isBrowser ? (refreshToken) => {
|
|
3531
|
+
try {
|
|
3532
|
+
if (refreshToken) localStorage.setItem(refreshKey, refreshToken);
|
|
3533
|
+
else localStorage.removeItem(refreshKey);
|
|
3534
|
+
} catch {
|
|
3535
|
+
}
|
|
3536
|
+
} : void 0;
|
|
1627
3537
|
} else {
|
|
1628
3538
|
this.token = options?.token ?? null;
|
|
3539
|
+
this.refreshTokenValue = options?.refreshToken ?? null;
|
|
1629
3540
|
this.onTokenChange = options?.onTokenChange;
|
|
3541
|
+
this.onRefreshTokenChange = options?.onRefreshTokenChange;
|
|
1630
3542
|
}
|
|
1631
3543
|
}
|
|
1632
3544
|
/**
|
|
@@ -1650,13 +3562,17 @@ var CustomerAuth = class {
|
|
|
1650
3562
|
}
|
|
1651
3563
|
);
|
|
1652
3564
|
this.setToken(result.token);
|
|
3565
|
+
if (result.refreshToken) this.setRefreshToken(result.refreshToken);
|
|
1653
3566
|
return result;
|
|
1654
3567
|
}
|
|
1655
3568
|
/**
|
|
1656
|
-
* Refresh the current token.
|
|
3569
|
+
* Refresh the current token. Uses a refresh token when available, otherwise
|
|
3570
|
+
* falls back to the legacy bearer-token compatibility path.
|
|
1657
3571
|
*/
|
|
1658
3572
|
async refreshToken() {
|
|
1659
|
-
if (!this.token)
|
|
3573
|
+
if (!this.refreshTokenValue && !this.token) {
|
|
3574
|
+
throw new ApiError("Not authenticated", 401);
|
|
3575
|
+
}
|
|
1660
3576
|
if (this.refreshPromise) return this.refreshPromise;
|
|
1661
3577
|
this.refreshPromise = this._doRefreshToken();
|
|
1662
3578
|
try {
|
|
@@ -1666,14 +3582,19 @@ var CustomerAuth = class {
|
|
|
1666
3582
|
}
|
|
1667
3583
|
}
|
|
1668
3584
|
async _doRefreshToken() {
|
|
3585
|
+
const init = this.refreshTokenValue ? {
|
|
3586
|
+
method: "POST",
|
|
3587
|
+
body: JSON.stringify({ refreshToken: this.refreshTokenValue })
|
|
3588
|
+
} : {
|
|
3589
|
+
method: "POST",
|
|
3590
|
+
headers: { Authorization: `Bearer ${this.token}` }
|
|
3591
|
+
};
|
|
1669
3592
|
const result = await this.requestJson(
|
|
1670
3593
|
"/api/customers/refresh",
|
|
1671
|
-
|
|
1672
|
-
method: "POST",
|
|
1673
|
-
headers: { Authorization: `Bearer ${this.token}` }
|
|
1674
|
-
}
|
|
3594
|
+
init
|
|
1675
3595
|
);
|
|
1676
3596
|
this.setToken(result.token);
|
|
3597
|
+
if (result.refreshToken) this.setRefreshToken(result.refreshToken);
|
|
1677
3598
|
return result;
|
|
1678
3599
|
}
|
|
1679
3600
|
/**
|
|
@@ -1681,6 +3602,7 @@ var CustomerAuth = class {
|
|
|
1681
3602
|
*/
|
|
1682
3603
|
logout() {
|
|
1683
3604
|
this.setToken(null);
|
|
3605
|
+
this.setRefreshToken(null);
|
|
1684
3606
|
}
|
|
1685
3607
|
/**
|
|
1686
3608
|
* Get the current authenticated customer's profile
|
|
@@ -1756,25 +3678,28 @@ var CustomerAuth = class {
|
|
|
1756
3678
|
const params = new URLSearchParams();
|
|
1757
3679
|
if (options?.page) params.set("page", String(options.page));
|
|
1758
3680
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
1759
|
-
if (options?.
|
|
1760
|
-
params.set("
|
|
3681
|
+
if (options?.financialStatus) {
|
|
3682
|
+
params.set("financialStatus", options.financialStatus);
|
|
1761
3683
|
}
|
|
1762
|
-
if (options?.
|
|
1763
|
-
params.set("
|
|
3684
|
+
if (options?.fulfillmentStatus) {
|
|
3685
|
+
params.set("fulfillmentStatus", options.fulfillmentStatus);
|
|
1764
3686
|
}
|
|
1765
3687
|
if (options?.returnStatus) params.set("returnStatus", options.returnStatus);
|
|
3688
|
+
if (options?.confirmationStatus) {
|
|
3689
|
+
params.set("confirmationStatus", options.confirmationStatus);
|
|
3690
|
+
}
|
|
1766
3691
|
if (options?.primaryDisplayStatus) {
|
|
1767
3692
|
params.set("primaryDisplayStatus", options.primaryDisplayStatus);
|
|
1768
3693
|
}
|
|
1769
|
-
if (options?.returnDisplayStatus) {
|
|
1770
|
-
params.set("returnDisplayStatus", options.returnDisplayStatus);
|
|
1771
|
-
}
|
|
1772
|
-
if (options?.status) params.set("status", options.status);
|
|
1773
3694
|
const qs = params.toString();
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
3695
|
+
const result = await this.requestJson(
|
|
3696
|
+
`/api/customers/me/orders${qs ? `?${qs}` : ""}`,
|
|
3697
|
+
{
|
|
3698
|
+
method: "GET",
|
|
3699
|
+
headers: { Authorization: `Bearer ${this.token}` }
|
|
3700
|
+
}
|
|
3701
|
+
);
|
|
3702
|
+
return validatePublicOrderList(result);
|
|
1778
3703
|
}
|
|
1779
3704
|
/**
|
|
1780
3705
|
* Get the current token (or null if not authenticated)
|
|
@@ -1782,6 +3707,12 @@ var CustomerAuth = class {
|
|
|
1782
3707
|
getToken() {
|
|
1783
3708
|
return this.token;
|
|
1784
3709
|
}
|
|
3710
|
+
/**
|
|
3711
|
+
* Get the current refresh token (or null if unavailable)
|
|
3712
|
+
*/
|
|
3713
|
+
getRefreshToken() {
|
|
3714
|
+
return this.refreshTokenValue;
|
|
3715
|
+
}
|
|
1785
3716
|
/**
|
|
1786
3717
|
* Set the token manually (e.g. from SSR)
|
|
1787
3718
|
*/
|
|
@@ -1789,6 +3720,13 @@ var CustomerAuth = class {
|
|
|
1789
3720
|
this.token = token;
|
|
1790
3721
|
this.onTokenChange?.(token);
|
|
1791
3722
|
}
|
|
3723
|
+
/**
|
|
3724
|
+
* Set the refresh token manually (e.g. from SSR cookie)
|
|
3725
|
+
*/
|
|
3726
|
+
setRefreshToken(refreshToken) {
|
|
3727
|
+
this.refreshTokenValue = refreshToken;
|
|
3728
|
+
this.onRefreshTokenChange?.(refreshToken);
|
|
3729
|
+
}
|
|
1792
3730
|
/**
|
|
1793
3731
|
* Check if the customer is currently authenticated
|
|
1794
3732
|
*/
|
|
@@ -1817,91 +3755,362 @@ var CustomerAuth = class {
|
|
|
1817
3755
|
}
|
|
1818
3756
|
};
|
|
1819
3757
|
|
|
3758
|
+
// src/core/customer/customer-oauth.ts
|
|
3759
|
+
var DEFAULT_SCOPES = ["openid", "profile", "email"];
|
|
3760
|
+
var DEFAULT_TIMEOUT3 = 15e3;
|
|
3761
|
+
function issuerUrl(issuer, path) {
|
|
3762
|
+
const base = resolveApiUrl(issuer);
|
|
3763
|
+
return new URL(path, base.endsWith("/") ? base : `${base}/`).toString();
|
|
3764
|
+
}
|
|
3765
|
+
function randomBase64Url(bytes) {
|
|
3766
|
+
const buffer = new Uint8Array(bytes);
|
|
3767
|
+
crypto.getRandomValues(buffer);
|
|
3768
|
+
let binary = "";
|
|
3769
|
+
for (const value of buffer) {
|
|
3770
|
+
binary += String.fromCharCode(value);
|
|
3771
|
+
}
|
|
3772
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
3773
|
+
}
|
|
3774
|
+
async function sha256Base64Url(value) {
|
|
3775
|
+
const data = new TextEncoder().encode(value);
|
|
3776
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
3777
|
+
let binary = "";
|
|
3778
|
+
for (const byte of new Uint8Array(digest)) {
|
|
3779
|
+
binary += String.fromCharCode(byte);
|
|
3780
|
+
}
|
|
3781
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
3782
|
+
}
|
|
3783
|
+
function normalizeToken(body) {
|
|
3784
|
+
if (body.token_type !== "Bearer") {
|
|
3785
|
+
throw new Error("Unsupported customer OAuth token type");
|
|
3786
|
+
}
|
|
3787
|
+
return {
|
|
3788
|
+
accessToken: body.access_token,
|
|
3789
|
+
expiresAt: Date.now() + body.expires_in * 1e3,
|
|
3790
|
+
expiresIn: body.expires_in,
|
|
3791
|
+
...body.id_token ? { idToken: body.id_token } : {},
|
|
3792
|
+
refreshToken: body.refresh_token,
|
|
3793
|
+
...body.scope ? { scope: body.scope } : {},
|
|
3794
|
+
tokenType: "Bearer"
|
|
3795
|
+
};
|
|
3796
|
+
}
|
|
3797
|
+
var CustomerOAuth = class {
|
|
3798
|
+
constructor(config) {
|
|
3799
|
+
if (!config.clientId) throw new Error("customer OAuth clientId is required");
|
|
3800
|
+
if (!config.issuer) throw new Error("customer OAuth issuer is required");
|
|
3801
|
+
this.clientId = config.clientId;
|
|
3802
|
+
this.issuer = config.issuer;
|
|
3803
|
+
this.timeout = config.timeout ?? DEFAULT_TIMEOUT3;
|
|
3804
|
+
}
|
|
3805
|
+
async createAuthorizationUrl(input) {
|
|
3806
|
+
const codeVerifier = randomBase64Url(48);
|
|
3807
|
+
const codeChallenge = await sha256Base64Url(codeVerifier);
|
|
3808
|
+
const state = randomBase64Url(32);
|
|
3809
|
+
const nonce = randomBase64Url(32);
|
|
3810
|
+
const scopes = input.scopes ?? DEFAULT_SCOPES;
|
|
3811
|
+
const url = new URL(issuerUrl(this.issuer, "customer-oauth/authorize"));
|
|
3812
|
+
url.searchParams.set("response_type", "code");
|
|
3813
|
+
url.searchParams.set("client_id", this.clientId);
|
|
3814
|
+
url.searchParams.set("redirect_uri", input.redirectUri);
|
|
3815
|
+
url.searchParams.set("scope", scopes.join(" "));
|
|
3816
|
+
url.searchParams.set("state", state);
|
|
3817
|
+
url.searchParams.set("nonce", nonce);
|
|
3818
|
+
url.searchParams.set("code_challenge", codeChallenge);
|
|
3819
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
3820
|
+
return {
|
|
3821
|
+
authorizationUrl: url.toString(),
|
|
3822
|
+
codeChallenge,
|
|
3823
|
+
codeVerifier,
|
|
3824
|
+
nonce,
|
|
3825
|
+
returnTo: input.returnTo ?? null,
|
|
3826
|
+
state
|
|
3827
|
+
};
|
|
3828
|
+
}
|
|
3829
|
+
parseCallback(callbackUrl, options) {
|
|
3830
|
+
const url = new URL(callbackUrl);
|
|
3831
|
+
const error = url.searchParams.get("error");
|
|
3832
|
+
if (error) {
|
|
3833
|
+
throw new Error(
|
|
3834
|
+
url.searchParams.get("error_description") ?? `OAuth error: ${error}`
|
|
3835
|
+
);
|
|
3836
|
+
}
|
|
3837
|
+
const code = url.searchParams.get("code");
|
|
3838
|
+
const state = url.searchParams.get("state");
|
|
3839
|
+
if (!code || !state) throw new Error("OAuth callback is missing code/state");
|
|
3840
|
+
if (state !== options.expectedState) throw new Error("OAuth state mismatch");
|
|
3841
|
+
return { code, state };
|
|
3842
|
+
}
|
|
3843
|
+
async exchangeCode(input) {
|
|
3844
|
+
const body = new URLSearchParams({
|
|
3845
|
+
client_id: this.clientId,
|
|
3846
|
+
code: input.code,
|
|
3847
|
+
code_verifier: input.codeVerifier,
|
|
3848
|
+
grant_type: "authorization_code",
|
|
3849
|
+
redirect_uri: input.redirectUri
|
|
3850
|
+
});
|
|
3851
|
+
return this.tokenRequest(body);
|
|
3852
|
+
}
|
|
3853
|
+
async refresh(input) {
|
|
3854
|
+
const body = new URLSearchParams({
|
|
3855
|
+
client_id: this.clientId,
|
|
3856
|
+
grant_type: "refresh_token",
|
|
3857
|
+
refresh_token: input.refreshToken
|
|
3858
|
+
});
|
|
3859
|
+
return this.tokenRequest(body);
|
|
3860
|
+
}
|
|
3861
|
+
async logout(input) {
|
|
3862
|
+
const body = { client_id: this.clientId };
|
|
3863
|
+
if (input.refreshToken) body.refresh_token = input.refreshToken;
|
|
3864
|
+
if (input.postLogoutRedirectUri) {
|
|
3865
|
+
body.post_logout_redirect_uri = input.postLogoutRedirectUri;
|
|
3866
|
+
}
|
|
3867
|
+
const response = await httpFetch("/customer-oauth/logout", {
|
|
3868
|
+
apiUrl: this.issuer,
|
|
3869
|
+
method: "POST",
|
|
3870
|
+
body: JSON.stringify(body),
|
|
3871
|
+
headers: { "Content-Type": "application/json" },
|
|
3872
|
+
timeout: this.timeout,
|
|
3873
|
+
retry: { maxRetries: 0 }
|
|
3874
|
+
});
|
|
3875
|
+
return parseApiResponse(
|
|
3876
|
+
response,
|
|
3877
|
+
"/customer-oauth/logout"
|
|
3878
|
+
);
|
|
3879
|
+
}
|
|
3880
|
+
verifyIdToken() {
|
|
3881
|
+
throw new Error(
|
|
3882
|
+
"Customer OAuth ID token verification is not implemented; treat idToken as opaque."
|
|
3883
|
+
);
|
|
3884
|
+
}
|
|
3885
|
+
async tokenRequest(body) {
|
|
3886
|
+
const response = await httpFetch("/api/customer-oauth/token", {
|
|
3887
|
+
apiUrl: this.issuer,
|
|
3888
|
+
method: "POST",
|
|
3889
|
+
body,
|
|
3890
|
+
headers: {
|
|
3891
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
3892
|
+
},
|
|
3893
|
+
timeout: this.timeout,
|
|
3894
|
+
retry: { maxRetries: 0 }
|
|
3895
|
+
});
|
|
3896
|
+
return normalizeToken(
|
|
3897
|
+
await parseApiResponse(
|
|
3898
|
+
response,
|
|
3899
|
+
"/api/customer-oauth/token"
|
|
3900
|
+
)
|
|
3901
|
+
);
|
|
3902
|
+
}
|
|
3903
|
+
};
|
|
3904
|
+
|
|
1820
3905
|
// src/core/customer/customer-namespace.ts
|
|
1821
3906
|
var CustomerNamespace = class {
|
|
1822
3907
|
constructor(publishableKey, options, apiUrl) {
|
|
1823
3908
|
this.auth = new CustomerAuth(publishableKey, options, apiUrl);
|
|
3909
|
+
if (options?.oauth) {
|
|
3910
|
+
this.oauth = new CustomerOAuth(options.oauth);
|
|
3911
|
+
}
|
|
1824
3912
|
}
|
|
1825
3913
|
};
|
|
1826
3914
|
|
|
3915
|
+
// src/core/api/commerce-idempotency.ts
|
|
3916
|
+
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;
|
|
3917
|
+
var PREFIXED_BASE64URL_PATTERN = /^ik_[A-Za-z0-9_-]{22}$/;
|
|
3918
|
+
function isCommerceIdempotencyKey(value) {
|
|
3919
|
+
return typeof value === "string" && value.length <= 255 && (UUID_V4_PATTERN.test(value) || PREFIXED_BASE64URL_PATTERN.test(value));
|
|
3920
|
+
}
|
|
3921
|
+
function assertCommerceIdempotencyKey(value) {
|
|
3922
|
+
if (isCommerceIdempotencyKey(value)) return;
|
|
3923
|
+
throw createValidationError(
|
|
3924
|
+
"idempotencyKey must be a UUIDv4 or ik_-prefixed 128-bit base64url value.",
|
|
3925
|
+
{ field: "idempotencyKey" }
|
|
3926
|
+
);
|
|
3927
|
+
}
|
|
3928
|
+
function createCommerceIdempotencyKey() {
|
|
3929
|
+
return globalThis.crypto.randomUUID();
|
|
3930
|
+
}
|
|
3931
|
+
|
|
1827
3932
|
// src/core/api/cart-api.ts
|
|
3933
|
+
var MAX_CART_LINE_ADMISSIONS = 32;
|
|
1828
3934
|
var CartApi = class extends CustomerScopedApi {
|
|
1829
3935
|
constructor(options) {
|
|
1830
3936
|
super("CartApi", { ...options, requiresCredential: false });
|
|
3937
|
+
this.serverTransport = Boolean(options.secretKey);
|
|
1831
3938
|
}
|
|
1832
|
-
|
|
1833
|
-
return this.
|
|
3939
|
+
endpoint(key) {
|
|
3940
|
+
return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
|
|
1834
3941
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
3942
|
+
execute(endpoint2, body, idempotencyKey) {
|
|
3943
|
+
return this.requestEndpoint(endpoint2, body, {
|
|
3944
|
+
...idempotencyKey && {
|
|
3945
|
+
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
3946
|
+
}
|
|
3947
|
+
});
|
|
1841
3948
|
}
|
|
1842
|
-
|
|
1843
|
-
return this.execute("
|
|
3949
|
+
create(params = {}) {
|
|
3950
|
+
return this.execute(this.endpoint("create"), params).then(
|
|
3951
|
+
(value) => validateCreateCartResult(value)
|
|
3952
|
+
);
|
|
1844
3953
|
}
|
|
1845
|
-
|
|
1846
|
-
return this.execute(
|
|
1847
|
-
|
|
1848
|
-
"POST",
|
|
1849
|
-
params
|
|
3954
|
+
retrieve(params) {
|
|
3955
|
+
return this.execute(this.endpoint("retrieve"), params).then(
|
|
3956
|
+
(value) => validatePublicCart(value)
|
|
1850
3957
|
);
|
|
1851
3958
|
}
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
3959
|
+
mine(params = {}) {
|
|
3960
|
+
const endpoint2 = this.endpoint("mine");
|
|
3961
|
+
return this.execute(endpoint2, params).then(
|
|
3962
|
+
(value) => validateCartMineResult(value)
|
|
3963
|
+
);
|
|
3964
|
+
}
|
|
3965
|
+
merge(params) {
|
|
3966
|
+
const { idempotencyKey, ...body } = params;
|
|
3967
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3968
|
+
const endpoint2 = this.endpoint("merge");
|
|
3969
|
+
return this.execute(endpoint2, body, idempotencyKey).then(
|
|
3970
|
+
(value) => validateCartMergeResult(value)
|
|
1862
3971
|
);
|
|
1863
3972
|
}
|
|
1864
3973
|
addItem(params) {
|
|
1865
|
-
return this.
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
3974
|
+
return this.mutate(this.endpoint("addItem"), params);
|
|
3975
|
+
}
|
|
3976
|
+
mutate(endpoint2, params) {
|
|
3977
|
+
const { idempotencyKey, ...body } = params;
|
|
3978
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
3979
|
+
return this.execute(endpoint2, body, idempotencyKey).then(
|
|
3980
|
+
(value) => validateCartMutationResult(value)
|
|
1869
3981
|
);
|
|
1870
3982
|
}
|
|
1871
3983
|
updateItem(params) {
|
|
1872
|
-
return this.
|
|
1873
|
-
COMMERCE_ENDPOINTS.carts.updateItem,
|
|
1874
|
-
"POST",
|
|
1875
|
-
params
|
|
1876
|
-
);
|
|
3984
|
+
return this.mutate(this.endpoint("updateItem"), params);
|
|
1877
3985
|
}
|
|
1878
3986
|
removeItem(params) {
|
|
1879
|
-
return this.
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
3987
|
+
return this.mutate(this.endpoint("removeItem"), params);
|
|
3988
|
+
}
|
|
3989
|
+
clear(params) {
|
|
3990
|
+
return this.mutate(this.endpoint("clear"), params);
|
|
3991
|
+
}
|
|
3992
|
+
updateDiscountCodes(params) {
|
|
3993
|
+
return this.mutate(this.endpoint("updateDiscountCodes"), params);
|
|
3994
|
+
}
|
|
3995
|
+
updateAttributes(params) {
|
|
3996
|
+
return this.mutate(this.endpoint("updateAttributes"), params);
|
|
3997
|
+
}
|
|
3998
|
+
};
|
|
3999
|
+
|
|
4000
|
+
// src/core/api/checkout-api.ts
|
|
4001
|
+
var CheckoutApi = class extends CustomerScopedApi {
|
|
4002
|
+
constructor(options) {
|
|
4003
|
+
super("CheckoutApi", { ...options, requiresCredential: false });
|
|
4004
|
+
}
|
|
4005
|
+
post(endpoint2, body, idempotencyKey) {
|
|
4006
|
+
return this.requestEndpoint(endpoint2, body, {
|
|
4007
|
+
...idempotencyKey && {
|
|
4008
|
+
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4009
|
+
}
|
|
4010
|
+
});
|
|
4011
|
+
}
|
|
4012
|
+
async publicCheckout(result) {
|
|
4013
|
+
return validatePublicCheckout(await result);
|
|
4014
|
+
}
|
|
4015
|
+
async serverCheckout(result) {
|
|
4016
|
+
return validateServerCheckout(await result);
|
|
4017
|
+
}
|
|
4018
|
+
async createResult(result) {
|
|
4019
|
+
return validateCreateCheckoutResult(
|
|
4020
|
+
await result,
|
|
4021
|
+
false
|
|
1883
4022
|
);
|
|
1884
4023
|
}
|
|
1885
|
-
|
|
1886
|
-
return
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
params
|
|
4024
|
+
async createServerResult(result) {
|
|
4025
|
+
return validateCreateCheckoutResult(
|
|
4026
|
+
await result,
|
|
4027
|
+
true
|
|
1890
4028
|
);
|
|
1891
4029
|
}
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
4030
|
+
create(params) {
|
|
4031
|
+
const { idempotencyKey, ...body } = params;
|
|
4032
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4033
|
+
return this.createResult(
|
|
4034
|
+
this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
|
|
1897
4035
|
);
|
|
1898
4036
|
}
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
4037
|
+
createServer(params) {
|
|
4038
|
+
const { idempotencyKey, ...body } = params;
|
|
4039
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4040
|
+
return this.createServerResult(
|
|
4041
|
+
this.post(
|
|
4042
|
+
COMMERCE_ENDPOINTS.checkouts.server.create,
|
|
4043
|
+
body,
|
|
4044
|
+
idempotencyKey
|
|
4045
|
+
)
|
|
4046
|
+
);
|
|
4047
|
+
}
|
|
4048
|
+
retrieve(params) {
|
|
4049
|
+
return this.publicCheckout(
|
|
4050
|
+
this.post(COMMERCE_ENDPOINTS.checkouts.retrieve, params)
|
|
4051
|
+
);
|
|
4052
|
+
}
|
|
4053
|
+
retrieveServer(params) {
|
|
4054
|
+
return this.serverCheckout(
|
|
4055
|
+
this.post(COMMERCE_ENDPOINTS.checkouts.server.retrieve, params)
|
|
4056
|
+
);
|
|
4057
|
+
}
|
|
4058
|
+
async query(params = {}) {
|
|
4059
|
+
const result = await this.post(
|
|
4060
|
+
COMMERCE_ENDPOINTS.checkouts.server.query,
|
|
1903
4061
|
params
|
|
1904
4062
|
);
|
|
4063
|
+
return validateCheckoutQueryResult(result);
|
|
4064
|
+
}
|
|
4065
|
+
};
|
|
4066
|
+
|
|
4067
|
+
// src/core/api/payment-session-api.ts
|
|
4068
|
+
var PaymentSessionApi = class extends CustomerScopedApi {
|
|
4069
|
+
constructor(options) {
|
|
4070
|
+
super("PaymentSessionApi", { ...options, requiresCredential: false });
|
|
4071
|
+
this.serverTransport = Boolean(options.secretKey);
|
|
4072
|
+
}
|
|
4073
|
+
post(endpoint2, body, idempotencyKey) {
|
|
4074
|
+
return this.requestEndpoint(endpoint2, body, {
|
|
4075
|
+
...idempotencyKey && {
|
|
4076
|
+
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4077
|
+
}
|
|
4078
|
+
});
|
|
4079
|
+
}
|
|
4080
|
+
async paymentSession(result) {
|
|
4081
|
+
return validatePublicPaymentSession(await result);
|
|
4082
|
+
}
|
|
4083
|
+
create(params) {
|
|
4084
|
+
const { idempotencyKey, ...body } = params;
|
|
4085
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4086
|
+
return this.paymentSession(
|
|
4087
|
+
this.post(
|
|
4088
|
+
this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
|
|
4089
|
+
body,
|
|
4090
|
+
idempotencyKey
|
|
4091
|
+
)
|
|
4092
|
+
);
|
|
4093
|
+
}
|
|
4094
|
+
retrieve(params) {
|
|
4095
|
+
const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
4096
|
+
return this.paymentSession(this.post(endpoint2, params));
|
|
4097
|
+
}
|
|
4098
|
+
cancel(params) {
|
|
4099
|
+
const { idempotencyKey, ...body } = params;
|
|
4100
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4101
|
+
const endpoint2 = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4102
|
+
return this.paymentSession(this.post(endpoint2, body, idempotencyKey));
|
|
4103
|
+
}
|
|
4104
|
+
confirm(params) {
|
|
4105
|
+
const { idempotencyKey, ...body } = params;
|
|
4106
|
+
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4107
|
+
return this.paymentSession(
|
|
4108
|
+
this.post(
|
|
4109
|
+
COMMERCE_ENDPOINTS.paymentSessions.server.confirm,
|
|
4110
|
+
body,
|
|
4111
|
+
idempotencyKey
|
|
4112
|
+
)
|
|
4113
|
+
);
|
|
1905
4114
|
}
|
|
1906
4115
|
};
|
|
1907
4116
|
|
|
@@ -2904,9 +5113,13 @@ function resolveVariantIdForCompleteSelection(matrix, selectedByOptionId) {
|
|
|
2904
5113
|
return getExactSelectedVariantEntry(matrix, normalized, matchingVariantEntries)?.id ?? null;
|
|
2905
5114
|
}
|
|
2906
5115
|
function buildSelectionPrice(variants) {
|
|
2907
|
-
const { min, max } = getMinMax(
|
|
5116
|
+
const { min, max } = getMinMax(
|
|
5117
|
+
variants.map((variant) => variant.resolvedPrice?.amount ?? variant.price)
|
|
5118
|
+
);
|
|
2908
5119
|
const { min: compareAtMin, max: compareAtMax } = getMinMax(
|
|
2909
|
-
variants.map(
|
|
5120
|
+
variants.map(
|
|
5121
|
+
(variant) => variant.resolvedPrice?.compareAtPrice ?? variant.compareAtPrice
|
|
5122
|
+
)
|
|
2910
5123
|
);
|
|
2911
5124
|
return {
|
|
2912
5125
|
min,
|
|
@@ -2966,8 +5179,8 @@ function buildSelectionStock(selectedVariant, matchingVariants) {
|
|
|
2966
5179
|
return {
|
|
2967
5180
|
availableForSale: getVariantAvailableForSale(selectedVariant),
|
|
2968
5181
|
isUnlimited: selectedVariant.isUnlimited,
|
|
2969
|
-
stock: selectedVariant.stock,
|
|
2970
|
-
reservedStock: selectedVariant.reservedStock,
|
|
5182
|
+
stock: "stock" in selectedVariant ? selectedVariant.stock : null,
|
|
5183
|
+
reservedStock: "reservedStock" in selectedVariant ? selectedVariant.reservedStock : null,
|
|
2971
5184
|
availableStock
|
|
2972
5185
|
};
|
|
2973
5186
|
}
|
|
@@ -3349,6 +5562,9 @@ function compareVariantOrder(a, b) {
|
|
|
3349
5562
|
}
|
|
3350
5563
|
function getVariantAvailableForSale(variant) {
|
|
3351
5564
|
if (variant.isActive === false) return false;
|
|
5565
|
+
if (typeof variant.availableForSale === "boolean") {
|
|
5566
|
+
return variant.availableForSale;
|
|
5567
|
+
}
|
|
3352
5568
|
if (variant.isUnlimited) return true;
|
|
3353
5569
|
if (variant.inventoryPolicy === "continue") return true;
|
|
3354
5570
|
return (variant.stock ?? 0) - (variant.reservedStock ?? 0) > 0;
|
|
@@ -3462,7 +5678,7 @@ function buildProductListingCard(item, options = {}) {
|
|
|
3462
5678
|
{ listing: { selectionHintVariant } },
|
|
3463
5679
|
options
|
|
3464
5680
|
),
|
|
3465
|
-
title: product.title,
|
|
5681
|
+
title: product.title ?? "",
|
|
3466
5682
|
representativeVariant,
|
|
3467
5683
|
primaryImage: listingPrimaryMedia,
|
|
3468
5684
|
priceRange,
|
|
@@ -3649,6 +5865,11 @@ function productDetailResultFromError(error) {
|
|
|
3649
5865
|
if (!reason) return void 0;
|
|
3650
5866
|
return { found: false, reason };
|
|
3651
5867
|
}
|
|
5868
|
+
var MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE = "Market listing pages do not support base price filters or price sorts.";
|
|
5869
|
+
var BASE_PRICE_RANGE_SORT_FIELDS = /* @__PURE__ */ new Set([
|
|
5870
|
+
"priceRange.minVariantPrice.amount",
|
|
5871
|
+
"priceRange.maxVariantPrice.amount"
|
|
5872
|
+
]);
|
|
3652
5873
|
function nonEmpty(values) {
|
|
3653
5874
|
return values?.length ? values : void 0;
|
|
3654
5875
|
}
|
|
@@ -3696,14 +5917,34 @@ function buildProductListingPageWhere(params) {
|
|
|
3696
5917
|
if (clauses.length === 1) return clauses[0];
|
|
3697
5918
|
return { and: clauses };
|
|
3698
5919
|
}
|
|
3699
|
-
function
|
|
5920
|
+
function productListingPageUsesBasePriceSort(sort) {
|
|
5921
|
+
const values = Array.isArray(sort) ? sort : sort ? [sort] : [];
|
|
5922
|
+
return values.some(
|
|
5923
|
+
(value) => BASE_PRICE_RANGE_SORT_FIELDS.has(String(value).replace(/^-/, ""))
|
|
5924
|
+
);
|
|
5925
|
+
}
|
|
5926
|
+
function assertMarketListingPageQuerySupported(params) {
|
|
5927
|
+
if (!params.market?.trim()) return;
|
|
5928
|
+
const priceFilter = params.filters?.price;
|
|
5929
|
+
if (priceFilter?.min != null || priceFilter?.max != null || productListingPageUsesBasePriceSort(params.sort)) {
|
|
5930
|
+
throw new TypeError(MARKET_PRICE_QUERY_UNSUPPORTED_MESSAGE);
|
|
5931
|
+
}
|
|
5932
|
+
}
|
|
5933
|
+
function buildProductListingPageRequest(params) {
|
|
5934
|
+
assertMarketListingPageQuerySupported(params);
|
|
3700
5935
|
const options = {
|
|
5936
|
+
market: params.market,
|
|
5937
|
+
locale: params.locale,
|
|
5938
|
+
fallbackLocale: params.fallbackLocale,
|
|
3701
5939
|
page: params.page,
|
|
3702
5940
|
limit: params.limit,
|
|
3703
5941
|
sort: params.sort,
|
|
3704
5942
|
where: buildProductListingPageWhere(params)
|
|
3705
5943
|
};
|
|
3706
|
-
return
|
|
5944
|
+
return {
|
|
5945
|
+
operation: params.mode === "full" ? COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet : COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog,
|
|
5946
|
+
query: listingPageSearchParams(options)
|
|
5947
|
+
};
|
|
3707
5948
|
}
|
|
3708
5949
|
function withProductListingCards(response, options) {
|
|
3709
5950
|
return {
|
|
@@ -3720,30 +5961,15 @@ function isProductUpsertFieldValidationErrorBody(value) {
|
|
|
3720
5961
|
return typeof body.error === "string" && typeof body.field === "string" && (reason === PRODUCT_UPSERT_UNKNOWN_FIELD_REASON || reason === PRODUCT_UPSERT_READONLY_FIELD_REASON);
|
|
3721
5962
|
}
|
|
3722
5963
|
|
|
3723
|
-
// src/core/api/order-api.ts
|
|
3724
|
-
function idempotencyRequestOptions(idempotencyKey) {
|
|
3725
|
-
return idempotencyKey ? { headers: { "X-Idempotency-Key": idempotencyKey } } : void 0;
|
|
3726
|
-
}
|
|
3727
|
-
function splitIdempotencyKey(params) {
|
|
3728
|
-
const { idempotencyKey, ...body } = params;
|
|
3729
|
-
return { body, idempotencyKey };
|
|
3730
|
-
}
|
|
3731
|
-
|
|
3732
5964
|
// src/core/commerce/commerce-client.ts
|
|
3733
5965
|
var BrowserCommerceApi = class extends CustomerScopedApi {
|
|
3734
|
-
|
|
3735
|
-
return
|
|
3736
|
-
method: "POST",
|
|
3737
|
-
body,
|
|
3738
|
-
headers: requestOptions?.headers
|
|
3739
|
-
});
|
|
3740
|
-
}
|
|
3741
|
-
get(endpoint) {
|
|
3742
|
-
return this.request(endpoint, { method: "GET" });
|
|
5966
|
+
requestEndpoint(endpoint2, body, options) {
|
|
5967
|
+
return super.requestEndpoint(endpoint2, body, options);
|
|
3743
5968
|
}
|
|
3744
5969
|
};
|
|
3745
5970
|
var CommerceClient = class {
|
|
3746
5971
|
constructor(options) {
|
|
5972
|
+
this.market = options.market;
|
|
3747
5973
|
const cartApi = new CartApi({
|
|
3748
5974
|
publishableKey: options.publishableKey,
|
|
3749
5975
|
apiUrl: options.apiUrl,
|
|
@@ -3751,6 +5977,20 @@ var CommerceClient = class {
|
|
|
3751
5977
|
onUnauthorized: options.onUnauthorized,
|
|
3752
5978
|
onRequestId: options.onRequestId
|
|
3753
5979
|
});
|
|
5980
|
+
const checkoutApi = new CheckoutApi({
|
|
5981
|
+
publishableKey: options.publishableKey,
|
|
5982
|
+
apiUrl: options.apiUrl,
|
|
5983
|
+
customerToken: options.customerToken,
|
|
5984
|
+
onUnauthorized: options.onUnauthorized,
|
|
5985
|
+
onRequestId: options.onRequestId
|
|
5986
|
+
});
|
|
5987
|
+
const paymentSessionApi = new PaymentSessionApi({
|
|
5988
|
+
publishableKey: options.publishableKey,
|
|
5989
|
+
apiUrl: options.apiUrl,
|
|
5990
|
+
customerToken: options.customerToken,
|
|
5991
|
+
onUnauthorized: options.onUnauthorized,
|
|
5992
|
+
onRequestId: options.onRequestId
|
|
5993
|
+
});
|
|
3754
5994
|
const api = new BrowserCommerceApi("CommerceClient", {
|
|
3755
5995
|
publishableKey: options.publishableKey,
|
|
3756
5996
|
apiUrl: options.apiUrl,
|
|
@@ -3759,29 +5999,42 @@ var CommerceClient = class {
|
|
|
3759
5999
|
onRequestId: options.onRequestId
|
|
3760
6000
|
});
|
|
3761
6001
|
this.product = {
|
|
3762
|
-
stockCheck: (params) => api.
|
|
3763
|
-
|
|
6002
|
+
stockCheck: (params) => api.requestEndpoint(
|
|
6003
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck,
|
|
3764
6004
|
params
|
|
3765
6005
|
),
|
|
3766
|
-
stockSnapshot: (params) => api.
|
|
3767
|
-
|
|
3768
|
-
|
|
6006
|
+
stockSnapshot: (params) => api.requestEndpoint(
|
|
6007
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot,
|
|
6008
|
+
void 0,
|
|
6009
|
+
{ query: stockSnapshotSearchParams(params) }
|
|
6010
|
+
),
|
|
6011
|
+
listingGroups: (params) => api.requestEndpoint(
|
|
6012
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
|
|
6013
|
+
void 0,
|
|
6014
|
+
{ query: listingGroupsSearchParams(this.withMarket(params)) }
|
|
3769
6015
|
),
|
|
3770
|
-
listingGroupsCatalog: (params) => api.
|
|
3771
|
-
|
|
6016
|
+
listingGroupsCatalog: (params) => api.requestEndpoint(
|
|
6017
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog,
|
|
6018
|
+
void 0,
|
|
6019
|
+
{ query: listingGroupsSearchParams(this.withMarket(params)) }
|
|
3772
6020
|
),
|
|
3773
6021
|
listingPage: async (params = {}) => {
|
|
3774
6022
|
const catalogParams = {
|
|
3775
6023
|
...params,
|
|
3776
6024
|
mode: "catalog"
|
|
3777
6025
|
};
|
|
3778
|
-
const
|
|
3779
|
-
|
|
6026
|
+
const request = buildProductListingPageRequest(
|
|
6027
|
+
this.withMarket(catalogParams)
|
|
6028
|
+
);
|
|
6029
|
+
const response = await api.requestEndpoint(request.operation, void 0, { query: request.query });
|
|
6030
|
+
return withProductListingCards(response, this.withMarket(catalogParams));
|
|
3780
6031
|
},
|
|
3781
6032
|
detail: async (params) => {
|
|
3782
6033
|
try {
|
|
3783
|
-
const product = await api.
|
|
3784
|
-
|
|
6034
|
+
const product = await api.requestEndpoint(
|
|
6035
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
|
|
6036
|
+
void 0,
|
|
6037
|
+
{ query: productDetailSearchParams(this.withMarket(params)) }
|
|
3785
6038
|
);
|
|
3786
6039
|
return { found: true, product };
|
|
3787
6040
|
} catch (err) {
|
|
@@ -3792,8 +6045,10 @@ var CommerceClient = class {
|
|
|
3792
6045
|
},
|
|
3793
6046
|
detailCatalog: async (params) => {
|
|
3794
6047
|
try {
|
|
3795
|
-
const product = await api.
|
|
3796
|
-
|
|
6048
|
+
const product = await api.requestEndpoint(
|
|
6049
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog,
|
|
6050
|
+
void 0,
|
|
6051
|
+
{ query: productDetailSearchParams(this.withMarket(params)) }
|
|
3797
6052
|
);
|
|
3798
6053
|
return { found: true, product };
|
|
3799
6054
|
} catch (err) {
|
|
@@ -3803,39 +6058,51 @@ var CommerceClient = class {
|
|
|
3803
6058
|
}
|
|
3804
6059
|
}
|
|
3805
6060
|
};
|
|
3806
|
-
this.
|
|
3807
|
-
create: cartApi.
|
|
3808
|
-
|
|
6061
|
+
this.carts = {
|
|
6062
|
+
create: (params) => cartApi.create(this.withMarket(params ?? {})),
|
|
6063
|
+
retrieve: cartApi.retrieve.bind(cartApi),
|
|
3809
6064
|
addItem: cartApi.addItem.bind(cartApi),
|
|
3810
6065
|
updateItem: cartApi.updateItem.bind(cartApi),
|
|
3811
6066
|
removeItem: cartApi.removeItem.bind(cartApi),
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
clear: cartApi.
|
|
6067
|
+
updateDiscountCodes: cartApi.updateDiscountCodes.bind(cartApi),
|
|
6068
|
+
updateAttributes: cartApi.updateAttributes.bind(cartApi),
|
|
6069
|
+
clear: cartApi.clear.bind(cartApi),
|
|
3815
6070
|
merge: cartApi.merge.bind(cartApi),
|
|
3816
6071
|
mine: cartApi.mine.bind(cartApi)
|
|
3817
6072
|
};
|
|
3818
6073
|
this.orders = {
|
|
3819
|
-
checkout: (params) => {
|
|
3820
|
-
const { body, idempotencyKey } = splitIdempotencyKey(params);
|
|
3821
|
-
return api.post(
|
|
3822
|
-
"/api/orders/checkout",
|
|
3823
|
-
body,
|
|
3824
|
-
idempotencyRequestOptions(idempotencyKey)
|
|
3825
|
-
);
|
|
3826
|
-
},
|
|
3827
6074
|
listMine: (params) => options.customerAuth.getMyOrders(params)
|
|
3828
6075
|
};
|
|
6076
|
+
this.checkouts = {
|
|
6077
|
+
create: checkoutApi.create.bind(checkoutApi),
|
|
6078
|
+
retrieve: checkoutApi.retrieve.bind(checkoutApi)
|
|
6079
|
+
};
|
|
6080
|
+
this.paymentSessions = {
|
|
6081
|
+
create: paymentSessionApi.create.bind(paymentSessionApi),
|
|
6082
|
+
retrieve: (params) => paymentSessionApi.retrieve(params),
|
|
6083
|
+
cancel: (params) => paymentSessionApi.cancel(params)
|
|
6084
|
+
};
|
|
3829
6085
|
this.discounts = {
|
|
3830
|
-
validate: (params) => api.
|
|
6086
|
+
validate: (params) => api.requestEndpoint(
|
|
6087
|
+
COMMERCE_ENDPOINT_OPERATIONS.discounts.validate,
|
|
6088
|
+
params
|
|
6089
|
+
)
|
|
3831
6090
|
};
|
|
3832
6091
|
this.shipping = {
|
|
3833
|
-
calculate: (params) => api.
|
|
3834
|
-
|
|
6092
|
+
calculate: (params) => api.requestEndpoint(
|
|
6093
|
+
COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate,
|
|
3835
6094
|
params
|
|
3836
6095
|
)
|
|
3837
6096
|
};
|
|
3838
6097
|
}
|
|
6098
|
+
getDefaultMarket() {
|
|
6099
|
+
return this.market;
|
|
6100
|
+
}
|
|
6101
|
+
withMarket(params) {
|
|
6102
|
+
const defaultMarket = this.market?.trim();
|
|
6103
|
+
if (!defaultMarket || params.market?.trim()) return params;
|
|
6104
|
+
return { ...params, market: defaultMarket };
|
|
6105
|
+
}
|
|
3839
6106
|
};
|
|
3840
6107
|
|
|
3841
6108
|
// src/core/events/events-client.ts
|
|
@@ -3855,7 +6122,17 @@ var EventsClient = class {
|
|
|
3855
6122
|
getRange(params) {
|
|
3856
6123
|
return this.execute(
|
|
3857
6124
|
buildRangeEndpoint(params),
|
|
3858
|
-
|
|
6125
|
+
resolveOperationMethod(EVENTS_ENDPOINT_OPERATIONS.occurrences.range),
|
|
6126
|
+
void 0,
|
|
6127
|
+
{ useCustomerAuth: false }
|
|
6128
|
+
);
|
|
6129
|
+
}
|
|
6130
|
+
getAdmissionAvailability(params) {
|
|
6131
|
+
return this.execute(
|
|
6132
|
+
buildAdmissionAvailabilityEndpoint(params),
|
|
6133
|
+
resolveOperationMethod(
|
|
6134
|
+
EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability
|
|
6135
|
+
),
|
|
3859
6136
|
void 0,
|
|
3860
6137
|
{ useCustomerAuth: false }
|
|
3861
6138
|
);
|
|
@@ -3884,11 +6161,11 @@ var EventsClient = class {
|
|
|
3884
6161
|
{ useCustomerAuth: false }
|
|
3885
6162
|
);
|
|
3886
6163
|
}
|
|
3887
|
-
async execute(
|
|
6164
|
+
async execute(endpoint2, method, body, options = {}) {
|
|
3888
6165
|
const useCustomerAuth = options.useCustomerAuth === true;
|
|
3889
6166
|
const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
|
|
3890
6167
|
try {
|
|
3891
|
-
const response = await httpFetch(
|
|
6168
|
+
const response = await httpFetch(endpoint2, {
|
|
3892
6169
|
method,
|
|
3893
6170
|
apiUrl: this.apiUrl,
|
|
3894
6171
|
publishableKey: this.publishableKey,
|
|
@@ -3897,7 +6174,7 @@ var EventsClient = class {
|
|
|
3897
6174
|
...body !== void 0 && { body: JSON.stringify(body) }
|
|
3898
6175
|
});
|
|
3899
6176
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
3900
|
-
return parseApiResponse(response,
|
|
6177
|
+
return parseApiResponse(response, endpoint2);
|
|
3901
6178
|
} catch (err) {
|
|
3902
6179
|
const id = err instanceof SDKError ? err.requestId ?? null : null;
|
|
3903
6180
|
this.onRequestId?.(id);
|
|
@@ -3936,7 +6213,17 @@ function buildRangeEndpoint(params) {
|
|
|
3936
6213
|
appendValues(urlParams, "categorySlug", params.categorySlug);
|
|
3937
6214
|
appendValues(urlParams, "tag", params.tag);
|
|
3938
6215
|
appendValues(urlParams, "tagSlug", params.tagSlug);
|
|
3939
|
-
return
|
|
6216
|
+
return resolveOperationPath(EVENTS_ENDPOINT_OPERATIONS.occurrences.range, {
|
|
6217
|
+
query: urlParams
|
|
6218
|
+
});
|
|
6219
|
+
}
|
|
6220
|
+
function buildAdmissionAvailabilityEndpoint(params) {
|
|
6221
|
+
const urlParams = new URLSearchParams();
|
|
6222
|
+
urlParams.set("occurrence", params.occurrence);
|
|
6223
|
+
return resolveOperationPath(
|
|
6224
|
+
EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
|
|
6225
|
+
{ query: urlParams }
|
|
6226
|
+
);
|
|
3940
6227
|
}
|
|
3941
6228
|
function formatDateParam(value) {
|
|
3942
6229
|
return value instanceof Date ? value.toISOString() : value;
|
|
@@ -3949,15 +6236,62 @@ function appendValues(params, key, value) {
|
|
|
3949
6236
|
}
|
|
3950
6237
|
}
|
|
3951
6238
|
|
|
6239
|
+
// src/core/market/market-discovery.ts
|
|
6240
|
+
function toMarketDTO(row) {
|
|
6241
|
+
return {
|
|
6242
|
+
id: row.id,
|
|
6243
|
+
handle: row.handle,
|
|
6244
|
+
name: row.name,
|
|
6245
|
+
countryCode: row.countryCode,
|
|
6246
|
+
targetCountries: (row.targetCountries ?? []).map((c) => c.countryCode),
|
|
6247
|
+
currency: row.currency,
|
|
6248
|
+
isPrimary: row.isPrimary === true,
|
|
6249
|
+
isActive: row.isActive === true
|
|
6250
|
+
};
|
|
6251
|
+
}
|
|
6252
|
+
var MarketDiscovery = class {
|
|
6253
|
+
constructor(read) {
|
|
6254
|
+
this.read = read;
|
|
6255
|
+
}
|
|
6256
|
+
async list() {
|
|
6257
|
+
const res = await this.read({
|
|
6258
|
+
where: { isActive: { equals: true } },
|
|
6259
|
+
limit: 100
|
|
6260
|
+
});
|
|
6261
|
+
if (res.hasNextPage) {
|
|
6262
|
+
console.warn(
|
|
6263
|
+
"[markets.list] more than 100 active markets; results truncated to 100."
|
|
6264
|
+
);
|
|
6265
|
+
}
|
|
6266
|
+
return res.docs.map(toMarketDTO);
|
|
6267
|
+
}
|
|
6268
|
+
async default() {
|
|
6269
|
+
const res = await this.read({
|
|
6270
|
+
where: { isPrimary: { equals: true }, isActive: { equals: true } },
|
|
6271
|
+
limit: 1
|
|
6272
|
+
});
|
|
6273
|
+
const row = res.docs[0];
|
|
6274
|
+
return row ? toMarketDTO(row) : null;
|
|
6275
|
+
}
|
|
6276
|
+
};
|
|
6277
|
+
|
|
3952
6278
|
// src/core/client/client.ts
|
|
3953
6279
|
var BrowserMembershipApi = class extends CustomerScopedApi {
|
|
3954
6280
|
me() {
|
|
3955
|
-
return this.
|
|
3956
|
-
|
|
3957
|
-
|
|
6281
|
+
return this.requestEndpoint(
|
|
6282
|
+
MEMBERSHIP_ENDPOINT_OPERATIONS.me
|
|
6283
|
+
);
|
|
6284
|
+
}
|
|
6285
|
+
cancel(params) {
|
|
6286
|
+
const { id, immediate } = params;
|
|
6287
|
+
return this.requestEndpoint(
|
|
6288
|
+
MEMBERSHIP_ENDPOINT_OPERATIONS.cancel,
|
|
6289
|
+
immediate !== void 0 ? { immediate } : {},
|
|
6290
|
+
{ pathParams: { id } }
|
|
6291
|
+
);
|
|
3958
6292
|
}
|
|
3959
6293
|
};
|
|
3960
|
-
var Client = class {
|
|
6294
|
+
var Client = class _Client {
|
|
3961
6295
|
constructor(options) {
|
|
3962
6296
|
this.lastRequestId = null;
|
|
3963
6297
|
const publishableKey = options.publishableKey;
|
|
@@ -3989,6 +6323,7 @@ var Client = class {
|
|
|
3989
6323
|
this.commerce = new CommerceClient({
|
|
3990
6324
|
publishableKey: this.config.publishableKey,
|
|
3991
6325
|
apiUrl: this.config.apiUrl,
|
|
6326
|
+
market: this.config.market,
|
|
3992
6327
|
customerToken: () => this.customer.auth.getToken(),
|
|
3993
6328
|
onUnauthorized,
|
|
3994
6329
|
onRequestId,
|
|
@@ -4021,6 +6356,9 @@ var Client = class {
|
|
|
4021
6356
|
onRequestId,
|
|
4022
6357
|
this.config.apiUrl
|
|
4023
6358
|
);
|
|
6359
|
+
this.markets = new MarketDiscovery(
|
|
6360
|
+
(options2) => this.collections.from("markets").find(options2)
|
|
6361
|
+
);
|
|
4024
6362
|
const membershipApi = new BrowserMembershipApi("MembershipApi", {
|
|
4025
6363
|
publishableKey: this.config.publishableKey,
|
|
4026
6364
|
apiUrl: this.config.apiUrl,
|
|
@@ -4029,12 +6367,23 @@ var Client = class {
|
|
|
4029
6367
|
onRequestId
|
|
4030
6368
|
});
|
|
4031
6369
|
this.memberships = {
|
|
4032
|
-
me: membershipApi.me.bind(membershipApi)
|
|
6370
|
+
me: membershipApi.me.bind(membershipApi),
|
|
6371
|
+
cancel: membershipApi.cancel.bind(membershipApi)
|
|
4033
6372
|
};
|
|
4034
6373
|
}
|
|
4035
6374
|
getState() {
|
|
4036
6375
|
return { ...this.state };
|
|
4037
6376
|
}
|
|
6377
|
+
withMarket(market) {
|
|
6378
|
+
return new _Client({
|
|
6379
|
+
...this.config,
|
|
6380
|
+
customer: this.config.customer?.persist === false ? {
|
|
6381
|
+
...this.config.customer,
|
|
6382
|
+
token: this.customer.auth.getToken() ?? void 0
|
|
6383
|
+
} : this.config.customer,
|
|
6384
|
+
market
|
|
6385
|
+
});
|
|
6386
|
+
}
|
|
4038
6387
|
getConfig() {
|
|
4039
6388
|
return { ...this.config };
|
|
4040
6389
|
}
|
|
@@ -4100,6 +6449,7 @@ var COMMERCE_NOTIFICATION_EVENTS = [
|
|
|
4100
6449
|
"returnRequested",
|
|
4101
6450
|
"returnApproved",
|
|
4102
6451
|
"returnRejected",
|
|
6452
|
+
"returnCanceled",
|
|
4103
6453
|
"returnCompleted"
|
|
4104
6454
|
];
|
|
4105
6455
|
function isStringOrNumber(value) {
|
|
@@ -4188,7 +6538,7 @@ function isCommerceNotificationWebhookEvent(event) {
|
|
|
4188
6538
|
if (notification.event === "fulfillmentShipped") {
|
|
4189
6539
|
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);
|
|
4190
6540
|
}
|
|
4191
|
-
if (notification.event === "returnRequested" || notification.event === "returnApproved" || notification.event === "returnRejected" || notification.event === "returnCompleted") {
|
|
6541
|
+
if (notification.event === "returnRequested" || notification.event === "returnApproved" || notification.event === "returnRejected" || notification.event === "returnCanceled" || notification.event === "returnCompleted") {
|
|
4192
6542
|
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);
|
|
4193
6543
|
}
|
|
4194
6544
|
return false;
|
|
@@ -4222,8 +6572,8 @@ function createCommerceEmailWebhookHandler(handlers) {
|
|
|
4222
6572
|
function isWebhookCollection(event, collection) {
|
|
4223
6573
|
return isValidWebhookEvent(event) && event.collection === collection;
|
|
4224
6574
|
}
|
|
4225
|
-
function isWebhookOperation(event,
|
|
4226
|
-
return isValidWebhookEvent(event) && event.operation ===
|
|
6575
|
+
function isWebhookOperation(event, operation2) {
|
|
6576
|
+
return isValidWebhookEvent(event) && event.operation === operation2;
|
|
4227
6577
|
}
|
|
4228
6578
|
var CUSTOMER_PASSWORD_RESET_OPERATION = "password-reset";
|
|
4229
6579
|
function isRecord2(value) {
|
|
@@ -4250,7 +6600,7 @@ function createCustomerAuthWebhookHandler(handlers) {
|
|
|
4250
6600
|
await handlers.unhandled?.(event);
|
|
4251
6601
|
};
|
|
4252
6602
|
}
|
|
4253
|
-
async function verifySignature(payload, secret, signature,
|
|
6603
|
+
async function verifySignature(payload, secret, signature, timestamp2, deliveryId) {
|
|
4254
6604
|
const encoder = new TextEncoder();
|
|
4255
6605
|
const key = await crypto.subtle.importKey(
|
|
4256
6606
|
"raw",
|
|
@@ -4269,12 +6619,12 @@ async function verifySignature(payload, secret, signature, timestamp, deliveryId
|
|
|
4269
6619
|
"HMAC",
|
|
4270
6620
|
key,
|
|
4271
6621
|
sigBytes,
|
|
4272
|
-
encoder.encode(`${
|
|
6622
|
+
encoder.encode(`${timestamp2}.${deliveryId}.${payload}`)
|
|
4273
6623
|
);
|
|
4274
6624
|
}
|
|
4275
|
-
function timestampIsFresh(
|
|
4276
|
-
if (!/^\d+$/.test(
|
|
4277
|
-
const timestampMs = Number(
|
|
6625
|
+
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6626
|
+
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6627
|
+
const timestampMs = Number(timestamp2);
|
|
4278
6628
|
if (!Number.isFinite(timestampMs)) return false;
|
|
4279
6629
|
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
4280
6630
|
return skewMs <= toleranceSeconds * 1e3;
|
|
@@ -4284,14 +6634,14 @@ async function handleWebhook(request, handler, options) {
|
|
|
4284
6634
|
const rawBody = await request.text();
|
|
4285
6635
|
if (options?.secret) {
|
|
4286
6636
|
const signature = request.headers.get("x-webhook-signature") || "";
|
|
4287
|
-
const
|
|
6637
|
+
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
4288
6638
|
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
4289
6639
|
const toleranceSeconds = options.toleranceSeconds ?? 300;
|
|
4290
|
-
const valid = Boolean(
|
|
6640
|
+
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(
|
|
4291
6641
|
rawBody,
|
|
4292
6642
|
options.secret,
|
|
4293
6643
|
signature,
|
|
4294
|
-
|
|
6644
|
+
timestamp2,
|
|
4295
6645
|
deliveryId
|
|
4296
6646
|
);
|
|
4297
6647
|
if (!valid) {
|
|
@@ -4355,12 +6705,21 @@ var INTERNAL_COLLECTIONS = [
|
|
|
4355
6705
|
"analytics-event-schemas",
|
|
4356
6706
|
"subscriptions",
|
|
4357
6707
|
"billing-history",
|
|
6708
|
+
"usage-rate-cards",
|
|
6709
|
+
"usage-invoices",
|
|
4358
6710
|
"inventory-reservations",
|
|
4359
6711
|
"inventory-adjustments",
|
|
6712
|
+
"payment-sessions",
|
|
6713
|
+
"payment-event-inbox",
|
|
6714
|
+
"payment-refund-attempts",
|
|
6715
|
+
"portone-payment-interactions",
|
|
4360
6716
|
"commerce-notification-intents",
|
|
6717
|
+
"commerce-idempotency-records",
|
|
4361
6718
|
"product-collection-items",
|
|
4362
6719
|
"order-status-logs",
|
|
6720
|
+
"fulfillment-events",
|
|
4363
6721
|
"tenant-commerce-config",
|
|
6722
|
+
"customer-oauth-clients",
|
|
4364
6723
|
"api-keys",
|
|
4365
6724
|
"personal-access-tokens",
|
|
4366
6725
|
"tenant-entitlements",
|
|
@@ -4368,12 +6727,18 @@ var INTERNAL_COLLECTIONS = [
|
|
|
4368
6727
|
"direct-upload-sessions",
|
|
4369
6728
|
"webhook-events",
|
|
4370
6729
|
"webhook-deliveries",
|
|
6730
|
+
"webhook-outbox-deliveries",
|
|
4371
6731
|
"audit-logs",
|
|
4372
6732
|
"plans",
|
|
4373
6733
|
"webhooks",
|
|
6734
|
+
"custom-field-definitions",
|
|
4374
6735
|
"event-registrations",
|
|
6736
|
+
"event-admission-holds",
|
|
6737
|
+
"event-admission-types",
|
|
4375
6738
|
"customer-payment-methods",
|
|
4376
|
-
"tenant-payment-credentials"
|
|
6739
|
+
"tenant-payment-credentials",
|
|
6740
|
+
"commerce-payment-accounts",
|
|
6741
|
+
"payment-provider-customer-aliases"
|
|
4377
6742
|
];
|
|
4378
6743
|
var COLLECTIONS = [
|
|
4379
6744
|
"tenants",
|
|
@@ -4432,6 +6797,7 @@ var COLLECTIONS = [
|
|
|
4432
6797
|
"event-occurrences",
|
|
4433
6798
|
"event-tags",
|
|
4434
6799
|
"membership-plans",
|
|
6800
|
+
"membership-plan-prices",
|
|
4435
6801
|
"customer-memberships"
|
|
4436
6802
|
];
|
|
4437
6803
|
var SERVER_ONLY_COLLECTIONS = [
|
|
@@ -4440,9 +6806,14 @@ var SERVER_ONLY_COLLECTIONS = [
|
|
|
4440
6806
|
"images",
|
|
4441
6807
|
"videos",
|
|
4442
6808
|
"orders",
|
|
6809
|
+
"order-tags",
|
|
4443
6810
|
"order-items",
|
|
4444
6811
|
"returns",
|
|
4445
6812
|
"return-items",
|
|
6813
|
+
"refunds",
|
|
6814
|
+
"refund-line-items",
|
|
6815
|
+
"order-edit-sessions",
|
|
6816
|
+
"order-staged-changes",
|
|
4446
6817
|
"fulfillment-orders",
|
|
4447
6818
|
"fulfillment-order-items",
|
|
4448
6819
|
"fulfillments",
|
|
@@ -4455,6 +6826,8 @@ var SERVER_ONLY_COLLECTIONS = [
|
|
|
4455
6826
|
"cart-items",
|
|
4456
6827
|
"checkouts",
|
|
4457
6828
|
"checkout-items",
|
|
6829
|
+
"draft-orders",
|
|
6830
|
+
"draft-order-items",
|
|
4458
6831
|
"posts",
|
|
4459
6832
|
"comments",
|
|
4460
6833
|
"reactions",
|
|
@@ -4850,9 +7223,9 @@ var generateOrderNumber = () => {
|
|
|
4850
7223
|
const year = now.getFullYear().toString().slice(-2);
|
|
4851
7224
|
const month = (now.getMonth() + 1).toString().padStart(2, "0");
|
|
4852
7225
|
const day = now.getDate().toString().padStart(2, "0");
|
|
4853
|
-
const
|
|
4854
|
-
globalThis.crypto.getRandomValues(
|
|
4855
|
-
const random = ((
|
|
7226
|
+
const array2 = new Uint32Array(1);
|
|
7227
|
+
globalThis.crypto.getRandomValues(array2);
|
|
7228
|
+
const random = ((array2[0] ?? 0) % 1e6).toString().padStart(6, "0");
|
|
4856
7229
|
return `${year}${month}${day}${random}`;
|
|
4857
7230
|
};
|
|
4858
7231
|
|
|
@@ -4903,7 +7276,7 @@ function createAnalytics(config) {
|
|
|
4903
7276
|
}, destroy() {
|
|
4904
7277
|
} };
|
|
4905
7278
|
}
|
|
4906
|
-
const
|
|
7279
|
+
const endpoint2 = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
|
|
4907
7280
|
const respectDnt = config.respectDnt !== false;
|
|
4908
7281
|
function isDntActive() {
|
|
4909
7282
|
if (!respectDnt) return false;
|
|
@@ -4944,10 +7317,10 @@ function createAnalytics(config) {
|
|
|
4944
7317
|
try {
|
|
4945
7318
|
if (typeof navigator.sendBeacon === "function") {
|
|
4946
7319
|
const blob = new Blob([body], { type: "text/plain" });
|
|
4947
|
-
const sent = navigator.sendBeacon(
|
|
7320
|
+
const sent = navigator.sendBeacon(endpoint2, blob);
|
|
4948
7321
|
if (sent) return;
|
|
4949
7322
|
}
|
|
4950
|
-
fetch(
|
|
7323
|
+
fetch(endpoint2, {
|
|
4951
7324
|
method: "POST",
|
|
4952
7325
|
keepalive: true,
|
|
4953
7326
|
headers: { "Content-Type": "application/json" },
|