@01.software/sdk 0.51.0 → 0.65.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 +313 -0
- package/README.md +228 -102
- package/dist/client.cjs +556 -60
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +6 -6
- package/dist/client.d.ts +6 -6
- package/dist/client.js +556 -60
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-CWAeuzV4.d.cts → collection-client-B7rsTtVj.d.cts} +6 -6
- package/dist/{collection-client-hYvVfHIm.d.ts → collection-client-C2sMvfme.d.ts} +6 -6
- package/dist/{const-JD8obaKg.d.ts → const-CRxPTDGt.d.ts} +2 -2
- package/dist/{const-D8LixhAJ.d.cts → const-D6ZRQLxI.d.cts} +2 -2
- package/dist/{index-B0Hjh3Ey.d.ts → index-1auUEYrl.d.ts} +24 -7
- package/dist/{index-Bu0kCc6o.d.cts → index-Bbpf5t-l.d.cts} +24 -7
- package/dist/index.cjs +573 -260
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -12
- package/dist/index.d.ts +19 -12
- package/dist/index.js +573 -260
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-BOsckg8B.d.cts → payload-types-BnIET0xU.d.cts} +567 -438
- package/dist/{payload-types-BOsckg8B.d.ts → payload-types-BnIET0xU.d.ts} +567 -438
- package/dist/query.cjs +62 -3
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +5 -5
- package/dist/query.d.ts +5 -5
- package/dist/query.js +62 -3
- package/dist/query.js.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/server.cjs +557 -20
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +14 -8
- package/dist/server.d.ts +14 -8
- package/dist/server.js +557 -20
- package/dist/server.js.map +1 -1
- package/dist/{types-5ZlcAFuU.d.ts → types-D1y4TgQm.d.ts} +2 -2
- package/dist/{types-Bj8j7VHU.d.ts → types-DnRC3nLG.d.ts} +464 -16
- package/dist/{types-B14sEt1z.d.cts → types-Dp1oYpD3.d.cts} +2 -2
- package/dist/{types-CM5qiR2k.d.cts → types-Dzn0LD2N.d.cts} +464 -16
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.cjs +4 -2
- package/dist/ui/video.cjs.map +1 -1
- package/dist/ui/video.d.cts +4 -2
- package/dist/ui/video.d.ts +4 -2
- package/dist/ui/video.js +4 -2
- package/dist/ui/video.js.map +1 -1
- package/dist/webhook.cjs +13 -2
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +5 -5
- package/dist/webhook.d.ts +5 -5
- package/dist/webhook.js +13 -2
- package/dist/webhook.js.map +1 -1
- package/package.json +9 -28
- package/dist/analytics/react.cjs +0 -344
- package/dist/analytics/react.cjs.map +0 -1
- package/dist/analytics/react.d.cts +0 -24
- package/dist/analytics/react.d.ts +0 -24
- package/dist/analytics/react.js +0 -319
- package/dist/analytics/react.js.map +0 -1
- package/dist/analytics.cjs +0 -238
- package/dist/analytics.cjs.map +0 -1
- package/dist/analytics.d.cts +0 -39
- package/dist/analytics.d.ts +0 -39
- package/dist/analytics.js +0 -215
- package/dist/analytics.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1005,6 +1005,49 @@ function stockSnapshotSearchParams(params) {
|
|
|
1005
1005
|
}
|
|
1006
1006
|
|
|
1007
1007
|
// src/core/collection/http-client.ts
|
|
1008
|
+
function validateWhere(where) {
|
|
1009
|
+
if (where === void 0) return false;
|
|
1010
|
+
let hasNull = false;
|
|
1011
|
+
function visit(value, depth, key) {
|
|
1012
|
+
if (depth > 10) {
|
|
1013
|
+
throw createValidationError(
|
|
1014
|
+
"Collection where must not exceed nesting depth 10."
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
if (value === null && (key === "equals" || key === "not_equals")) {
|
|
1018
|
+
hasNull = true;
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
if (value == null) {
|
|
1022
|
+
throw createValidationError(
|
|
1023
|
+
"Collection where must not contain null or undefined values."
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
if (Array.isArray(value)) {
|
|
1027
|
+
if (value.length === 0) {
|
|
1028
|
+
throw createValidationError(
|
|
1029
|
+
"Collection where must not contain empty arrays, including and/or."
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
if (value.length > 1e3) {
|
|
1033
|
+
throw createValidationError(
|
|
1034
|
+
"Collection where arrays must not contain more than 1000 elements."
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
for (const item of value) visit(item, depth + 1);
|
|
1038
|
+
} else if (typeof value === "object" && !(value instanceof Date)) {
|
|
1039
|
+
const values = Object.entries(value);
|
|
1040
|
+
if (values.length === 0) {
|
|
1041
|
+
throw createValidationError(
|
|
1042
|
+
"Collection where must not contain empty condition objects."
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
for (const [key2, item] of values) visit(item, depth + 1, key2);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
visit(where, 0);
|
|
1049
|
+
return hasNull;
|
|
1050
|
+
}
|
|
1008
1051
|
var HttpClient = class {
|
|
1009
1052
|
constructor(publishableKey, secretKey, getCustomerToken, onUnauthorized, onRequestId, apiUrl) {
|
|
1010
1053
|
this.publishableKey = requirePublishableKeyForSecret(
|
|
@@ -1051,7 +1094,8 @@ var HttpClient = class {
|
|
|
1051
1094
|
...rest,
|
|
1052
1095
|
"fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
|
|
1053
1096
|
};
|
|
1054
|
-
const
|
|
1097
|
+
const encodedOptions = validateWhere(queryOptions.where) ? { ...queryOptions, where: JSON.stringify(queryOptions.where) } : queryOptions;
|
|
1098
|
+
const queryString = stringify(encodedOptions, { addQueryPrefix: true });
|
|
1055
1099
|
return queryString ? `${endpoint}${queryString}` : endpoint;
|
|
1056
1100
|
}
|
|
1057
1101
|
assertJsonResponse(response) {
|
|
@@ -1360,6 +1404,11 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1360
1404
|
detail: strictCommerceOperation("checkouts", "post", "/detail"),
|
|
1361
1405
|
query: strictCommerceOperation("checkouts", "post", "/query")
|
|
1362
1406
|
},
|
|
1407
|
+
draftOrders: {
|
|
1408
|
+
calculate: operation("draft-orders", "post", "/:id/calculate"),
|
|
1409
|
+
complete: operation("draft-orders", "post", "/:id/complete"),
|
|
1410
|
+
finalize: operation("draft-orders", "post", "/:id/finalize")
|
|
1411
|
+
},
|
|
1363
1412
|
transactions: {
|
|
1364
1413
|
update: operation("transactions", "post", "/update")
|
|
1365
1414
|
},
|
|
@@ -1459,8 +1508,51 @@ var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
|
|
|
1459
1508
|
]);
|
|
1460
1509
|
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
1461
1510
|
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
1511
|
+
billingCustody: operation(null, "post", "/memberships/billing-custody"),
|
|
1462
1512
|
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
1463
|
-
me: operation(null, "get", "/memberships/me")
|
|
1513
|
+
me: operation(null, "get", "/memberships/me"),
|
|
1514
|
+
chargeResult: operation(null, "post", "/memberships/:id/charge-result"),
|
|
1515
|
+
refundResult: operation(null, "post", "/memberships/:id/refund-result"),
|
|
1516
|
+
revoke: operation(null, "post", "/memberships/:id/revoke")
|
|
1517
|
+
};
|
|
1518
|
+
var EXTERNAL_EFFECT_CLAIM_ENDPOINT_OPERATIONS = {
|
|
1519
|
+
claim: operation(null, "post", "/external-effect-claims/claim"),
|
|
1520
|
+
get: operation(null, "post", "/external-effect-claims/get"),
|
|
1521
|
+
arm: operation(null, "post", "/external-effect-claims/arm"),
|
|
1522
|
+
release: operation(null, "post", "/external-effect-claims/release"),
|
|
1523
|
+
report: operation(null, "post", "/external-effect-claims/report"),
|
|
1524
|
+
recovery: operation(null, "post", "/external-effect-claims/recovery")
|
|
1525
|
+
};
|
|
1526
|
+
var INSTALLATION_CREDENTIAL_ENDPOINT_OPERATIONS = {
|
|
1527
|
+
create: operation(null, "post", "/installation-credentials/create"),
|
|
1528
|
+
get: operation(null, "post", "/installation-credentials/get"),
|
|
1529
|
+
replace: operation(null, "post", "/installation-credentials/replace"),
|
|
1530
|
+
dispose: operation(null, "post", "/installation-credentials/dispose")
|
|
1531
|
+
};
|
|
1532
|
+
var EXTERNAL_CUSTOMER_LINK_ENDPOINT_OPERATIONS = {
|
|
1533
|
+
connect: operation("customers", "post", "/external-links/connect"),
|
|
1534
|
+
get: operation("customers", "post", "/external-links/get"),
|
|
1535
|
+
list: operation("customers", "post", "/external-links/list"),
|
|
1536
|
+
unlink: operation("customers", "post", "/external-links/unlink"),
|
|
1537
|
+
capturePreviousState: operation(
|
|
1538
|
+
"customers",
|
|
1539
|
+
"post",
|
|
1540
|
+
"/external-links/capture-previous-state"
|
|
1541
|
+
),
|
|
1542
|
+
clearPreviousState: operation(
|
|
1543
|
+
"customers",
|
|
1544
|
+
"post",
|
|
1545
|
+
"/external-links/clear-previous-state"
|
|
1546
|
+
)
|
|
1547
|
+
};
|
|
1548
|
+
var CUSTOMER_GROUP_ENDPOINT_OPERATIONS = {
|
|
1549
|
+
members: operation("customer-groups", "get", "/:id/members"),
|
|
1550
|
+
grant: operation("customer-groups", "post", "/:id/members/grant"),
|
|
1551
|
+
revoke: operation("customer-groups", "post", "/:id/members/revoke")
|
|
1552
|
+
};
|
|
1553
|
+
var CUSTOMER_AUTH_ENDPOINT_OPERATIONS = {
|
|
1554
|
+
revokeRefresh: operation("customers", "post", "/revoke-refresh"),
|
|
1555
|
+
withdraw: operation("customers", "post", "/withdraw")
|
|
1464
1556
|
};
|
|
1465
1557
|
var EMBEDDED_ADMIN_ENDPOINT_OPERATIONS = {
|
|
1466
1558
|
show: operation("tenants", "get", "/embedded-admin-app"),
|
|
@@ -1485,6 +1577,14 @@ var COMMUNITY_ENDPOINT_OPERATIONS = {
|
|
|
1485
1577
|
detail: operation("posts", "get", "/detail")
|
|
1486
1578
|
}
|
|
1487
1579
|
};
|
|
1580
|
+
var GALLERY_ENDPOINT_OPERATIONS = {
|
|
1581
|
+
items: {
|
|
1582
|
+
storefront: operation("gallery-items", "get", "/storefront")
|
|
1583
|
+
}
|
|
1584
|
+
};
|
|
1585
|
+
var VIDEO_ENDPOINT_OPERATIONS = {
|
|
1586
|
+
playback: operation("videos", "post", "/:id/playback")
|
|
1587
|
+
};
|
|
1488
1588
|
function resolveOperationTemplate(descriptor) {
|
|
1489
1589
|
return descriptor.collection ? `/api/${descriptor.collection}${descriptor.path}` : `/api${descriptor.path}`;
|
|
1490
1590
|
}
|
|
@@ -2074,6 +2174,15 @@ var PublicContentApi = class extends RawCustomerScopedApi {
|
|
|
2074
2174
|
get(endpoint) {
|
|
2075
2175
|
return this.request(endpoint, { method: "GET" });
|
|
2076
2176
|
}
|
|
2177
|
+
galleryItems(options) {
|
|
2178
|
+
const operation2 = GALLERY_ENDPOINT_OPERATIONS.items.storefront;
|
|
2179
|
+
return this.request(
|
|
2180
|
+
resolveOperationPath(operation2, {
|
|
2181
|
+
query: galleryItemsListQuery(options)
|
|
2182
|
+
}),
|
|
2183
|
+
{ method: resolveOperationMethod(operation2) }
|
|
2184
|
+
);
|
|
2185
|
+
}
|
|
2077
2186
|
};
|
|
2078
2187
|
function appendCommonParams(search, options, defaultSort) {
|
|
2079
2188
|
search.set("sort", options?.sort ?? defaultSort);
|
|
@@ -2093,12 +2202,12 @@ function linksListPath(options) {
|
|
|
2093
2202
|
search.set("featured", String(options.featured));
|
|
2094
2203
|
return `/api/links/storefront?${search}`;
|
|
2095
2204
|
}
|
|
2096
|
-
function
|
|
2205
|
+
function galleryItemsListQuery(options) {
|
|
2097
2206
|
const search = new URLSearchParams();
|
|
2098
2207
|
appendCommonParams(search, options, "manual");
|
|
2099
2208
|
if (options?.galleryId) search.set("galleryId", options.galleryId);
|
|
2100
2209
|
if (options?.gallerySlug) search.set("gallerySlug", options.gallerySlug);
|
|
2101
|
-
return
|
|
2210
|
+
return search;
|
|
2102
2211
|
}
|
|
2103
2212
|
var ContentClient = class {
|
|
2104
2213
|
constructor(options) {
|
|
@@ -2112,9 +2221,7 @@ var ContentClient = class {
|
|
|
2112
2221
|
list: (params) => api.get(linksListPath(params))
|
|
2113
2222
|
};
|
|
2114
2223
|
this.galleryItems = {
|
|
2115
|
-
list: (params) => api.
|
|
2116
|
-
galleryItemsListPath(params)
|
|
2117
|
-
)
|
|
2224
|
+
list: (params) => api.galleryItems(params)
|
|
2118
2225
|
};
|
|
2119
2226
|
}
|
|
2120
2227
|
};
|
|
@@ -2170,7 +2277,10 @@ var ORDER_PRIMARY_DISPLAY_STATUSES = [
|
|
|
2170
2277
|
];
|
|
2171
2278
|
var CHECKOUT_STATUSES = ["open", "placed", "abandoned"];
|
|
2172
2279
|
var ABANDONED_REASONS = ["expired", "customer", "operator"];
|
|
2173
|
-
|
|
2280
|
+
function managedPaymentProviders(providers) {
|
|
2281
|
+
return providers;
|
|
2282
|
+
}
|
|
2283
|
+
var PAYMENT_PROVIDERS = managedPaymentProviders(["toss", "portone"]);
|
|
2174
2284
|
var PAYMENT_PROVIDER_STATUSES = [
|
|
2175
2285
|
"requires_payment_method",
|
|
2176
2286
|
"requires_action",
|
|
@@ -2218,6 +2328,26 @@ function invalidCanonicalResponse(resource, details) {
|
|
|
2218
2328
|
function fail(resource, path, expected) {
|
|
2219
2329
|
invalidCanonicalResponse(resource, { path, expected });
|
|
2220
2330
|
}
|
|
2331
|
+
function providerMismatch(resource, expected, actual, operation2) {
|
|
2332
|
+
if (operation2 === "cancel") {
|
|
2333
|
+
const method = {
|
|
2334
|
+
toss: "cancel()",
|
|
2335
|
+
portone: "cancelPortOne()"
|
|
2336
|
+
}[actual];
|
|
2337
|
+
throw createApiError(
|
|
2338
|
+
`Canonical ${resource} response provider mismatch: expected ${expected}, received ${actual}.`,
|
|
2339
|
+
502,
|
|
2340
|
+
{ resource, path: "$.provider", expected, actual },
|
|
2341
|
+
`The server applied the cancellation to a ${actual} PaymentSession, but this SDK method expects ${expected}.`,
|
|
2342
|
+
`Re-invoke ${method} with the same idempotencyKey; do not create a new key.`
|
|
2343
|
+
);
|
|
2344
|
+
}
|
|
2345
|
+
invalidCanonicalResponse(resource, {
|
|
2346
|
+
path: "$.provider",
|
|
2347
|
+
expected,
|
|
2348
|
+
actual
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2221
2351
|
function record(value, resource, path) {
|
|
2222
2352
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2223
2353
|
fail(resource, path, "object");
|
|
@@ -3510,7 +3640,7 @@ function validateNextAction(value, provider, resource, path) {
|
|
|
3510
3640
|
if (action.customerEmail !== void 0)
|
|
3511
3641
|
validateCustomer({ email: action.customerEmail }, resource, path);
|
|
3512
3642
|
}
|
|
3513
|
-
function validatePublicPaymentSession(value, expectedProvider) {
|
|
3643
|
+
function validatePublicPaymentSession(value, expectedProvider, operation2) {
|
|
3514
3644
|
const resource = "PaymentSession";
|
|
3515
3645
|
const session = record(value, resource, "$");
|
|
3516
3646
|
const provider = enumValue(
|
|
@@ -3519,9 +3649,6 @@ function validatePublicPaymentSession(value, expectedProvider) {
|
|
|
3519
3649
|
resource,
|
|
3520
3650
|
"$.provider"
|
|
3521
3651
|
);
|
|
3522
|
-
if (expectedProvider !== void 0 && provider !== expectedProvider) {
|
|
3523
|
-
fail(resource, "$.provider", expectedProvider);
|
|
3524
|
-
}
|
|
3525
3652
|
const status = enumValue(
|
|
3526
3653
|
session.providerStatus,
|
|
3527
3654
|
PAYMENT_PROVIDER_STATUSES,
|
|
@@ -3725,44 +3852,128 @@ function validatePublicPaymentSession(value, expectedProvider) {
|
|
|
3725
3852
|
"$.cancellationReason"
|
|
3726
3853
|
);
|
|
3727
3854
|
}
|
|
3855
|
+
if (expectedProvider !== void 0 && provider !== expectedProvider) {
|
|
3856
|
+
if (operation2 === "cancel" && status !== "canceling" && status !== "canceled") {
|
|
3857
|
+
fail(
|
|
3858
|
+
resource,
|
|
3859
|
+
"$.providerStatus",
|
|
3860
|
+
"canceling or canceled after a successful cancellation"
|
|
3861
|
+
);
|
|
3862
|
+
}
|
|
3863
|
+
providerMismatch(resource, expectedProvider, provider, operation2);
|
|
3864
|
+
}
|
|
3728
3865
|
return value;
|
|
3729
3866
|
}
|
|
3730
3867
|
|
|
3731
3868
|
// src/core/customer/customer-auth.ts
|
|
3732
3869
|
var DEFAULT_TIMEOUT2 = 15e3;
|
|
3733
|
-
|
|
3870
|
+
var REFRESH_LOCK_TIMEOUT = DEFAULT_TIMEOUT2 * 3;
|
|
3871
|
+
var SESSION_RECORD_VERSION = 1;
|
|
3872
|
+
var STORAGE_UNUSABLE = /* @__PURE__ */ Symbol("storage-unusable");
|
|
3873
|
+
function canonicalApiIdentity(apiUrl) {
|
|
3734
3874
|
try {
|
|
3735
|
-
|
|
3875
|
+
const url = new URL(apiUrl);
|
|
3876
|
+
return `${url.protocol.toLowerCase()}//${url.host.toLowerCase()}${url.pathname.replace(/\/+$/, "")}`;
|
|
3877
|
+
} catch {
|
|
3878
|
+
return apiUrl.trim().toLowerCase().replace(/\/+$/, "");
|
|
3879
|
+
}
|
|
3880
|
+
}
|
|
3881
|
+
function buildRefreshLockName(apiUrl, publishableKey, storageKey) {
|
|
3882
|
+
return `01software:customer-auth-refresh:${canonicalApiIdentity(apiUrl)}:${publishableKey}:${storageKey}`;
|
|
3883
|
+
}
|
|
3884
|
+
function getRefreshLockRequester() {
|
|
3885
|
+
try {
|
|
3886
|
+
if (typeof navigator === "undefined") return null;
|
|
3887
|
+
const locks = navigator.locks;
|
|
3888
|
+
if (!locks || typeof locks.request !== "function") return null;
|
|
3889
|
+
return (name, options, callback) => locks.request(
|
|
3890
|
+
name,
|
|
3891
|
+
options,
|
|
3892
|
+
() => callback()
|
|
3893
|
+
);
|
|
3894
|
+
} catch {
|
|
3895
|
+
return null;
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
function parseSessionRecord(raw) {
|
|
3899
|
+
try {
|
|
3900
|
+
const parsed = JSON.parse(raw);
|
|
3901
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
3902
|
+
const candidate = parsed;
|
|
3903
|
+
if (candidate.v !== SESSION_RECORD_VERSION) return null;
|
|
3904
|
+
if (typeof candidate.rev !== "number" || !Number.isFinite(candidate.rev)) {
|
|
3905
|
+
return null;
|
|
3906
|
+
}
|
|
3907
|
+
const token = candidate.token;
|
|
3908
|
+
const refreshToken = candidate.refreshToken;
|
|
3909
|
+
if (token !== null && typeof token !== "string") return null;
|
|
3910
|
+
if (refreshToken !== null && typeof refreshToken !== "string") return null;
|
|
3911
|
+
return {
|
|
3912
|
+
v: SESSION_RECORD_VERSION,
|
|
3913
|
+
rev: candidate.rev,
|
|
3914
|
+
token,
|
|
3915
|
+
refreshToken
|
|
3916
|
+
};
|
|
3736
3917
|
} catch {
|
|
3737
3918
|
return null;
|
|
3738
3919
|
}
|
|
3739
3920
|
}
|
|
3921
|
+
function readSessionRecord(recordKey, mirrorKey, mirrorRefreshKey) {
|
|
3922
|
+
let raw;
|
|
3923
|
+
try {
|
|
3924
|
+
raw = localStorage.getItem(recordKey);
|
|
3925
|
+
} catch {
|
|
3926
|
+
return STORAGE_UNUSABLE;
|
|
3927
|
+
}
|
|
3928
|
+
if (raw !== null) {
|
|
3929
|
+
const parsed = parseSessionRecord(raw);
|
|
3930
|
+
return parsed ? { record: parsed, stored: true } : STORAGE_UNUSABLE;
|
|
3931
|
+
}
|
|
3932
|
+
try {
|
|
3933
|
+
return {
|
|
3934
|
+
record: {
|
|
3935
|
+
v: SESSION_RECORD_VERSION,
|
|
3936
|
+
rev: 0,
|
|
3937
|
+
token: localStorage.getItem(mirrorKey),
|
|
3938
|
+
refreshToken: localStorage.getItem(mirrorRefreshKey)
|
|
3939
|
+
},
|
|
3940
|
+
stored: false
|
|
3941
|
+
};
|
|
3942
|
+
} catch {
|
|
3943
|
+
return STORAGE_UNUSABLE;
|
|
3944
|
+
}
|
|
3945
|
+
}
|
|
3740
3946
|
var CustomerAuth = class {
|
|
3741
3947
|
constructor(publishableKey, options, apiUrl) {
|
|
3742
3948
|
this.refreshPromise = null;
|
|
3949
|
+
/** Canonical record key; null unless persistence is active in a browser. */
|
|
3950
|
+
this.persistRecordKey = null;
|
|
3951
|
+
/** Advisory single-value access mirror, plus the retired refresh mirror. */
|
|
3952
|
+
this.persistMirrorKey = null;
|
|
3953
|
+
this.persistMirrorRefreshKey = null;
|
|
3954
|
+
/** Cross-context refresh lock name; null when there is no shared storage. */
|
|
3955
|
+
this.refreshLockName = null;
|
|
3956
|
+
/** Revision of the canonical record this instance last observed. */
|
|
3957
|
+
this.sessionRev = 0;
|
|
3743
3958
|
this.publishableKey = publishableKey;
|
|
3744
3959
|
this.baseUrl = resolveApiUrl(apiUrl);
|
|
3745
3960
|
const persist = options?.persist ?? true;
|
|
3746
3961
|
if (persist) {
|
|
3747
3962
|
const key = typeof persist === "string" ? persist : "customer-token";
|
|
3748
|
-
const refreshKey = `${key}:refresh`;
|
|
3749
3963
|
const isBrowser = typeof window !== "undefined";
|
|
3750
|
-
this.token =
|
|
3751
|
-
this.refreshTokenValue =
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
} catch {
|
|
3764
|
-
}
|
|
3765
|
-
} : void 0;
|
|
3964
|
+
this.token = null;
|
|
3965
|
+
this.refreshTokenValue = null;
|
|
3966
|
+
if (isBrowser) {
|
|
3967
|
+
this.persistRecordKey = `${key}:session`;
|
|
3968
|
+
this.persistMirrorKey = key;
|
|
3969
|
+
this.persistMirrorRefreshKey = `${key}:refresh`;
|
|
3970
|
+
this.refreshLockName = buildRefreshLockName(
|
|
3971
|
+
this.baseUrl,
|
|
3972
|
+
publishableKey,
|
|
3973
|
+
key
|
|
3974
|
+
);
|
|
3975
|
+
this.syncFromPersistedStorage();
|
|
3976
|
+
}
|
|
3766
3977
|
} else {
|
|
3767
3978
|
this.token = options?.token ?? null;
|
|
3768
3979
|
this.refreshTokenValue = options?.refreshToken ?? null;
|
|
@@ -3790,66 +4001,334 @@ var CustomerAuth = class {
|
|
|
3790
4001
|
body: JSON.stringify(data)
|
|
3791
4002
|
}
|
|
3792
4003
|
);
|
|
3793
|
-
this.
|
|
3794
|
-
|
|
4004
|
+
if (result.refreshToken) this.setSession(result.token, result.refreshToken);
|
|
4005
|
+
else this.setToken(result.token);
|
|
3795
4006
|
return result;
|
|
3796
4007
|
}
|
|
3797
4008
|
/**
|
|
3798
4009
|
* Refresh the current token. Uses a refresh token when available, otherwise
|
|
3799
4010
|
* falls back to the legacy bearer-token compatibility path.
|
|
4011
|
+
*
|
|
4012
|
+
* Refresh tokens are single-use, so a persisted session shared by several
|
|
4013
|
+
* tabs or SDK instances must rotate at most once: concurrent rotations of the
|
|
4014
|
+
* same token are replay from the server's point of view and revoke the whole
|
|
4015
|
+
* family. Persisted browser sessions therefore serialize rotation across
|
|
4016
|
+
* contexts and re-read the canonical persisted credentials inside the lock.
|
|
3800
4017
|
*/
|
|
3801
4018
|
async refreshToken() {
|
|
4019
|
+
this.syncFromPersistedStorage();
|
|
3802
4020
|
if (!this.refreshTokenValue && !this.token) {
|
|
3803
4021
|
throw new ApiError("Not authenticated", 401);
|
|
3804
4022
|
}
|
|
3805
4023
|
if (this.refreshPromise) return this.refreshPromise;
|
|
3806
|
-
|
|
4024
|
+
const intended = this.currentFence();
|
|
4025
|
+
this.refreshPromise = this.rotateAcrossContexts(intended);
|
|
3807
4026
|
try {
|
|
3808
4027
|
return await this.refreshPromise;
|
|
3809
4028
|
} finally {
|
|
3810
4029
|
this.refreshPromise = null;
|
|
3811
4030
|
}
|
|
3812
4031
|
}
|
|
3813
|
-
|
|
3814
|
-
|
|
4032
|
+
/**
|
|
4033
|
+
* Re-read the canonical persisted session. In persisted mode the shared
|
|
4034
|
+
* record — not this instance's memory — is the source of truth, so another
|
|
4035
|
+
* context's rotation, login, or logout is observed before the next credential
|
|
4036
|
+
* use. Change callbacks are deliberately not invoked: this is a read.
|
|
4037
|
+
*/
|
|
4038
|
+
syncFromPersistedStorage() {
|
|
4039
|
+
const canonical = this.readCanonicalSession();
|
|
4040
|
+
if (canonical === STORAGE_UNUSABLE) {
|
|
4041
|
+
this.disablePersistence();
|
|
4042
|
+
return;
|
|
4043
|
+
}
|
|
4044
|
+
if (!canonical) return;
|
|
4045
|
+
this.sessionRev = canonical.record.rev;
|
|
4046
|
+
this.token = canonical.record.token;
|
|
4047
|
+
this.refreshTokenValue = canonical.record.refreshToken;
|
|
4048
|
+
}
|
|
4049
|
+
/** `null` when this instance does not persist. */
|
|
4050
|
+
readCanonicalSession() {
|
|
4051
|
+
if (!this.persistRecordKey || !this.persistMirrorKey || !this.persistMirrorRefreshKey) {
|
|
4052
|
+
return null;
|
|
4053
|
+
}
|
|
4054
|
+
return readSessionRecord(
|
|
4055
|
+
this.persistRecordKey,
|
|
4056
|
+
this.persistMirrorKey,
|
|
4057
|
+
this.persistMirrorRefreshKey
|
|
4058
|
+
);
|
|
4059
|
+
}
|
|
4060
|
+
/**
|
|
4061
|
+
* Publish a change to canonical storage.
|
|
4062
|
+
*
|
|
4063
|
+
* The canonical pair is re-read immediately before the single record write so
|
|
4064
|
+
* that a field this call does not change is taken from that read rather than
|
|
4065
|
+
* from this instance's possibly stale copy. That merge is BEST-EFFORT: it
|
|
4066
|
+
* removes the stale counterpart an instance would otherwise carry, but it is
|
|
4067
|
+
* not a compare-and-swap. Web Storage offers none, and the synchronous public
|
|
4068
|
+
* mutators cannot await the refresh lease, so a commit that lands between
|
|
4069
|
+
* this read and the store operation is lost by ordering — including the
|
|
4070
|
+
* counterpart just read, which is then republished stale. The window is one
|
|
4071
|
+
* store operation wide and the server remains authoritative; see
|
|
4072
|
+
* `CUST-AUTH-033` for the stated limit.
|
|
4073
|
+
*
|
|
4074
|
+
* Returns `false` only when `requireLiveSession` refused a write because the
|
|
4075
|
+
* canonical session had already been cleared.
|
|
4076
|
+
*/
|
|
4077
|
+
commitPersistedSession(change, options) {
|
|
4078
|
+
const recordKey = this.persistRecordKey;
|
|
4079
|
+
const mirrorKey = this.persistMirrorKey;
|
|
4080
|
+
const mirrorRefreshKey = this.persistMirrorRefreshKey;
|
|
4081
|
+
const canonical = this.readCanonicalSession();
|
|
4082
|
+
if (canonical === null || !recordKey || !mirrorKey || !mirrorRefreshKey) {
|
|
4083
|
+
return true;
|
|
4084
|
+
}
|
|
4085
|
+
if (canonical === STORAGE_UNUSABLE) {
|
|
4086
|
+
this.disablePersistence();
|
|
4087
|
+
return true;
|
|
4088
|
+
}
|
|
4089
|
+
const current = canonical.record;
|
|
4090
|
+
if (options?.requireLiveSession && !current.token && !current.refreshToken) {
|
|
4091
|
+
return false;
|
|
4092
|
+
}
|
|
4093
|
+
const next = {
|
|
4094
|
+
v: SESSION_RECORD_VERSION,
|
|
4095
|
+
rev: current.rev + 1,
|
|
4096
|
+
token: "token" in change ? change.token ?? null : current.token,
|
|
4097
|
+
refreshToken: "refreshToken" in change ? change.refreshToken ?? null : current.refreshToken
|
|
4098
|
+
};
|
|
4099
|
+
if (
|
|
4100
|
+
// Only a state that is genuinely persisted can already say what this
|
|
4101
|
+
// write would say. An absent record reads as an empty pair, and treating
|
|
4102
|
+
// that as a no-op would drop the very tombstone that stops a later
|
|
4103
|
+
// migration from resurrecting the session out of the earlier layout.
|
|
4104
|
+
canonical.stored && next.token === current.token && next.refreshToken === current.refreshToken
|
|
4105
|
+
) {
|
|
4106
|
+
this.sessionRev = current.rev;
|
|
4107
|
+
this.token = current.token;
|
|
4108
|
+
this.refreshTokenValue = current.refreshToken;
|
|
4109
|
+
return true;
|
|
4110
|
+
}
|
|
4111
|
+
try {
|
|
4112
|
+
localStorage.setItem(recordKey, JSON.stringify(next));
|
|
4113
|
+
} catch {
|
|
4114
|
+
this.disablePersistence();
|
|
4115
|
+
return true;
|
|
4116
|
+
}
|
|
4117
|
+
this.sessionRev = next.rev;
|
|
4118
|
+
this.token = next.token;
|
|
4119
|
+
this.refreshTokenValue = next.refreshToken;
|
|
4120
|
+
try {
|
|
4121
|
+
localStorage.removeItem(mirrorRefreshKey);
|
|
4122
|
+
} catch {
|
|
4123
|
+
return true;
|
|
4124
|
+
}
|
|
4125
|
+
try {
|
|
4126
|
+
if (next.token) localStorage.setItem(mirrorKey, next.token);
|
|
4127
|
+
else localStorage.removeItem(mirrorKey);
|
|
4128
|
+
} catch {
|
|
4129
|
+
}
|
|
4130
|
+
return true;
|
|
4131
|
+
}
|
|
4132
|
+
/**
|
|
4133
|
+
* Storage rejected a write or a read, so it is not a canonical store for this
|
|
4134
|
+
* instance. Fall back to the memory-only session and take no lease: there is
|
|
4135
|
+
* no shared state left to coordinate. Nothing is purged — the record commit
|
|
4136
|
+
* is atomic, so no inconsistent state was published, and another context's
|
|
4137
|
+
* valid session must not be destroyed by this instance's local failure.
|
|
4138
|
+
*/
|
|
4139
|
+
disablePersistence() {
|
|
4140
|
+
this.persistRecordKey = null;
|
|
4141
|
+
this.persistMirrorKey = null;
|
|
4142
|
+
this.persistMirrorRefreshKey = null;
|
|
4143
|
+
this.refreshLockName = null;
|
|
4144
|
+
}
|
|
4145
|
+
/**
|
|
4146
|
+
* Compare the canonical record with the fence this call captured before it
|
|
4147
|
+
* left. Every persisted decision — rotate, converge, or fail closed — goes
|
|
4148
|
+
* through this one comparison. The revision catches a logout, a fresh login,
|
|
4149
|
+
* or a manual setter even when token values coincide; the value comparison
|
|
4150
|
+
* additionally catches a mirror-only writer that cannot bump a revision.
|
|
4151
|
+
*/
|
|
4152
|
+
classifyCanonicalState(intended) {
|
|
4153
|
+
if (!this.persistRecordKey) return "current";
|
|
4154
|
+
this.syncFromPersistedStorage();
|
|
4155
|
+
if (!this.persistRecordKey) return "current";
|
|
4156
|
+
if (!this.token && !this.refreshTokenValue) return "cleared";
|
|
4157
|
+
if (intended.refreshToken !== null) {
|
|
4158
|
+
return this.refreshTokenValue === intended.refreshToken ? "current" : "superseded";
|
|
4159
|
+
}
|
|
4160
|
+
return this.token === intended.token && !this.refreshTokenValue ? "current" : "superseded";
|
|
4161
|
+
}
|
|
4162
|
+
/** The canonical persisted pair, as a refresh result. */
|
|
4163
|
+
canonicalPair(token) {
|
|
4164
|
+
return {
|
|
4165
|
+
token,
|
|
4166
|
+
...this.refreshTokenValue ? { refreshToken: this.refreshTokenValue } : {}
|
|
4167
|
+
};
|
|
4168
|
+
}
|
|
4169
|
+
/** Current credentials plus the revision they were observed at. */
|
|
4170
|
+
currentFence() {
|
|
4171
|
+
return { token: this.token, refreshToken: this.refreshTokenValue };
|
|
4172
|
+
}
|
|
4173
|
+
/**
|
|
4174
|
+
* Clear an access credential a 401 just proved unusable — but only while it
|
|
4175
|
+
* is still the canonical one. A rotation committed by another context while
|
|
4176
|
+
* the request was in flight is newer than this 401, so it must survive; the
|
|
4177
|
+
* instance adopts it instead. The refresh entry is never touched here: a
|
|
4178
|
+
* rejected access token says nothing about the refresh family.
|
|
4179
|
+
*/
|
|
4180
|
+
invalidateAccessToken(spentToken) {
|
|
4181
|
+
this.syncFromPersistedStorage();
|
|
4182
|
+
if (this.token !== spentToken) return;
|
|
4183
|
+
this.setToken(null);
|
|
4184
|
+
}
|
|
4185
|
+
/** Commit both credentials in one canonical write. */
|
|
4186
|
+
setSession(token, refreshToken, options) {
|
|
4187
|
+
this.token = token;
|
|
4188
|
+
this.refreshTokenValue = refreshToken;
|
|
4189
|
+
const committed = this.commitPersistedSession(
|
|
4190
|
+
{ token, refreshToken },
|
|
4191
|
+
options
|
|
4192
|
+
);
|
|
4193
|
+
if (!committed) return false;
|
|
4194
|
+
this.onTokenChange?.(this.token);
|
|
4195
|
+
this.onRefreshTokenChange?.(this.refreshTokenValue);
|
|
4196
|
+
return true;
|
|
4197
|
+
}
|
|
4198
|
+
/**
|
|
4199
|
+
* Serialize rotation against every other context sharing the same storage
|
|
4200
|
+
* key and API/tenant identity. Coordination is best-effort: when it is
|
|
4201
|
+
* unavailable or times out the rotation still happens, so server-side reuse
|
|
4202
|
+
* detection is never bypassed by a client that failed to coordinate.
|
|
4203
|
+
*/
|
|
4204
|
+
async rotateAcrossContexts(intended) {
|
|
4205
|
+
const lockName = this.refreshLockName;
|
|
4206
|
+
const requestLock = lockName ? getRefreshLockRequester() : null;
|
|
4207
|
+
if (!lockName || !requestLock) {
|
|
4208
|
+
return this.rotateWithCanonicalState(intended);
|
|
4209
|
+
}
|
|
4210
|
+
const controller = new AbortController();
|
|
4211
|
+
const timer = setTimeout(() => controller.abort(), REFRESH_LOCK_TIMEOUT);
|
|
4212
|
+
let entered = false;
|
|
4213
|
+
try {
|
|
4214
|
+
return await requestLock(
|
|
4215
|
+
lockName,
|
|
4216
|
+
{ signal: controller.signal },
|
|
4217
|
+
async () => {
|
|
4218
|
+
entered = true;
|
|
4219
|
+
return this.rotateWithCanonicalState(intended);
|
|
4220
|
+
}
|
|
4221
|
+
);
|
|
4222
|
+
} catch (error) {
|
|
4223
|
+
if (entered) throw error;
|
|
4224
|
+
return this.rotateWithCanonicalState(intended);
|
|
4225
|
+
} finally {
|
|
4226
|
+
clearTimeout(timer);
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
/**
|
|
4230
|
+
* Decide, against freshly re-read canonical state, whether this context still
|
|
4231
|
+
* owns the rotation.
|
|
4232
|
+
*/
|
|
4233
|
+
async rotateWithCanonicalState(intended) {
|
|
4234
|
+
let fence = intended;
|
|
4235
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
4236
|
+
const state = this.classifyCanonicalState(fence);
|
|
4237
|
+
if (state === "cleared") throw new ApiError("Not authenticated", 401);
|
|
4238
|
+
if (state === "current") return this._doRefreshToken(fence);
|
|
4239
|
+
if (this.token) return this.canonicalPair(this.token);
|
|
4240
|
+
fence = this.currentFence();
|
|
4241
|
+
}
|
|
4242
|
+
throw new ApiError("Not authenticated", 401);
|
|
4243
|
+
}
|
|
4244
|
+
async _doRefreshToken(intended) {
|
|
4245
|
+
const init = intended.refreshToken ? {
|
|
3815
4246
|
method: "POST",
|
|
3816
|
-
body: JSON.stringify({ refreshToken:
|
|
4247
|
+
body: JSON.stringify({ refreshToken: intended.refreshToken })
|
|
3817
4248
|
} : {
|
|
3818
4249
|
method: "POST",
|
|
3819
|
-
headers: { Authorization: `Bearer ${
|
|
4250
|
+
headers: { Authorization: `Bearer ${intended.token}` }
|
|
3820
4251
|
};
|
|
3821
4252
|
const result = await this.requestJson(
|
|
3822
4253
|
"/api/customers/refresh",
|
|
3823
4254
|
init
|
|
3824
4255
|
);
|
|
3825
|
-
this.
|
|
3826
|
-
if (
|
|
3827
|
-
|
|
4256
|
+
const state = this.classifyCanonicalState(intended);
|
|
4257
|
+
if (state === "cleared") throw new ApiError("Not authenticated", 401);
|
|
4258
|
+
if (state === "superseded") {
|
|
4259
|
+
if (this.token) return this.canonicalPair(this.token);
|
|
4260
|
+
throw new ApiError("Not authenticated", 401);
|
|
4261
|
+
}
|
|
4262
|
+
const replacedAccessToken = this.token !== null && this.token !== intended.token ? this.token : null;
|
|
4263
|
+
const nextToken = replacedAccessToken ?? result.token;
|
|
4264
|
+
const nextRefresh = result.refreshToken ?? null;
|
|
4265
|
+
if (!this.setSession(nextToken, nextRefresh, { requireLiveSession: true })) {
|
|
4266
|
+
throw new ApiError("Not authenticated", 401);
|
|
4267
|
+
}
|
|
4268
|
+
return {
|
|
4269
|
+
token: nextToken,
|
|
4270
|
+
...nextRefresh ? { refreshToken: nextRefresh } : {}
|
|
4271
|
+
};
|
|
3828
4272
|
}
|
|
3829
4273
|
/**
|
|
3830
|
-
* Clear
|
|
4274
|
+
* Clear local credentials synchronously. This compatibility API cannot
|
|
4275
|
+
* revoke the server-side refresh family; use logoutAsync() for that.
|
|
4276
|
+
* @deprecated Use logoutAsync() to end the direct server session.
|
|
3831
4277
|
*/
|
|
3832
4278
|
logout() {
|
|
3833
|
-
this.
|
|
3834
|
-
|
|
4279
|
+
this.setSession(null, null);
|
|
4280
|
+
}
|
|
4281
|
+
/**
|
|
4282
|
+
* End the current direct refresh family and clear local credentials even if
|
|
4283
|
+
* revocation fails. A legacy access-only session has no refresh family here.
|
|
4284
|
+
*/
|
|
4285
|
+
async logoutAsync() {
|
|
4286
|
+
this.syncFromPersistedStorage();
|
|
4287
|
+
const refreshToken = this.refreshTokenValue;
|
|
4288
|
+
this.logout();
|
|
4289
|
+
if (!refreshToken) return;
|
|
4290
|
+
const operation2 = CUSTOMER_AUTH_ENDPOINT_OPERATIONS.revokeRefresh;
|
|
4291
|
+
await this.requestJson(resolveOperationPath(operation2), {
|
|
4292
|
+
method: resolveOperationMethod(operation2),
|
|
4293
|
+
body: JSON.stringify({ refreshToken })
|
|
4294
|
+
});
|
|
4295
|
+
}
|
|
4296
|
+
/** Archive the current password account and clear this client's credentials on success. */
|
|
4297
|
+
async withdraw(currentPassword) {
|
|
4298
|
+
const token = this.getToken();
|
|
4299
|
+
if (!token) throw new ApiError("Not authenticated", 401);
|
|
4300
|
+
const operation2 = CUSTOMER_AUTH_ENDPOINT_OPERATIONS.withdraw;
|
|
4301
|
+
const result = await this.requestJson(
|
|
4302
|
+
resolveOperationPath(operation2),
|
|
4303
|
+
{
|
|
4304
|
+
method: resolveOperationMethod(operation2),
|
|
4305
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
4306
|
+
body: JSON.stringify({ currentPassword })
|
|
4307
|
+
}
|
|
4308
|
+
);
|
|
4309
|
+
if (!result || typeof result.withdrawnAt !== "string" || !Number.isFinite(Date.parse(result.withdrawnAt)))
|
|
4310
|
+
throw new ApiError("Invalid customer withdrawal response", 502);
|
|
4311
|
+
this.logout();
|
|
4312
|
+
return { withdrawnAt: result.withdrawnAt };
|
|
3835
4313
|
}
|
|
3836
4314
|
/**
|
|
3837
4315
|
* Get the current authenticated customer's profile
|
|
3838
4316
|
*/
|
|
3839
4317
|
async me() {
|
|
3840
|
-
|
|
4318
|
+
const token = this.getToken();
|
|
4319
|
+
if (!token) return null;
|
|
3841
4320
|
try {
|
|
3842
4321
|
const data = await this.requestJson(
|
|
3843
4322
|
"/api/customers/me",
|
|
3844
4323
|
{
|
|
3845
4324
|
method: "GET",
|
|
3846
|
-
headers: { Authorization: `Bearer ${
|
|
4325
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
3847
4326
|
}
|
|
3848
4327
|
);
|
|
3849
4328
|
return data.customer ?? null;
|
|
3850
4329
|
} catch (error) {
|
|
3851
4330
|
if (error instanceof SDKError && error.status === 401) {
|
|
3852
|
-
this.
|
|
4331
|
+
this.invalidateAccessToken(token);
|
|
3853
4332
|
return null;
|
|
3854
4333
|
}
|
|
3855
4334
|
throw error;
|
|
@@ -3877,12 +4356,13 @@ var CustomerAuth = class {
|
|
|
3877
4356
|
* Update the authenticated customer's profile (name, phone, marketingConsent)
|
|
3878
4357
|
*/
|
|
3879
4358
|
async updateProfile(data) {
|
|
3880
|
-
|
|
4359
|
+
const token = this.getToken();
|
|
4360
|
+
if (!token) throw new ApiError("Not authenticated", 401);
|
|
3881
4361
|
const result = await this.requestJson(
|
|
3882
4362
|
"/api/customers/me",
|
|
3883
4363
|
{
|
|
3884
4364
|
method: "PATCH",
|
|
3885
|
-
headers: { Authorization: `Bearer ${
|
|
4365
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
3886
4366
|
body: JSON.stringify(data)
|
|
3887
4367
|
}
|
|
3888
4368
|
);
|
|
@@ -3892,10 +4372,11 @@ var CustomerAuth = class {
|
|
|
3892
4372
|
* Change the password of the currently authenticated customer
|
|
3893
4373
|
*/
|
|
3894
4374
|
async changePassword(currentPassword, newPassword) {
|
|
3895
|
-
|
|
4375
|
+
const token = this.getToken();
|
|
4376
|
+
if (!token) throw new ApiError("Not authenticated", 401);
|
|
3896
4377
|
await this.requestJson("/api/customers/change-password", {
|
|
3897
4378
|
method: "POST",
|
|
3898
|
-
headers: { Authorization: `Bearer ${
|
|
4379
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
3899
4380
|
body: JSON.stringify({ currentPassword, newPassword })
|
|
3900
4381
|
});
|
|
3901
4382
|
}
|
|
@@ -3903,7 +4384,8 @@ var CustomerAuth = class {
|
|
|
3903
4384
|
* Get the authenticated customer's orders with pagination and optional status filter
|
|
3904
4385
|
*/
|
|
3905
4386
|
async getMyOrders(options) {
|
|
3906
|
-
|
|
4387
|
+
const token = this.getToken();
|
|
4388
|
+
if (!token) throw new ApiError("Not authenticated", 401);
|
|
3907
4389
|
const params = new URLSearchParams();
|
|
3908
4390
|
if (options?.page) params.set("page", String(options.page));
|
|
3909
4391
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
@@ -3925,21 +4407,27 @@ var CustomerAuth = class {
|
|
|
3925
4407
|
`/api/customers/me/orders${qs ? `?${qs}` : ""}`,
|
|
3926
4408
|
{
|
|
3927
4409
|
method: "GET",
|
|
3928
|
-
headers: { Authorization: `Bearer ${
|
|
4410
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
3929
4411
|
}
|
|
3930
4412
|
);
|
|
3931
4413
|
return validatePublicOrderList(result);
|
|
3932
4414
|
}
|
|
3933
4415
|
/**
|
|
3934
|
-
* Get the current token (or null if not authenticated)
|
|
4416
|
+
* Get the current token (or null if not authenticated).
|
|
4417
|
+
*
|
|
4418
|
+
* In persisted mode this re-reads shared storage first, so a rotation or
|
|
4419
|
+
* logout performed by another tab is observed before the token is used.
|
|
3935
4420
|
*/
|
|
3936
4421
|
getToken() {
|
|
4422
|
+
this.syncFromPersistedStorage();
|
|
3937
4423
|
return this.token;
|
|
3938
4424
|
}
|
|
3939
4425
|
/**
|
|
3940
|
-
* Get the current refresh token (or null if unavailable)
|
|
4426
|
+
* Get the current refresh token (or null if unavailable). Persisted mode
|
|
4427
|
+
* re-reads shared storage first, like {@link CustomerAuth.getToken}.
|
|
3941
4428
|
*/
|
|
3942
4429
|
getRefreshToken() {
|
|
4430
|
+
this.syncFromPersistedStorage();
|
|
3943
4431
|
return this.refreshTokenValue;
|
|
3944
4432
|
}
|
|
3945
4433
|
/**
|
|
@@ -3947,6 +4435,7 @@ var CustomerAuth = class {
|
|
|
3947
4435
|
*/
|
|
3948
4436
|
setToken(token) {
|
|
3949
4437
|
this.token = token;
|
|
4438
|
+
this.commitPersistedSession({ token });
|
|
3950
4439
|
this.onTokenChange?.(token);
|
|
3951
4440
|
}
|
|
3952
4441
|
/**
|
|
@@ -3954,13 +4443,14 @@ var CustomerAuth = class {
|
|
|
3954
4443
|
*/
|
|
3955
4444
|
setRefreshToken(refreshToken) {
|
|
3956
4445
|
this.refreshTokenValue = refreshToken;
|
|
4446
|
+
this.commitPersistedSession({ refreshToken });
|
|
3957
4447
|
this.onRefreshTokenChange?.(refreshToken);
|
|
3958
4448
|
}
|
|
3959
4449
|
/**
|
|
3960
4450
|
* Check if the customer is currently authenticated
|
|
3961
4451
|
*/
|
|
3962
4452
|
isAuthenticated() {
|
|
3963
|
-
return this.
|
|
4453
|
+
return this.getToken() !== null;
|
|
3964
4454
|
}
|
|
3965
4455
|
/**
|
|
3966
4456
|
* Internal: make a request with timeout and error handling.
|
|
@@ -4310,8 +4800,12 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4310
4800
|
...Object.keys(headers).length > 0 && { headers }
|
|
4311
4801
|
});
|
|
4312
4802
|
}
|
|
4313
|
-
async paymentSession(result, expectedProvider) {
|
|
4314
|
-
return validatePublicPaymentSession(
|
|
4803
|
+
async paymentSession(result, expectedProvider, operation2) {
|
|
4804
|
+
return validatePublicPaymentSession(
|
|
4805
|
+
await result,
|
|
4806
|
+
expectedProvider,
|
|
4807
|
+
operation2
|
|
4808
|
+
);
|
|
4315
4809
|
}
|
|
4316
4810
|
create(params) {
|
|
4317
4811
|
const { idempotencyKey, ...body } = params;
|
|
@@ -4358,7 +4852,8 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4358
4852
|
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4359
4853
|
return this.paymentSession(
|
|
4360
4854
|
this.post(endpoint, body, idempotencyKey),
|
|
4361
|
-
"toss"
|
|
4855
|
+
"toss",
|
|
4856
|
+
"cancel"
|
|
4362
4857
|
);
|
|
4363
4858
|
}
|
|
4364
4859
|
cancelPortOne(params) {
|
|
@@ -4367,7 +4862,8 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4367
4862
|
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4368
4863
|
return this.paymentSession(
|
|
4369
4864
|
this.post(endpoint, body, idempotencyKey),
|
|
4370
|
-
"portone"
|
|
4865
|
+
"portone",
|
|
4866
|
+
"cancel"
|
|
4371
4867
|
);
|
|
4372
4868
|
}
|
|
4373
4869
|
confirm(params) {
|
|
@@ -6808,7 +7304,11 @@ var COMMERCE_NOTIFICATION_EVENTS = [
|
|
|
6808
7304
|
"returnCanceled",
|
|
6809
7305
|
"returnCompleted",
|
|
6810
7306
|
"paymentReconciliationRequired",
|
|
6811
|
-
"paymentRefundRequiresAttention"
|
|
7307
|
+
"paymentRefundRequiresAttention",
|
|
7308
|
+
"membershipActivated",
|
|
7309
|
+
"membershipPastDue",
|
|
7310
|
+
"membershipExpired",
|
|
7311
|
+
"membershipCancelled"
|
|
6812
7312
|
];
|
|
6813
7313
|
function isStringOrNumber(value) {
|
|
6814
7314
|
return typeof value === "string" || typeof value === "number";
|
|
@@ -6838,7 +7338,7 @@ function isCommerceNotificationEventName(value) {
|
|
|
6838
7338
|
return typeof value === "string" && COMMERCE_NOTIFICATION_EVENTS.includes(value);
|
|
6839
7339
|
}
|
|
6840
7340
|
function isCommerceNotificationSourceCollection(value) {
|
|
6841
|
-
return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts";
|
|
7341
|
+
return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts" || value === "customer-memberships";
|
|
6842
7342
|
}
|
|
6843
7343
|
function isCommerceNotificationData(value) {
|
|
6844
7344
|
if (!isRecord(value)) return false;
|
|
@@ -6858,6 +7358,10 @@ function isPaymentIncidentNotificationData(value, event) {
|
|
|
6858
7358
|
const expectedReason = reconciliation ? "orderless_capture" : "local_commit_ambiguous";
|
|
6859
7359
|
return value.source?.collection === expectedCollection && typeof value.source.id === "string" && value.source.id.length > 0 && typeof value.paymentSessionId === "string" && value.paymentSessionId.length > 0 && isRecord(value.providerObject) && typeof value.providerObject.provider === "string" && value.providerObject.provider.length > 0 && (value.providerObject.kind === "payment" || value.providerObject.kind === "refund") && typeof value.providerObject.id === "string" && value.providerObject.id.length > 0 && isRecord(value.money) && Number.isSafeInteger(value.money.amountMinor) && Number(value.money.amountMinor) > 0 && typeof value.money.currency === "string" && value.money.currency.length > 0 && value.status === expectedStatus && value.reason === expectedReason && typeof value.observedAt === "string" && value.observedAt.length > 0 && !Number.isNaN(Date.parse(value.observedAt)) && (value.checkoutId === void 0 || typeof value.checkoutId === "string" && value.checkoutId.length > 0) && (value.orderId === void 0 || typeof value.orderId === "string" && value.orderId.length > 0) && (reconciliation ? value.source.id === value.paymentSessionId && value.providerObject.kind === "payment" && value.refundAttemptId === void 0 : typeof value.refundAttemptId === "string" && value.refundAttemptId.length > 0 && value.source.id === value.refundAttemptId);
|
|
6860
7360
|
}
|
|
7361
|
+
function isMembershipNotificationData(value, event) {
|
|
7362
|
+
const expectedStatus = event === "membershipActivated" ? "active" : event === "membershipPastDue" ? "past_due" : event === "membershipExpired" ? "expired" : "cancelled";
|
|
7363
|
+
return typeof value.membershipId === "string" && value.membershipId.length > 0 && typeof value.planId === "string" && value.planId.length > 0 && typeof value.customerId === "string" && value.customerId.length > 0 && typeof value.fromStatus === "string" && value.fromStatus.length > 0 && value.fromStatus !== value.toStatus && value.toStatus === expectedStatus && typeof value.occurredAt === "string" && !Number.isNaN(Date.parse(value.occurredAt));
|
|
7364
|
+
}
|
|
6861
7365
|
function isWebhookCommerceNotificationChange(value) {
|
|
6862
7366
|
if (!isRecord(value)) return false;
|
|
6863
7367
|
return value.type === "notification" && value.source === "commerce-notifications" && isCommerceNotificationEventName(value.event) && isCommerceNotificationSourceCollection(value.sourceCollection) && isStringOrNumber(value.sourceId);
|
|
@@ -6906,6 +7410,9 @@ function isCommerceNotificationWebhookEvent(event) {
|
|
|
6906
7410
|
const notificationSourceId = notification.event === "paymentReconciliationRequired" ? notification.paymentSessionId : notification.refundAttemptId;
|
|
6907
7411
|
return sourceCollection === expectedCollection && typeof notification.paymentSessionId === "string" && notification.paymentSessionId === incidentData.paymentSessionId && typeof notificationSourceId === "string" && notificationSourceId === incidentData.source.id && matchesOptionalId(changeSourceId, incidentData.source.id);
|
|
6908
7412
|
}
|
|
7413
|
+
if (notification.event === "membershipActivated" || notification.event === "membershipPastDue" || notification.event === "membershipExpired" || notification.event === "membershipCancelled") {
|
|
7414
|
+
return sourceCollection === "customer-memberships" && isMembershipNotificationData(data, notification.event) && typeof notification.membershipId === "string" && notification.membershipId === data.membershipId && matchesOptionalId(changeSourceId, data.membershipId);
|
|
7415
|
+
}
|
|
6909
7416
|
if (notification.event === "orderPaid" || notification.event === "orderCanceled" || notification.event === "orderDelivered") {
|
|
6910
7417
|
return sourceCollection === "orders" && typeof notification.orderId === "string" && notification.orderId.length > 0 && matchesOptionalId(data.orderId, sourceId) && matchesOptionalId(notification.orderId, sourceId) && matchesOptionalId(data.orderId, notification.orderId) && matchesOptionalId(changeSourceId, data.orderId ?? notification.orderId);
|
|
6911
7418
|
}
|
|
@@ -7002,9 +7509,7 @@ var INTERNAL_COLLECTIONS = [
|
|
|
7002
7509
|
"audiences",
|
|
7003
7510
|
"email-logs",
|
|
7004
7511
|
"api-usage",
|
|
7005
|
-
"tenant-
|
|
7006
|
-
"tenant-web-analytics-config",
|
|
7007
|
-
"analytics-event-schemas",
|
|
7512
|
+
"tenant-mcp-usage-daily",
|
|
7008
7513
|
"subscriptions",
|
|
7009
7514
|
"billing-history",
|
|
7010
7515
|
"usage-rate-cards",
|
|
@@ -7023,6 +7528,8 @@ var INTERNAL_COLLECTIONS = [
|
|
|
7023
7528
|
"fulfillment-events",
|
|
7024
7529
|
"tenant-commerce-config",
|
|
7025
7530
|
"customer-oauth-clients",
|
|
7531
|
+
"customer-consent-receipts",
|
|
7532
|
+
"customer-group-grants",
|
|
7026
7533
|
"api-keys",
|
|
7027
7534
|
"personal-access-tokens",
|
|
7028
7535
|
"tenant-entitlements",
|
|
@@ -7040,6 +7547,7 @@ var INTERNAL_COLLECTIONS = [
|
|
|
7040
7547
|
"event-admission-types",
|
|
7041
7548
|
"customer-payment-methods",
|
|
7042
7549
|
"tenant-payment-credentials",
|
|
7550
|
+
"membership-unapplied-paid-evidence",
|
|
7043
7551
|
"commerce-payment-accounts",
|
|
7044
7552
|
"payment-provider-customer-aliases"
|
|
7045
7553
|
];
|
|
@@ -7422,200 +7930,6 @@ function getVideoMp4Url(playbackId, resolution = "high") {
|
|
|
7422
7930
|
return `${MUX_STREAM_BASE}/${playbackId}/${resolution}.mp4`;
|
|
7423
7931
|
}
|
|
7424
7932
|
|
|
7425
|
-
// src/analytics.ts
|
|
7426
|
-
function createAnalytics(config) {
|
|
7427
|
-
if (typeof window === "undefined") {
|
|
7428
|
-
return { pageview() {
|
|
7429
|
-
}, track() {
|
|
7430
|
-
}, destroy() {
|
|
7431
|
-
} };
|
|
7432
|
-
}
|
|
7433
|
-
const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
|
|
7434
|
-
const respectDnt = config.respectDnt !== false;
|
|
7435
|
-
function isDntActive() {
|
|
7436
|
-
if (!respectDnt) return false;
|
|
7437
|
-
const nav = navigator;
|
|
7438
|
-
return nav.doNotTrack === "1" || nav.globalPrivacyControl === true;
|
|
7439
|
-
}
|
|
7440
|
-
const isLocalHost = (() => {
|
|
7441
|
-
try {
|
|
7442
|
-
const h = location.hostname;
|
|
7443
|
-
return h === "localhost" || h === "127.0.0.1" || h.endsWith(".local");
|
|
7444
|
-
} catch {
|
|
7445
|
-
return false;
|
|
7446
|
-
}
|
|
7447
|
-
})();
|
|
7448
|
-
const mode = config.mode ?? "auto";
|
|
7449
|
-
const sendSuppressed = mode === "development" || mode === "auto" && isLocalHost;
|
|
7450
|
-
let suppressNoticeShown = false;
|
|
7451
|
-
function devSuppressNotice() {
|
|
7452
|
-
if (suppressNoticeShown) return;
|
|
7453
|
-
suppressNoticeShown = true;
|
|
7454
|
-
try {
|
|
7455
|
-
console.info(
|
|
7456
|
-
`[01 analytics] events disabled on local host (mode: '${mode}'). Pass mode: 'production' to send while developing.`
|
|
7457
|
-
);
|
|
7458
|
-
} catch {
|
|
7459
|
-
}
|
|
7460
|
-
}
|
|
7461
|
-
let lastPath = null;
|
|
7462
|
-
let lastAt = 0;
|
|
7463
|
-
const autoTrack = config.autoTrack !== false;
|
|
7464
|
-
const originalPushState = history.pushState;
|
|
7465
|
-
const originalReplaceState = history.replaceState;
|
|
7466
|
-
let destroyed = false;
|
|
7467
|
-
function newEventId() {
|
|
7468
|
-
return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : String(Date.now()) + String(Math.random());
|
|
7469
|
-
}
|
|
7470
|
-
function sendBeaconOrFetch(body) {
|
|
7471
|
-
try {
|
|
7472
|
-
if (typeof navigator.sendBeacon === "function") {
|
|
7473
|
-
const blob = new Blob([body], { type: "text/plain" });
|
|
7474
|
-
const sent = navigator.sendBeacon(endpoint, blob);
|
|
7475
|
-
if (sent) return;
|
|
7476
|
-
}
|
|
7477
|
-
fetch(endpoint, {
|
|
7478
|
-
method: "POST",
|
|
7479
|
-
keepalive: true,
|
|
7480
|
-
headers: { "Content-Type": "application/json" },
|
|
7481
|
-
body
|
|
7482
|
-
}).catch(() => {
|
|
7483
|
-
});
|
|
7484
|
-
} catch {
|
|
7485
|
-
}
|
|
7486
|
-
}
|
|
7487
|
-
function sendPageview(pathname) {
|
|
7488
|
-
if (isDntActive()) return;
|
|
7489
|
-
const doc = document;
|
|
7490
|
-
if (doc.prerendering === true || document.visibilityState === "prerender") return;
|
|
7491
|
-
if (sendSuppressed) {
|
|
7492
|
-
devSuppressNotice();
|
|
7493
|
-
return;
|
|
7494
|
-
}
|
|
7495
|
-
const now = Date.now();
|
|
7496
|
-
if (pathname === lastPath && now - lastAt < 500) return;
|
|
7497
|
-
lastPath = pathname;
|
|
7498
|
-
lastAt = now;
|
|
7499
|
-
const body = JSON.stringify({
|
|
7500
|
-
publishableKey: config.publishableKey,
|
|
7501
|
-
pathname,
|
|
7502
|
-
referrer: document.referrer || "",
|
|
7503
|
-
eventId: newEventId(),
|
|
7504
|
-
eventTs: Date.now()
|
|
7505
|
-
});
|
|
7506
|
-
sendBeaconOrFetch(body);
|
|
7507
|
-
}
|
|
7508
|
-
function trackCurrentPath() {
|
|
7509
|
-
if (destroyed) return;
|
|
7510
|
-
sendPageview(location.pathname);
|
|
7511
|
-
}
|
|
7512
|
-
function patchedPushState(data, unused, url) {
|
|
7513
|
-
originalPushState.apply(this, [data, unused, url]);
|
|
7514
|
-
if (!destroyed) setTimeout(trackCurrentPath, 0);
|
|
7515
|
-
}
|
|
7516
|
-
function patchedReplaceState(data, unused, url) {
|
|
7517
|
-
originalReplaceState.apply(this, [data, unused, url]);
|
|
7518
|
-
if (!destroyed) setTimeout(trackCurrentPath, 0);
|
|
7519
|
-
}
|
|
7520
|
-
if (autoTrack) {
|
|
7521
|
-
history.pushState = patchedPushState;
|
|
7522
|
-
history.replaceState = patchedReplaceState;
|
|
7523
|
-
window.addEventListener("popstate", trackCurrentPath);
|
|
7524
|
-
if (document.readyState === "complete") {
|
|
7525
|
-
trackCurrentPath();
|
|
7526
|
-
} else {
|
|
7527
|
-
window.addEventListener("load", trackCurrentPath, { once: true });
|
|
7528
|
-
}
|
|
7529
|
-
}
|
|
7530
|
-
const isProduction = !isLocalHost;
|
|
7531
|
-
const warnedReasons = /* @__PURE__ */ new Set();
|
|
7532
|
-
function devWarn(name, reason) {
|
|
7533
|
-
if (isProduction) return;
|
|
7534
|
-
if (warnedReasons.has(reason)) return;
|
|
7535
|
-
warnedReasons.add(reason);
|
|
7536
|
-
console.warn(`[01 analytics] dropped event ${name}: ${reason}`);
|
|
7537
|
-
}
|
|
7538
|
-
const EVENT_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_:-]{0,49}$/;
|
|
7539
|
-
const RESERVED_PREFIXES = ["__", "_pv_"];
|
|
7540
|
-
function validateEventName(name) {
|
|
7541
|
-
if (!name || typeof name !== "string") return "name-empty";
|
|
7542
|
-
for (const prefix of RESERVED_PREFIXES) {
|
|
7543
|
-
if (name.startsWith(prefix)) return "name-reserved";
|
|
7544
|
-
}
|
|
7545
|
-
if (!EVENT_NAME_RE.test(name)) return "name-regex";
|
|
7546
|
-
return null;
|
|
7547
|
-
}
|
|
7548
|
-
const PROP_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]{0,31}$/;
|
|
7549
|
-
function validateEventProps(props) {
|
|
7550
|
-
if (props === void 0 || props === null) return null;
|
|
7551
|
-
if (typeof props !== "object" || Array.isArray(props)) return "props-value-type";
|
|
7552
|
-
const keys = Object.keys(props);
|
|
7553
|
-
if (keys.length > 10) return "props-too-many-keys";
|
|
7554
|
-
for (const k of keys) {
|
|
7555
|
-
const v = props[k];
|
|
7556
|
-
if (!PROP_KEY_RE.test(k)) return "props-key-regex";
|
|
7557
|
-
if (typeof v === "string") {
|
|
7558
|
-
if (v.length > 80) return "props-value-too-long";
|
|
7559
|
-
} else if (typeof v === "number") {
|
|
7560
|
-
if (!isFinite(v)) return "props-value-not-finite";
|
|
7561
|
-
} else if (typeof v === "boolean") {
|
|
7562
|
-
} else {
|
|
7563
|
-
return "props-value-type";
|
|
7564
|
-
}
|
|
7565
|
-
}
|
|
7566
|
-
return null;
|
|
7567
|
-
}
|
|
7568
|
-
return {
|
|
7569
|
-
pageview(path) {
|
|
7570
|
-
if (destroyed) return;
|
|
7571
|
-
sendPageview(path ?? location.pathname);
|
|
7572
|
-
},
|
|
7573
|
-
track(name, props) {
|
|
7574
|
-
if (destroyed) return;
|
|
7575
|
-
if (isDntActive()) return;
|
|
7576
|
-
const doc = document;
|
|
7577
|
-
if (doc.prerendering === true || document.visibilityState === "prerender") return;
|
|
7578
|
-
const nameErr = validateEventName(name);
|
|
7579
|
-
if (nameErr) {
|
|
7580
|
-
devWarn(name, nameErr);
|
|
7581
|
-
return;
|
|
7582
|
-
}
|
|
7583
|
-
if (props !== void 0) {
|
|
7584
|
-
const propsErr = validateEventProps(props);
|
|
7585
|
-
if (propsErr) {
|
|
7586
|
-
devWarn(name, propsErr);
|
|
7587
|
-
return;
|
|
7588
|
-
}
|
|
7589
|
-
}
|
|
7590
|
-
if (sendSuppressed) {
|
|
7591
|
-
devSuppressNotice();
|
|
7592
|
-
return;
|
|
7593
|
-
}
|
|
7594
|
-
const body = JSON.stringify({
|
|
7595
|
-
publishableKey: config.publishableKey,
|
|
7596
|
-
pathname: location.pathname,
|
|
7597
|
-
referrer: document.referrer || "",
|
|
7598
|
-
eventId: newEventId(),
|
|
7599
|
-
eventName: name,
|
|
7600
|
-
eventProps: props,
|
|
7601
|
-
eventTs: Date.now()
|
|
7602
|
-
});
|
|
7603
|
-
sendBeaconOrFetch(body);
|
|
7604
|
-
},
|
|
7605
|
-
destroy() {
|
|
7606
|
-
if (destroyed) return;
|
|
7607
|
-
destroyed = true;
|
|
7608
|
-
if (autoTrack) {
|
|
7609
|
-
history.pushState = originalPushState;
|
|
7610
|
-
history.replaceState = originalReplaceState;
|
|
7611
|
-
window.removeEventListener("popstate", trackCurrentPath);
|
|
7612
|
-
}
|
|
7613
|
-
lastPath = null;
|
|
7614
|
-
lastAt = 0;
|
|
7615
|
-
}
|
|
7616
|
-
};
|
|
7617
|
-
}
|
|
7618
|
-
|
|
7619
7933
|
// src/index.ts
|
|
7620
7934
|
function createClient2(options) {
|
|
7621
7935
|
return createClient(options);
|
|
@@ -7666,7 +7980,6 @@ export {
|
|
|
7666
7980
|
buildProductListingGroupsByOption,
|
|
7667
7981
|
buildProductOptionMatrix,
|
|
7668
7982
|
buildProductOptionMatrixFromDetail,
|
|
7669
|
-
createAnalytics,
|
|
7670
7983
|
createAuthError,
|
|
7671
7984
|
createClient2 as createClient,
|
|
7672
7985
|
createCommerceEmailWebhookHandler,
|