@01.software/sdk 0.49.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +130 -1
- package/MIGRATION.md +56 -0
- package/README.md +215 -45
- package/dist/client.cjs +188 -137
- 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 +188 -137
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-XfGLPuTf.d.cts → collection-client-CWAeuzV4.d.cts} +6 -4
- package/dist/{collection-client-DnDt6EQz.d.ts → collection-client-hYvVfHIm.d.ts} +6 -4
- package/dist/{const-DCNV5Kq7.d.ts → const-D8LixhAJ.d.cts} +5 -5
- package/dist/{const-CBba4lDo.d.cts → const-JD8obaKg.d.ts} +5 -5
- package/dist/embedded-admin/server.cjs +306 -0
- package/dist/embedded-admin/server.cjs.map +1 -0
- package/dist/embedded-admin/server.d.cts +33 -0
- package/dist/embedded-admin/server.d.ts +33 -0
- package/dist/embedded-admin/server.js +288 -0
- package/dist/embedded-admin/server.js.map +1 -0
- package/dist/embedded-admin.cjs +400 -0
- package/dist/embedded-admin.cjs.map +1 -0
- package/dist/embedded-admin.d.cts +61 -0
- package/dist/embedded-admin.d.ts +61 -0
- package/dist/embedded-admin.js +377 -0
- package/dist/embedded-admin.js.map +1 -0
- package/dist/errors.cjs +1 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +3 -3
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +1 -0
- package/dist/errors.js.map +1 -1
- package/dist/{index-CbKyoEzy.d.cts → index-B0Hjh3Ey.d.ts} +72 -10
- package/dist/{index-DUuIqUS8.d.ts → index-Bu0kCc6o.d.cts} +72 -10
- package/dist/index.cjs +320 -383
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -66
- package/dist/index.d.ts +8 -66
- package/dist/index.js +320 -383
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-MKbx5MuJ.d.cts → payload-types-BOsckg8B.d.cts} +263 -54
- package/dist/{payload-types-MKbx5MuJ.d.ts → payload-types-BOsckg8B.d.ts} +263 -54
- package/dist/query.cjs +94 -70
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +5 -5
- package/dist/query.d.ts +5 -5
- package/dist/query.js +94 -70
- package/dist/query.js.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/server.cjs +404 -162
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +7 -7
- package/dist/server.d.ts +7 -7
- package/dist/server.js +404 -162
- package/dist/server.js.map +1 -1
- package/dist/storefront-cache.cjs +1 -0
- package/dist/storefront-cache.cjs.map +1 -1
- package/dist/storefront-cache.js +1 -0
- package/dist/storefront-cache.js.map +1 -1
- package/dist/{types-L_nh-ED7.d.ts → types-5ZlcAFuU.d.ts} +2 -2
- package/dist/{types-BKr_2avj.d.cts → types-B14sEt1z.d.cts} +2 -2
- package/dist/{types-1UeOk1Uy.d.cts → types-Bj8j7VHU.d.ts} +79 -23
- package/dist/{types-Du4s5anw.d.ts → types-CM5qiR2k.d.cts} +79 -23
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.d.cts +1 -1
- package/dist/ui/video.d.ts +1 -1
- package/dist/webhook.cjs +124 -80
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.d.cts +21 -5
- package/dist/webhook.d.ts +21 -5
- package/dist/webhook.js +124 -80
- package/dist/webhook.js.map +1 -1
- package/package.json +23 -2
package/dist/index.cjs
CHANGED
|
@@ -130,8 +130,6 @@ __export(src_exports, {
|
|
|
130
130
|
projectProductToListingShape: () => projectProductToListingShape,
|
|
131
131
|
resolveFeaturedImagePointer: () => resolveFeaturedImagePointer,
|
|
132
132
|
resolveProductDisplayMedia: () => resolveProductDisplayMedia,
|
|
133
|
-
resolveProductGallery: () => resolveProductGallery,
|
|
134
|
-
resolveProductMedia: () => resolveProductMedia,
|
|
135
133
|
resolveProductSelection: () => resolveProductSelection,
|
|
136
134
|
resolveProductSelectionFromMatrix: () => resolveProductSelectionFromMatrix,
|
|
137
135
|
resolveProductSelectionMedia: () => resolveProductSelectionMedia,
|
|
@@ -243,6 +241,7 @@ var COMMERCE_ERROR_CODES = [
|
|
|
243
241
|
"payment_session_not_cancelable",
|
|
244
242
|
"payment_session_conflict",
|
|
245
243
|
"provider_identity_mismatch",
|
|
244
|
+
"managed_refund_attestation_forbidden",
|
|
246
245
|
"payment_method_unavailable",
|
|
247
246
|
"provider_unavailable",
|
|
248
247
|
"lock_timeout",
|
|
@@ -785,11 +784,11 @@ function parseRetryAfter(response) {
|
|
|
785
784
|
permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
|
|
786
785
|
};
|
|
787
786
|
}
|
|
788
|
-
function mapResponseToError(status, parsed, details, requestId, retryAfter,
|
|
787
|
+
function mapResponseToError(status, parsed, details, requestId, retryAfter, canonicalCommerceError) {
|
|
789
788
|
const errorDetails = {
|
|
790
789
|
...details,
|
|
791
790
|
...parsed.errors && { errors: parsed.errors },
|
|
792
|
-
|
|
791
|
+
...!canonicalCommerceError && parsed.body && { body: parsed.body }
|
|
793
792
|
};
|
|
794
793
|
const suggestion = getParsedErrorSuggestion(status, parsed);
|
|
795
794
|
const finalize = (error) => {
|
|
@@ -797,7 +796,7 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, erro
|
|
|
797
796
|
if (retryAfter !== void 0) {
|
|
798
797
|
Object.assign(withRequestId, { retryAfter });
|
|
799
798
|
}
|
|
800
|
-
return
|
|
799
|
+
return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
|
|
801
800
|
};
|
|
802
801
|
if (status === 400 || status === 422) {
|
|
803
802
|
return finalize(
|
|
@@ -903,6 +902,7 @@ async function httpFetch(url, options) {
|
|
|
903
902
|
retry,
|
|
904
903
|
onUnauthorized,
|
|
905
904
|
errorFamily,
|
|
905
|
+
typedCommerceErrorReasons,
|
|
906
906
|
...requestInit
|
|
907
907
|
} = options || {};
|
|
908
908
|
const baseUrl = resolveApiUrl(apiUrl);
|
|
@@ -956,7 +956,8 @@ async function httpFetch(url, options) {
|
|
|
956
956
|
});
|
|
957
957
|
if (!response.ok) {
|
|
958
958
|
const parsed = await parseErrorBody(response);
|
|
959
|
-
const
|
|
959
|
+
const canonicalCommerceError = errorFamily === "commerce" || typeof parsed.reason === "string" && typedCommerceErrorReasons?.includes(parsed.reason) === true;
|
|
960
|
+
const commerceEnvelope = canonicalCommerceError ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
|
|
960
961
|
if (isUsageLimitExceededResponse(response)) {
|
|
961
962
|
const limit = parseInt(
|
|
962
963
|
response.headers.get("X-Usage-Limit") || "0",
|
|
@@ -984,7 +985,7 @@ async function httpFetch(url, options) {
|
|
|
984
985
|
),
|
|
985
986
|
requestId
|
|
986
987
|
);
|
|
987
|
-
throw
|
|
988
|
+
throw canonicalCommerceError ? enhanceCommerceError(usageError, parsed.body, requestId) : enhanceNonCommerceError(usageError, parsed.reason);
|
|
988
989
|
}
|
|
989
990
|
if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
|
|
990
991
|
hasRetried401 = true;
|
|
@@ -1009,7 +1010,7 @@ async function httpFetch(url, options) {
|
|
|
1009
1010
|
details,
|
|
1010
1011
|
requestId,
|
|
1011
1012
|
retryAfter.seconds,
|
|
1012
|
-
|
|
1013
|
+
canonicalCommerceError
|
|
1013
1014
|
);
|
|
1014
1015
|
const method2 = (requestInit.method || "GET").toUpperCase();
|
|
1015
1016
|
const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
|
|
@@ -1187,15 +1188,15 @@ var HttpClient = class {
|
|
|
1187
1188
|
throw err;
|
|
1188
1189
|
}
|
|
1189
1190
|
}
|
|
1190
|
-
buildUrl(
|
|
1191
|
-
if (!options) return
|
|
1191
|
+
buildUrl(endpoint, options) {
|
|
1192
|
+
if (!options) return endpoint;
|
|
1192
1193
|
const { fallbackLocale, ...rest } = options;
|
|
1193
1194
|
const queryOptions = fallbackLocale === void 0 ? rest : {
|
|
1194
1195
|
...rest,
|
|
1195
1196
|
"fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
|
|
1196
1197
|
};
|
|
1197
1198
|
const queryString = (0, import_qs_esm.stringify)(queryOptions, { addQueryPrefix: true });
|
|
1198
|
-
return queryString ? `${
|
|
1199
|
+
return queryString ? `${endpoint}${queryString}` : endpoint;
|
|
1199
1200
|
}
|
|
1200
1201
|
assertJsonResponse(response) {
|
|
1201
1202
|
const contentType = response.headers.get("content-type");
|
|
@@ -1344,39 +1345,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1344
1345
|
from(collection) {
|
|
1345
1346
|
return new ReadOnlyCollectionQueryBuilder(this, collection);
|
|
1346
1347
|
}
|
|
1347
|
-
async requestFind(
|
|
1348
|
-
const url = this.buildUrl(
|
|
1348
|
+
async requestFind(endpoint, options) {
|
|
1349
|
+
const url = this.buildUrl(endpoint, options);
|
|
1349
1350
|
const response = await this.fetchWithTracking(url, {
|
|
1350
1351
|
...this.defaultOptions,
|
|
1351
1352
|
method: "GET"
|
|
1352
1353
|
});
|
|
1353
1354
|
return this.parseFindResponse(response);
|
|
1354
1355
|
}
|
|
1355
|
-
async requestFindEndpoint(
|
|
1356
|
-
const response = await this.fetchWithTracking(
|
|
1356
|
+
async requestFindEndpoint(endpoint, data) {
|
|
1357
|
+
const response = await this.fetchWithTracking(endpoint, {
|
|
1357
1358
|
...this.defaultOptions,
|
|
1358
1359
|
method: "POST",
|
|
1359
1360
|
body: data ? JSON.stringify(data) : void 0
|
|
1360
1361
|
});
|
|
1361
1362
|
return this.parseFindResponse(response);
|
|
1362
1363
|
}
|
|
1363
|
-
async requestFindEndpointGet(
|
|
1364
|
-
const response = await this.fetchWithTracking(
|
|
1364
|
+
async requestFindEndpointGet(endpoint) {
|
|
1365
|
+
const response = await this.fetchWithTracking(endpoint, {
|
|
1365
1366
|
...this.defaultOptions,
|
|
1366
1367
|
method: "GET"
|
|
1367
1368
|
});
|
|
1368
1369
|
return this.parseFindResponse(response);
|
|
1369
1370
|
}
|
|
1370
|
-
async requestFindById(
|
|
1371
|
-
const url = this.buildUrl(
|
|
1371
|
+
async requestFindById(endpoint, options) {
|
|
1372
|
+
const url = this.buildUrl(endpoint, options);
|
|
1372
1373
|
const response = await this.fetchWithTracking(url, {
|
|
1373
1374
|
...this.defaultOptions,
|
|
1374
1375
|
method: "GET"
|
|
1375
1376
|
});
|
|
1376
1377
|
return this.parseDocumentResponse(response);
|
|
1377
1378
|
}
|
|
1378
|
-
async requestCount(
|
|
1379
|
-
const url = this.buildUrl(
|
|
1379
|
+
async requestCount(endpoint, options) {
|
|
1380
|
+
const url = this.buildUrl(endpoint, options);
|
|
1380
1381
|
const response = await this.fetchWithTracking(url, {
|
|
1381
1382
|
...this.defaultOptions,
|
|
1382
1383
|
method: "GET"
|
|
@@ -1386,7 +1387,7 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1386
1387
|
};
|
|
1387
1388
|
|
|
1388
1389
|
// src/core/api/parse-response.ts
|
|
1389
|
-
async function parseApiResponse(response,
|
|
1390
|
+
async function parseApiResponse(response, endpoint, options = {}) {
|
|
1390
1391
|
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
1391
1392
|
return void 0;
|
|
1392
1393
|
}
|
|
@@ -1395,7 +1396,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
|
|
|
1395
1396
|
parsed = await response.json();
|
|
1396
1397
|
} catch {
|
|
1397
1398
|
throw createApiError(
|
|
1398
|
-
`Invalid JSON response from ${
|
|
1399
|
+
`Invalid JSON response from ${endpoint}`,
|
|
1399
1400
|
response.status,
|
|
1400
1401
|
void 0,
|
|
1401
1402
|
"Server returned an invalid response.",
|
|
@@ -1445,6 +1446,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
|
|
|
1445
1446
|
|
|
1446
1447
|
// ../../internal/http-contracts/src/index.ts
|
|
1447
1448
|
var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
|
|
1449
|
+
var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
|
|
1448
1450
|
var operation = (collection, method, path, errorFamily) => Object.freeze({
|
|
1449
1451
|
[operationBrand]: true,
|
|
1450
1452
|
collection,
|
|
@@ -1453,6 +1455,10 @@ var operation = (collection, method, path, errorFamily) => Object.freeze({
|
|
|
1453
1455
|
...errorFamily && { errorFamily }
|
|
1454
1456
|
});
|
|
1455
1457
|
var strictCommerceOperation = (collection, method, path) => operation(collection, method, path, "commerce");
|
|
1458
|
+
var selectiveCommerceOperation = (collection, method, path, typedCommerceErrorReasons) => Object.freeze({
|
|
1459
|
+
...operation(collection, method, path),
|
|
1460
|
+
typedCommerceErrorReasons: Object.freeze([...typedCommerceErrorReasons])
|
|
1461
|
+
});
|
|
1456
1462
|
var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
1457
1463
|
products: {
|
|
1458
1464
|
detail: operation("products", "get", "/detail"),
|
|
@@ -1484,7 +1490,12 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1484
1490
|
confirmPayment: operation("orders", "post", "/confirm-payment"),
|
|
1485
1491
|
byPayment: operation("orders", "get", "/by-payment"),
|
|
1486
1492
|
cancel: operation("orders", "post", "/cancel"),
|
|
1487
|
-
resolveCancelRefund:
|
|
1493
|
+
resolveCancelRefund: selectiveCommerceOperation(
|
|
1494
|
+
"orders",
|
|
1495
|
+
"post",
|
|
1496
|
+
"/resolve-cancel-refund",
|
|
1497
|
+
["managed_refund_attestation_forbidden"]
|
|
1498
|
+
),
|
|
1488
1499
|
checkout: strictCommerceOperation("orders", "post", "/checkout"),
|
|
1489
1500
|
createFulfillment: operation("orders", "post", "/create-fulfillment"),
|
|
1490
1501
|
updateFulfillment: operation("orders", "post", "/update-fulfillment")
|
|
@@ -1555,6 +1566,16 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1555
1566
|
"payment-sessions",
|
|
1556
1567
|
"post",
|
|
1557
1568
|
"/server/confirm"
|
|
1569
|
+
),
|
|
1570
|
+
findPortOne: strictCommerceOperation(
|
|
1571
|
+
"payment-sessions",
|
|
1572
|
+
"post",
|
|
1573
|
+
"/server/portone/find"
|
|
1574
|
+
),
|
|
1575
|
+
reconcilePortOne: strictCommerceOperation(
|
|
1576
|
+
"payment-sessions",
|
|
1577
|
+
"post",
|
|
1578
|
+
"/server/portone/reconcile"
|
|
1558
1579
|
)
|
|
1559
1580
|
},
|
|
1560
1581
|
custom: {
|
|
@@ -1574,12 +1595,26 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1574
1595
|
validate: operation("discounts", "post", "/validate")
|
|
1575
1596
|
}
|
|
1576
1597
|
};
|
|
1598
|
+
var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
|
|
1599
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.create,
|
|
1600
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.retrieve,
|
|
1601
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.create,
|
|
1602
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.retrieve
|
|
1603
|
+
]);
|
|
1577
1604
|
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
1578
1605
|
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
1579
1606
|
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
1580
1607
|
me: operation(null, "get", "/memberships/me")
|
|
1581
1608
|
};
|
|
1609
|
+
var EMBEDDED_ADMIN_ENDPOINT_OPERATIONS = {
|
|
1610
|
+
show: operation("tenants", "get", "/embedded-admin-app"),
|
|
1611
|
+
configure: operation("tenants", "patch", "/embedded-admin-app"),
|
|
1612
|
+
disable: operation("tenants", "delete", "/embedded-admin-app")
|
|
1613
|
+
};
|
|
1582
1614
|
var EVENTS_ENDPOINT_OPERATIONS = {
|
|
1615
|
+
events: {
|
|
1616
|
+
convertSchedule: operation("events", "post", "/:id/schedule")
|
|
1617
|
+
},
|
|
1583
1618
|
occurrences: {
|
|
1584
1619
|
range: operation("event-occurrences", "get", "/range"),
|
|
1585
1620
|
admissionAvailability: operation(
|
|
@@ -1620,46 +1655,51 @@ function resolveOperationMethod(descriptor) {
|
|
|
1620
1655
|
}
|
|
1621
1656
|
|
|
1622
1657
|
// src/core/api/endpoints.ts
|
|
1623
|
-
var endpoint = (method, path) => ({ method, path });
|
|
1624
1658
|
var sharedEndpoint = (descriptor) => descriptor;
|
|
1625
|
-
function resolveOperationMethod2(descriptor) {
|
|
1626
|
-
return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
|
|
1627
|
-
}
|
|
1628
1659
|
function resolveOperationErrorFamily(descriptor) {
|
|
1629
|
-
return
|
|
1630
|
-
}
|
|
1631
|
-
function resolveOperationPath2(descriptor, options) {
|
|
1632
|
-
if ("collection" in descriptor) {
|
|
1633
|
-
return resolveOperationPath(descriptor, options);
|
|
1634
|
-
}
|
|
1635
|
-
const query = options?.query?.toString().replace(/^\?/, "");
|
|
1636
|
-
return query ? `${descriptor.path}?${query}` : descriptor.path;
|
|
1660
|
+
return descriptor.errorFamily;
|
|
1637
1661
|
}
|
|
1638
1662
|
var COMMERCE_ENDPOINTS = {
|
|
1639
1663
|
products: {
|
|
1640
|
-
detail:
|
|
1641
|
-
detailCatalog:
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1664
|
+
detail: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.detail),
|
|
1665
|
+
detailCatalog: sharedEndpoint(
|
|
1666
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog
|
|
1667
|
+
),
|
|
1668
|
+
listingGroups: sharedEndpoint(
|
|
1669
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups
|
|
1670
|
+
),
|
|
1671
|
+
listingGroupsCatalog: sharedEndpoint(
|
|
1672
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog
|
|
1673
|
+
),
|
|
1674
|
+
// The manifest keeps the GET read and the POST body-query apart; this
|
|
1675
|
+
// semantic name has always resolved to the GET one.
|
|
1676
|
+
listingGroupsQuery: sharedEndpoint(
|
|
1677
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet
|
|
1678
|
+
),
|
|
1679
|
+
listingGroupsQueryCatalog: sharedEndpoint(
|
|
1680
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog
|
|
1681
|
+
),
|
|
1682
|
+
stockCheck: sharedEndpoint(
|
|
1683
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck
|
|
1646
1684
|
),
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
"GET",
|
|
1650
|
-
"/api/products/listing-groups/query/catalog"
|
|
1685
|
+
stockSnapshot: sharedEndpoint(
|
|
1686
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot
|
|
1651
1687
|
),
|
|
1652
|
-
|
|
1653
|
-
stockSnapshot: endpoint("GET", "/api/products/stock"),
|
|
1654
|
-
upsert: endpoint("POST", "/api/products/upsert")
|
|
1688
|
+
upsert: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.upsert)
|
|
1655
1689
|
},
|
|
1656
1690
|
orders: {
|
|
1657
|
-
update:
|
|
1658
|
-
byPayment:
|
|
1659
|
-
cancel:
|
|
1660
|
-
resolveCancelRefund:
|
|
1661
|
-
|
|
1662
|
-
|
|
1691
|
+
update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.update),
|
|
1692
|
+
byPayment: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.byPayment),
|
|
1693
|
+
cancel: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.cancel),
|
|
1694
|
+
resolveCancelRefund: sharedEndpoint(
|
|
1695
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.resolveCancelRefund
|
|
1696
|
+
),
|
|
1697
|
+
createFulfillment: sharedEndpoint(
|
|
1698
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.createFulfillment
|
|
1699
|
+
),
|
|
1700
|
+
updateFulfillment: sharedEndpoint(
|
|
1701
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.updateFulfillment
|
|
1702
|
+
)
|
|
1663
1703
|
},
|
|
1664
1704
|
checkouts: {
|
|
1665
1705
|
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.checkout),
|
|
@@ -1671,18 +1711,21 @@ var COMMERCE_ENDPOINTS = {
|
|
|
1671
1711
|
}
|
|
1672
1712
|
},
|
|
1673
1713
|
returns: {
|
|
1674
|
-
create:
|
|
1675
|
-
update:
|
|
1676
|
-
returnRefund:
|
|
1714
|
+
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.create),
|
|
1715
|
+
update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.update),
|
|
1716
|
+
returnRefund: sharedEndpoint(
|
|
1717
|
+
COMMERCE_ENDPOINT_OPERATIONS.returns.returnRefund
|
|
1718
|
+
)
|
|
1677
1719
|
},
|
|
1678
1720
|
fulfillmentOrders: {
|
|
1679
|
-
prepare:
|
|
1680
|
-
|
|
1681
|
-
"/api/fulfillment-orders/prepare-fulfillment-order"
|
|
1721
|
+
prepare: sharedEndpoint(
|
|
1722
|
+
COMMERCE_ENDPOINT_OPERATIONS.fulfillmentOrders.prepare
|
|
1682
1723
|
)
|
|
1683
1724
|
},
|
|
1684
1725
|
fulfillments: {
|
|
1685
|
-
bulkImport:
|
|
1726
|
+
bulkImport: sharedEndpoint(
|
|
1727
|
+
COMMERCE_ENDPOINT_OPERATIONS.fulfillments.bulkImport
|
|
1728
|
+
)
|
|
1686
1729
|
},
|
|
1687
1730
|
carts: {
|
|
1688
1731
|
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
|
|
@@ -1747,42 +1790,21 @@ var COMMERCE_ENDPOINTS = {
|
|
|
1747
1790
|
),
|
|
1748
1791
|
confirm: sharedEndpoint(
|
|
1749
1792
|
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.confirm
|
|
1793
|
+
),
|
|
1794
|
+
findPortOne: sharedEndpoint(
|
|
1795
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.findPortOne
|
|
1796
|
+
),
|
|
1797
|
+
reconcilePortOne: sharedEndpoint(
|
|
1798
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.reconcilePortOne
|
|
1750
1799
|
)
|
|
1751
1800
|
}
|
|
1752
1801
|
},
|
|
1753
1802
|
shippingPolicies: {
|
|
1754
|
-
calculate:
|
|
1803
|
+
calculate: sharedEndpoint(
|
|
1804
|
+
COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate
|
|
1805
|
+
)
|
|
1755
1806
|
}
|
|
1756
1807
|
};
|
|
1757
|
-
function isCommerceEndpointDescriptor(value) {
|
|
1758
|
-
if (!value || typeof value !== "object") return false;
|
|
1759
|
-
const candidate = value;
|
|
1760
|
-
return typeof candidate.method === "string" && typeof candidate.path === "string";
|
|
1761
|
-
}
|
|
1762
|
-
function flattenEndpointPaths(value) {
|
|
1763
|
-
if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
|
|
1764
|
-
if (!value || typeof value !== "object") return [];
|
|
1765
|
-
return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
|
|
1766
|
-
}
|
|
1767
|
-
function flattenEndpointDescriptors(value) {
|
|
1768
|
-
if (isCommerceEndpointDescriptor(value)) return [value];
|
|
1769
|
-
if (!value || typeof value !== "object") return [];
|
|
1770
|
-
return Object.values(value).flatMap(
|
|
1771
|
-
(entry) => flattenEndpointDescriptors(entry)
|
|
1772
|
-
);
|
|
1773
|
-
}
|
|
1774
|
-
var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
|
|
1775
|
-
var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
|
|
1776
|
-
var MEMBERSHIP_ENDPOINTS = {
|
|
1777
|
-
subscribe: "/api/memberships/subscribe",
|
|
1778
|
-
cancel: (id) => `/api/memberships/${id}/cancel`,
|
|
1779
|
-
me: "/api/memberships/me"
|
|
1780
|
-
};
|
|
1781
|
-
var MEMBERSHIP_ENDPOINT_PATHS = [
|
|
1782
|
-
MEMBERSHIP_ENDPOINTS.subscribe,
|
|
1783
|
-
MEMBERSHIP_ENDPOINTS.cancel(":id"),
|
|
1784
|
-
MEMBERSHIP_ENDPOINTS.me
|
|
1785
|
-
];
|
|
1786
1808
|
|
|
1787
1809
|
// src/core/api/customer-scoped-api.ts
|
|
1788
1810
|
var CustomerScopedTransport = class {
|
|
@@ -1803,10 +1825,10 @@ var CustomerScopedTransport = class {
|
|
|
1803
1825
|
this.onUnauthorized = options.onUnauthorized;
|
|
1804
1826
|
this.onRequestId = options.onRequestId;
|
|
1805
1827
|
}
|
|
1806
|
-
async request(
|
|
1828
|
+
async request(endpoint, options) {
|
|
1807
1829
|
const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
|
|
1808
1830
|
try {
|
|
1809
|
-
const response = await httpFetch(
|
|
1831
|
+
const response = await httpFetch(endpoint, {
|
|
1810
1832
|
method: options.method,
|
|
1811
1833
|
apiUrl: this.apiUrl,
|
|
1812
1834
|
publishableKey: this.publishableKey,
|
|
@@ -1820,7 +1842,7 @@ var CustomerScopedTransport = class {
|
|
|
1820
1842
|
...options.errorFamily && { errorFamily: options.errorFamily }
|
|
1821
1843
|
});
|
|
1822
1844
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
1823
|
-
return parseApiResponse(response,
|
|
1845
|
+
return parseApiResponse(response, endpoint, {
|
|
1824
1846
|
errorFamily: options.errorFamily
|
|
1825
1847
|
});
|
|
1826
1848
|
} catch (err) {
|
|
@@ -1834,12 +1856,12 @@ var CustomerScopedApi = class {
|
|
|
1834
1856
|
constructor(apiName, options) {
|
|
1835
1857
|
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1836
1858
|
}
|
|
1837
|
-
requestEndpoint(
|
|
1838
|
-
return this.transport.request(
|
|
1839
|
-
method:
|
|
1859
|
+
requestEndpoint(endpoint, body, options) {
|
|
1860
|
+
return this.transport.request(resolveOperationPath(endpoint, options), {
|
|
1861
|
+
method: resolveOperationMethod(endpoint),
|
|
1840
1862
|
body,
|
|
1841
1863
|
headers: options?.headers,
|
|
1842
|
-
errorFamily: resolveOperationErrorFamily(
|
|
1864
|
+
errorFamily: resolveOperationErrorFamily(endpoint)
|
|
1843
1865
|
});
|
|
1844
1866
|
}
|
|
1845
1867
|
};
|
|
@@ -1847,8 +1869,8 @@ var RawCustomerScopedApi = class {
|
|
|
1847
1869
|
constructor(apiName, options) {
|
|
1848
1870
|
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1849
1871
|
}
|
|
1850
|
-
request(
|
|
1851
|
-
return this.transport.request(
|
|
1872
|
+
request(endpoint, options) {
|
|
1873
|
+
return this.transport.request(endpoint, options);
|
|
1852
1874
|
}
|
|
1853
1875
|
};
|
|
1854
1876
|
|
|
@@ -1923,11 +1945,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
1923
1945
|
if (params.page !== void 0) urlParams.set("page", String(params.page));
|
|
1924
1946
|
return `/api/comments/public?${urlParams.toString()}`;
|
|
1925
1947
|
}
|
|
1926
|
-
async execute(
|
|
1927
|
-
return this.request(
|
|
1948
|
+
async execute(endpoint, method, body) {
|
|
1949
|
+
return this.request(endpoint, { method, body });
|
|
1928
1950
|
}
|
|
1929
|
-
async executeDoc(
|
|
1930
|
-
const response = await this.execute(
|
|
1951
|
+
async executeDoc(endpoint, method, body) {
|
|
1952
|
+
const response = await this.execute(endpoint, method, body);
|
|
1931
1953
|
return unwrapPayloadDoc(response);
|
|
1932
1954
|
}
|
|
1933
1955
|
createPost(params) {
|
|
@@ -2193,8 +2215,8 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
2193
2215
|
|
|
2194
2216
|
// src/core/content/content-client.ts
|
|
2195
2217
|
var PublicContentApi = class extends RawCustomerScopedApi {
|
|
2196
|
-
get(
|
|
2197
|
-
return this.request(
|
|
2218
|
+
get(endpoint) {
|
|
2219
|
+
return this.request(endpoint, { method: "GET" });
|
|
2198
2220
|
}
|
|
2199
2221
|
};
|
|
2200
2222
|
function appendCommonParams(search, options, defaultSort) {
|
|
@@ -2375,6 +2397,9 @@ function nullableString(value, resource, path) {
|
|
|
2375
2397
|
fail(resource, path, "string or null");
|
|
2376
2398
|
}
|
|
2377
2399
|
}
|
|
2400
|
+
function nullableNonEmptyString(value, resource, path) {
|
|
2401
|
+
if (value !== null) string(value, resource, path);
|
|
2402
|
+
}
|
|
2378
2403
|
function cartLineQuantity(value, resource, path) {
|
|
2379
2404
|
const quantity = positiveInteger(value, resource, path);
|
|
2380
2405
|
if (quantity > MAX_CART_LINE_QUANTITY) {
|
|
@@ -2884,8 +2909,8 @@ function validatePublicOrderItem(value, resource, path) {
|
|
|
2884
2909
|
validateReference(item.variant, resource, `${path}.variant`);
|
|
2885
2910
|
}
|
|
2886
2911
|
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2887
|
-
|
|
2888
|
-
|
|
2912
|
+
nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
2913
|
+
nullableNonEmptyString(item.sku, resource, `${path}.sku`);
|
|
2889
2914
|
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2890
2915
|
const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
|
|
2891
2916
|
const unitPrice = safeMinor(
|
|
@@ -3136,8 +3161,8 @@ function validateCheckoutItem(value, resource, path) {
|
|
|
3136
3161
|
validateReference(item.product, resource, `${path}.product`);
|
|
3137
3162
|
validateReference(item.variant, resource, `${path}.variant`);
|
|
3138
3163
|
string(item.productTitle, resource, `${path}.productTitle`);
|
|
3139
|
-
|
|
3140
|
-
|
|
3164
|
+
nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
3165
|
+
nullableNonEmptyString(item.sku, resource, `${path}.sku`);
|
|
3141
3166
|
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
3142
3167
|
cartLineQuantity(item.quantity, resource, `${path}.quantity`);
|
|
3143
3168
|
const unitPrice = safeMinor(
|
|
@@ -3469,11 +3494,21 @@ function validateNextAction(value, provider, resource, path) {
|
|
|
3469
3494
|
const action = record(value, resource, path);
|
|
3470
3495
|
if (provider === "portone") {
|
|
3471
3496
|
if (action.type === "portone_sdk") {
|
|
3497
|
+
const hasCancelable = "cancelable" in action;
|
|
3498
|
+
const hasRetryPolicy = "retryPolicy" in action;
|
|
3499
|
+
if (hasCancelable !== hasRetryPolicy) {
|
|
3500
|
+
fail(
|
|
3501
|
+
resource,
|
|
3502
|
+
path,
|
|
3503
|
+
"exact released action or exact negotiated capability action"
|
|
3504
|
+
);
|
|
3505
|
+
}
|
|
3472
3506
|
exact(
|
|
3473
3507
|
action,
|
|
3474
3508
|
[
|
|
3475
3509
|
"type",
|
|
3476
3510
|
"version",
|
|
3511
|
+
...hasCancelable ? ["cancelable", "retryPolicy"] : [],
|
|
3477
3512
|
"storeId",
|
|
3478
3513
|
"channelKey",
|
|
3479
3514
|
"paymentId",
|
|
@@ -3488,6 +3523,11 @@ function validateNextAction(value, provider, resource, path) {
|
|
|
3488
3523
|
path
|
|
3489
3524
|
);
|
|
3490
3525
|
if (action.version !== "v2") fail(resource, `${path}.version`, "v2");
|
|
3526
|
+
if (hasCancelable && action.cancelable !== false)
|
|
3527
|
+
fail(resource, `${path}.cancelable`, "false");
|
|
3528
|
+
if (hasRetryPolicy && action.retryPolicy !== "same_action_only") {
|
|
3529
|
+
fail(resource, `${path}.retryPolicy`, "same_action_only");
|
|
3530
|
+
}
|
|
3491
3531
|
for (const key of ["storeId", "channelKey"]) {
|
|
3492
3532
|
boundedString(action[key], 255, resource, `${path}.${key}`);
|
|
3493
3533
|
}
|
|
@@ -3534,6 +3574,10 @@ function validateNextAction(value, provider, resource, path) {
|
|
|
3534
3574
|
"HTTPS or loopback URL without embedded credentials"
|
|
3535
3575
|
);
|
|
3536
3576
|
}
|
|
3577
|
+
if (!hasCancelable) {
|
|
3578
|
+
action.cancelable = false;
|
|
3579
|
+
action.retryPolicy = "same_action_only";
|
|
3580
|
+
}
|
|
3537
3581
|
return;
|
|
3538
3582
|
}
|
|
3539
3583
|
exact(action, ["type", "checkoutUrl"], [], resource, path);
|
|
@@ -4268,8 +4312,8 @@ var CartApi = class extends CustomerScopedApi {
|
|
|
4268
4312
|
endpoint(key) {
|
|
4269
4313
|
return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
|
|
4270
4314
|
}
|
|
4271
|
-
execute(
|
|
4272
|
-
return this.requestEndpoint(
|
|
4315
|
+
execute(endpoint, body, idempotencyKey) {
|
|
4316
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4273
4317
|
...idempotencyKey && {
|
|
4274
4318
|
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4275
4319
|
}
|
|
@@ -4286,26 +4330,26 @@ var CartApi = class extends CustomerScopedApi {
|
|
|
4286
4330
|
);
|
|
4287
4331
|
}
|
|
4288
4332
|
mine(params = {}) {
|
|
4289
|
-
const
|
|
4290
|
-
return this.execute(
|
|
4333
|
+
const endpoint = this.endpoint("mine");
|
|
4334
|
+
return this.execute(endpoint, params).then(
|
|
4291
4335
|
(value) => validateCartMineResult(value)
|
|
4292
4336
|
);
|
|
4293
4337
|
}
|
|
4294
4338
|
merge(params) {
|
|
4295
4339
|
const { idempotencyKey, ...body } = params;
|
|
4296
4340
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4297
|
-
const
|
|
4298
|
-
return this.execute(
|
|
4341
|
+
const endpoint = this.endpoint("merge");
|
|
4342
|
+
return this.execute(endpoint, body, idempotencyKey).then(
|
|
4299
4343
|
(value) => validateCartMergeResult(value)
|
|
4300
4344
|
);
|
|
4301
4345
|
}
|
|
4302
4346
|
addItem(params) {
|
|
4303
4347
|
return this.mutate(this.endpoint("addItem"), params);
|
|
4304
4348
|
}
|
|
4305
|
-
mutate(
|
|
4349
|
+
mutate(endpoint, params) {
|
|
4306
4350
|
const { idempotencyKey, ...body } = params;
|
|
4307
4351
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4308
|
-
return this.execute(
|
|
4352
|
+
return this.execute(endpoint, body, idempotencyKey).then(
|
|
4309
4353
|
(value) => validateCartMutationResult(value)
|
|
4310
4354
|
);
|
|
4311
4355
|
}
|
|
@@ -4331,8 +4375,8 @@ var CheckoutApi = class extends CustomerScopedApi {
|
|
|
4331
4375
|
constructor(options) {
|
|
4332
4376
|
super("CheckoutApi", { ...options, requiresCredential: false });
|
|
4333
4377
|
}
|
|
4334
|
-
post(
|
|
4335
|
-
return this.requestEndpoint(
|
|
4378
|
+
post(endpoint, body, idempotencyKey) {
|
|
4379
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4336
4380
|
...idempotencyKey && {
|
|
4337
4381
|
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4338
4382
|
}
|
|
@@ -4399,11 +4443,15 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4399
4443
|
super("PaymentSessionApi", { ...options, requiresCredential: false });
|
|
4400
4444
|
this.serverTransport = Boolean(options.secretKey);
|
|
4401
4445
|
}
|
|
4402
|
-
post(
|
|
4403
|
-
|
|
4404
|
-
...idempotencyKey && {
|
|
4405
|
-
|
|
4446
|
+
post(endpoint, body, idempotencyKey, negotiateStandardActionCapabilities = false) {
|
|
4447
|
+
const headers = {
|
|
4448
|
+
...idempotencyKey && { "X-Idempotency-Key": idempotencyKey },
|
|
4449
|
+
...negotiateStandardActionCapabilities && {
|
|
4450
|
+
Accept: PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE
|
|
4406
4451
|
}
|
|
4452
|
+
};
|
|
4453
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4454
|
+
...Object.keys(headers).length > 0 && { headers }
|
|
4407
4455
|
});
|
|
4408
4456
|
}
|
|
4409
4457
|
async paymentSession(result, expectedProvider) {
|
|
@@ -4428,40 +4476,41 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4428
4476
|
this.post(
|
|
4429
4477
|
this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
|
|
4430
4478
|
body,
|
|
4431
|
-
idempotencyKey
|
|
4479
|
+
idempotencyKey,
|
|
4480
|
+
body.providerOptions.profile === "standard_v2"
|
|
4432
4481
|
),
|
|
4433
4482
|
"portone"
|
|
4434
4483
|
);
|
|
4435
4484
|
}
|
|
4436
4485
|
retrieve(params) {
|
|
4437
|
-
const
|
|
4486
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
4438
4487
|
return this.paymentSession(
|
|
4439
|
-
this.post(
|
|
4488
|
+
this.post(endpoint, params),
|
|
4440
4489
|
"toss"
|
|
4441
4490
|
);
|
|
4442
4491
|
}
|
|
4443
4492
|
retrievePortOne(params) {
|
|
4444
|
-
const
|
|
4493
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
4445
4494
|
return this.paymentSession(
|
|
4446
|
-
this.post(
|
|
4495
|
+
this.post(endpoint, params, void 0, true),
|
|
4447
4496
|
"portone"
|
|
4448
4497
|
);
|
|
4449
4498
|
}
|
|
4450
4499
|
cancel(params) {
|
|
4451
4500
|
const { idempotencyKey, ...body } = params;
|
|
4452
4501
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4453
|
-
const
|
|
4502
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4454
4503
|
return this.paymentSession(
|
|
4455
|
-
this.post(
|
|
4504
|
+
this.post(endpoint, body, idempotencyKey),
|
|
4456
4505
|
"toss"
|
|
4457
4506
|
);
|
|
4458
4507
|
}
|
|
4459
4508
|
cancelPortOne(params) {
|
|
4460
4509
|
const { idempotencyKey, ...body } = params;
|
|
4461
4510
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4462
|
-
const
|
|
4511
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4463
4512
|
return this.paymentSession(
|
|
4464
|
-
this.post(
|
|
4513
|
+
this.post(endpoint, body, idempotencyKey),
|
|
4465
4514
|
"portone"
|
|
4466
4515
|
);
|
|
4467
4516
|
}
|
|
@@ -4540,9 +4589,9 @@ function resolveVariantImageItems(variant, poolById) {
|
|
|
4540
4589
|
if (pooled) resolved.push(pooled);
|
|
4541
4590
|
continue;
|
|
4542
4591
|
}
|
|
4543
|
-
const
|
|
4544
|
-
if (
|
|
4545
|
-
const pooled = poolById.get(
|
|
4592
|
+
const mediaId = getMediaId(entry);
|
|
4593
|
+
if (mediaId) {
|
|
4594
|
+
const pooled = poolById.get(mediaId);
|
|
4546
4595
|
if (pooled) {
|
|
4547
4596
|
resolved.push(pooled);
|
|
4548
4597
|
}
|
|
@@ -4733,11 +4782,11 @@ function getFirstMediaId(values) {
|
|
|
4733
4782
|
}
|
|
4734
4783
|
return null;
|
|
4735
4784
|
}
|
|
4736
|
-
function inProductMediaPool(product,
|
|
4737
|
-
if (
|
|
4785
|
+
function inProductMediaPool(product, mediaId) {
|
|
4786
|
+
if (mediaId == null) return null;
|
|
4738
4787
|
const images = Array.isArray(product?.images) ? product.images : [];
|
|
4739
4788
|
for (const image of images) {
|
|
4740
|
-
if (extractEntityId(image) ===
|
|
4789
|
+
if (extractEntityId(image) === mediaId) return mediaId;
|
|
4741
4790
|
}
|
|
4742
4791
|
return null;
|
|
4743
4792
|
}
|
|
@@ -6318,8 +6367,8 @@ function isProductUpsertFieldValidationErrorBody(value) {
|
|
|
6318
6367
|
|
|
6319
6368
|
// src/core/commerce/commerce-client.ts
|
|
6320
6369
|
var BrowserCommerceApi = class extends CustomerScopedApi {
|
|
6321
|
-
requestEndpoint(
|
|
6322
|
-
return super.requestEndpoint(
|
|
6370
|
+
requestEndpoint(endpoint, body, options) {
|
|
6371
|
+
return super.requestEndpoint(endpoint, body, options);
|
|
6323
6372
|
}
|
|
6324
6373
|
};
|
|
6325
6374
|
var CommerceClient = class {
|
|
@@ -6519,11 +6568,11 @@ var EventsClient = class {
|
|
|
6519
6568
|
{ useCustomerAuth: false }
|
|
6520
6569
|
);
|
|
6521
6570
|
}
|
|
6522
|
-
async execute(
|
|
6571
|
+
async execute(endpoint, method, body, options = {}) {
|
|
6523
6572
|
const useCustomerAuth = options.useCustomerAuth === true;
|
|
6524
6573
|
const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
|
|
6525
6574
|
try {
|
|
6526
|
-
const response = await httpFetch(
|
|
6575
|
+
const response = await httpFetch(endpoint, {
|
|
6527
6576
|
method,
|
|
6528
6577
|
apiUrl: this.apiUrl,
|
|
6529
6578
|
publishableKey: this.publishableKey,
|
|
@@ -6532,7 +6581,7 @@ var EventsClient = class {
|
|
|
6532
6581
|
...body !== void 0 && { body: JSON.stringify(body) }
|
|
6533
6582
|
});
|
|
6534
6583
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
6535
|
-
return parseApiResponse(response,
|
|
6584
|
+
return parseApiResponse(response, endpoint);
|
|
6536
6585
|
} catch (err) {
|
|
6537
6586
|
const id = err instanceof SDKError ? err.requestId ?? null : null;
|
|
6538
6587
|
this.onRequestId?.(id);
|
|
@@ -6790,13 +6839,106 @@ function mergeProductDetailWithStock(catalog, snapshot) {
|
|
|
6790
6839
|
};
|
|
6791
6840
|
}
|
|
6792
6841
|
|
|
6842
|
+
// src/core/webhook/validation.ts
|
|
6843
|
+
function isValidWebhookEventData(data) {
|
|
6844
|
+
if (typeof data !== "object" || data === null) return false;
|
|
6845
|
+
const event = data;
|
|
6846
|
+
return typeof event.collection === "string" && typeof event.operation === "string" && event.operation.length > 0 && typeof event.data === "object" && event.data !== null;
|
|
6847
|
+
}
|
|
6848
|
+
|
|
6849
|
+
// src/core/webhook/receiver.ts
|
|
6850
|
+
async function verifySignature(rawBody, secret, signature, timestamp2, deliveryId) {
|
|
6851
|
+
const encoder = new TextEncoder();
|
|
6852
|
+
const signedPrefix = encoder.encode(`${timestamp2}.${deliveryId}.`);
|
|
6853
|
+
const signedPayload = new Uint8Array(signedPrefix.length + rawBody.length);
|
|
6854
|
+
signedPayload.set(signedPrefix);
|
|
6855
|
+
signedPayload.set(rawBody, signedPrefix.length);
|
|
6856
|
+
const key = await crypto.subtle.importKey(
|
|
6857
|
+
"raw",
|
|
6858
|
+
encoder.encode(secret),
|
|
6859
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
6860
|
+
false,
|
|
6861
|
+
["verify"]
|
|
6862
|
+
);
|
|
6863
|
+
if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
|
|
6864
|
+
return false;
|
|
6865
|
+
}
|
|
6866
|
+
const sigBytes = new Uint8Array(
|
|
6867
|
+
(signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
|
|
6868
|
+
);
|
|
6869
|
+
return crypto.subtle.verify("HMAC", key, sigBytes, signedPayload);
|
|
6870
|
+
}
|
|
6871
|
+
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6872
|
+
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6873
|
+
const timestampMs = Number(timestamp2);
|
|
6874
|
+
if (!Number.isFinite(timestampMs)) return false;
|
|
6875
|
+
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
6876
|
+
return skewMs <= toleranceSeconds * 1e3;
|
|
6877
|
+
}
|
|
6878
|
+
var MAX_TOLERANCE_SECONDS = 86400;
|
|
6879
|
+
function toleranceIsValid(toleranceSeconds) {
|
|
6880
|
+
return typeof toleranceSeconds === "number" && Number.isFinite(toleranceSeconds) && toleranceSeconds >= 0 && toleranceSeconds <= MAX_TOLERANCE_SECONDS;
|
|
6881
|
+
}
|
|
6882
|
+
async function processWebhookRequest(request, handler, verify) {
|
|
6883
|
+
try {
|
|
6884
|
+
const rawBody = new Uint8Array(await request.arrayBuffer());
|
|
6885
|
+
const verificationFailure = await verify?.(rawBody);
|
|
6886
|
+
if (verificationFailure) return verificationFailure;
|
|
6887
|
+
const body = JSON.parse(new TextDecoder().decode(rawBody));
|
|
6888
|
+
if (!isValidWebhookEventData(body)) {
|
|
6889
|
+
return new Response(
|
|
6890
|
+
JSON.stringify({ error: "Invalid webhook event format" }),
|
|
6891
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
6892
|
+
);
|
|
6893
|
+
}
|
|
6894
|
+
await handler(body);
|
|
6895
|
+
return new Response(
|
|
6896
|
+
JSON.stringify({ success: true, message: "Webhook processed" }),
|
|
6897
|
+
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
6898
|
+
);
|
|
6899
|
+
} catch (error) {
|
|
6900
|
+
console.error("Webhook processing error:", error);
|
|
6901
|
+
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
6902
|
+
status: 500,
|
|
6903
|
+
headers: { "Content-Type": "application/json" }
|
|
6904
|
+
});
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
async function handleSignedWebhook(request, handler, options) {
|
|
6908
|
+
const secret = options?.secret;
|
|
6909
|
+
const configuredTolerance = options?.toleranceSeconds;
|
|
6910
|
+
const toleranceSeconds = configuredTolerance ?? 300;
|
|
6911
|
+
if (typeof secret !== "string" || secret.trim().length === 0) {
|
|
6912
|
+
return new Response(
|
|
6913
|
+
JSON.stringify({ error: "Webhook signing secret is not configured" }),
|
|
6914
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
6915
|
+
);
|
|
6916
|
+
}
|
|
6917
|
+
if (!toleranceIsValid(toleranceSeconds)) {
|
|
6918
|
+
return new Response(
|
|
6919
|
+
JSON.stringify({ error: "Webhook signature tolerance is not valid" }),
|
|
6920
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
6921
|
+
);
|
|
6922
|
+
}
|
|
6923
|
+
return processWebhookRequest(request, handler, async (rawBody) => {
|
|
6924
|
+
const signature = request.headers.get("x-webhook-signature") || "";
|
|
6925
|
+
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
6926
|
+
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
6927
|
+
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(rawBody, secret, signature, timestamp2, deliveryId);
|
|
6928
|
+
if (!valid) {
|
|
6929
|
+
return new Response(
|
|
6930
|
+
JSON.stringify({ error: "Invalid webhook signature" }),
|
|
6931
|
+
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
6932
|
+
);
|
|
6933
|
+
}
|
|
6934
|
+
});
|
|
6935
|
+
}
|
|
6936
|
+
|
|
6793
6937
|
// src/core/webhook/index.ts
|
|
6794
6938
|
var ORDER_CHANGED_EVENT_TYPE = "collection.orderChanged";
|
|
6795
6939
|
var COMMERCE_NOTIFICATION_EVENT_TYPE = "commerce.notification";
|
|
6796
6940
|
function isValidWebhookEvent(data) {
|
|
6797
|
-
|
|
6798
|
-
const obj = data;
|
|
6799
|
-
return typeof obj.collection === "string" && typeof obj.operation === "string" && obj.operation.length > 0 && typeof obj.data === "object" && obj.data !== null;
|
|
6941
|
+
return isValidWebhookEventData(data);
|
|
6800
6942
|
}
|
|
6801
6943
|
var COMMERCE_NOTIFICATION_OPERATION = "notification";
|
|
6802
6944
|
var COMMERCE_NOTIFICATION_EVENTS = [
|
|
@@ -6808,7 +6950,9 @@ var COMMERCE_NOTIFICATION_EVENTS = [
|
|
|
6808
6950
|
"returnApproved",
|
|
6809
6951
|
"returnRejected",
|
|
6810
6952
|
"returnCanceled",
|
|
6811
|
-
"returnCompleted"
|
|
6953
|
+
"returnCompleted",
|
|
6954
|
+
"paymentReconciliationRequired",
|
|
6955
|
+
"paymentRefundRequiresAttention"
|
|
6812
6956
|
];
|
|
6813
6957
|
function isStringOrNumber(value) {
|
|
6814
6958
|
return typeof value === "string" || typeof value === "number";
|
|
@@ -6838,18 +6982,25 @@ function isCommerceNotificationEventName(value) {
|
|
|
6838
6982
|
return typeof value === "string" && COMMERCE_NOTIFICATION_EVENTS.includes(value);
|
|
6839
6983
|
}
|
|
6840
6984
|
function isCommerceNotificationSourceCollection(value) {
|
|
6841
|
-
return value === "orders" || value === "fulfillments" || value === "returns";
|
|
6985
|
+
return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts";
|
|
6842
6986
|
}
|
|
6843
6987
|
function isCommerceNotificationData(value) {
|
|
6844
6988
|
if (!isRecord(value)) return false;
|
|
6845
6989
|
if (value.source !== void 0 && (!isRecord(value.source) || !isCommerceNotificationSourceCollection(value.source.collection) || !isStringOrNumber(value.source.id))) {
|
|
6846
6990
|
return false;
|
|
6847
6991
|
}
|
|
6848
|
-
return (value.orderId === void 0 || isStringOrNumber(value.orderId)) && (value.orderNumber === void 0 || typeof value.orderNumber === "string") && (value.status === void 0 || typeof value.status === "string") && (value.totalAmount === void 0 || typeof value.totalAmount === "number") && (value.currency === void 0 || typeof value.currency === "string") && (value.fulfillmentId === void 0 || isStringOrNumber(value.fulfillmentId)) && (value.fulfillmentStatus === void 0 || typeof value.fulfillmentStatus === "string") && (value.shippedAt === void 0 || typeof value.shippedAt === "string") && (value.returnId === void 0 || isStringOrNumber(value.returnId)) && (value.returnStatus === void 0 || typeof value.returnStatus === "string") && (value.refundAmount === void 0 || typeof value.refundAmount === "number") && (value.completedAt === void 0 || typeof value.completedAt === "string");
|
|
6992
|
+
return (value.orderId === void 0 || isStringOrNumber(value.orderId)) && (value.orderNumber === void 0 || typeof value.orderNumber === "string") && (value.status === void 0 || typeof value.status === "string") && (value.totalAmount === void 0 || typeof value.totalAmount === "number") && (value.currency === void 0 || typeof value.currency === "string") && (value.fulfillmentId === void 0 || isStringOrNumber(value.fulfillmentId)) && (value.fulfillmentStatus === void 0 || typeof value.fulfillmentStatus === "string") && (value.shippedAt === void 0 || typeof value.shippedAt === "string") && (value.returnId === void 0 || isStringOrNumber(value.returnId)) && (value.returnStatus === void 0 || typeof value.returnStatus === "string") && (value.refundAmount === void 0 || typeof value.refundAmount === "number") && (value.completedAt === void 0 || typeof value.completedAt === "string") && (value.paymentSessionId === void 0 || typeof value.paymentSessionId === "string") && (value.checkoutId === void 0 || typeof value.checkoutId === "string") && (value.refundAttemptId === void 0 || typeof value.refundAttemptId === "string") && (value.reason === void 0 || typeof value.reason === "string") && (value.observedAt === void 0 || typeof value.observedAt === "string") && (value.providerObject === void 0 || isRecord(value.providerObject) && typeof value.providerObject.provider === "string" && (value.providerObject.kind === "payment" || value.providerObject.kind === "refund") && typeof value.providerObject.id === "string") && (value.money === void 0 || isRecord(value.money) && Number.isSafeInteger(value.money.amountMinor) && Number(value.money.amountMinor) > 0 && typeof value.money.currency === "string");
|
|
6849
6993
|
}
|
|
6850
6994
|
function isCommerceNotification(value) {
|
|
6851
6995
|
if (!isRecord(value)) return false;
|
|
6852
|
-
return isCommerceNotificationEventName(value.event) && typeof value.intentId === "string" && value.intentId.length > 0 && typeof value.dedupeKey === "string" && value.dedupeKey.length > 0 && (value.orderId === void 0 || typeof value.orderId === "string") && (value.fulfillmentId === void 0 || typeof value.fulfillmentId === "string") && (value.returnId === void 0 || typeof value.returnId === "string");
|
|
6996
|
+
return isCommerceNotificationEventName(value.event) && typeof value.intentId === "string" && value.intentId.length > 0 && typeof value.dedupeKey === "string" && value.dedupeKey.length > 0 && (value.orderId === void 0 || typeof value.orderId === "string") && (value.fulfillmentId === void 0 || typeof value.fulfillmentId === "string") && (value.returnId === void 0 || typeof value.returnId === "string") && (value.paymentSessionId === void 0 || typeof value.paymentSessionId === "string") && (value.refundAttemptId === void 0 || typeof value.refundAttemptId === "string");
|
|
6997
|
+
}
|
|
6998
|
+
function isPaymentIncidentNotificationData(value, event) {
|
|
6999
|
+
const reconciliation = event === "paymentReconciliationRequired";
|
|
7000
|
+
const expectedCollection = reconciliation ? "payment-sessions" : "payment-refund-attempts";
|
|
7001
|
+
const expectedStatus = reconciliation ? "reconciliation_required" : "requires_attention";
|
|
7002
|
+
const expectedReason = reconciliation ? "orderless_capture" : "local_commit_ambiguous";
|
|
7003
|
+
return value.source?.collection === expectedCollection && typeof value.source.id === "string" && value.source.id.length > 0 && typeof value.paymentSessionId === "string" && value.paymentSessionId.length > 0 && isRecord(value.providerObject) && typeof value.providerObject.provider === "string" && value.providerObject.provider.length > 0 && (value.providerObject.kind === "payment" || value.providerObject.kind === "refund") && typeof value.providerObject.id === "string" && value.providerObject.id.length > 0 && isRecord(value.money) && Number.isSafeInteger(value.money.amountMinor) && Number(value.money.amountMinor) > 0 && typeof value.money.currency === "string" && value.money.currency.length > 0 && value.status === expectedStatus && value.reason === expectedReason && typeof value.observedAt === "string" && value.observedAt.length > 0 && !Number.isNaN(Date.parse(value.observedAt)) && (value.checkoutId === void 0 || typeof value.checkoutId === "string" && value.checkoutId.length > 0) && (value.orderId === void 0 || typeof value.orderId === "string" && value.orderId.length > 0) && (reconciliation ? value.source.id === value.paymentSessionId && value.providerObject.kind === "payment" && value.refundAttemptId === void 0 : typeof value.refundAttemptId === "string" && value.refundAttemptId.length > 0 && value.source.id === value.refundAttemptId);
|
|
6853
7004
|
}
|
|
6854
7005
|
function isWebhookCommerceNotificationChange(value) {
|
|
6855
7006
|
if (!isRecord(value)) return false;
|
|
@@ -6890,6 +7041,15 @@ function isCommerceNotificationWebhookEvent(event) {
|
|
|
6890
7041
|
if (!matchesOptionalId(change.sourceId, sourceId)) return false;
|
|
6891
7042
|
}
|
|
6892
7043
|
const changeSourceId = isWebhookCommerceNotificationChange(change) ? change.sourceId : void 0;
|
|
7044
|
+
if (notification.event === "paymentReconciliationRequired" || notification.event === "paymentRefundRequiresAttention") {
|
|
7045
|
+
if (!isPaymentIncidentNotificationData(data, notification.event)) {
|
|
7046
|
+
return false;
|
|
7047
|
+
}
|
|
7048
|
+
const incidentData = data;
|
|
7049
|
+
const expectedCollection = notification.event === "paymentReconciliationRequired" ? "payment-sessions" : "payment-refund-attempts";
|
|
7050
|
+
const notificationSourceId = notification.event === "paymentReconciliationRequired" ? notification.paymentSessionId : notification.refundAttemptId;
|
|
7051
|
+
return sourceCollection === expectedCollection && typeof notification.paymentSessionId === "string" && notification.paymentSessionId === incidentData.paymentSessionId && typeof notificationSourceId === "string" && notificationSourceId === incidentData.source.id && matchesOptionalId(changeSourceId, incidentData.source.id);
|
|
7052
|
+
}
|
|
6893
7053
|
if (notification.event === "orderPaid" || notification.event === "orderCanceled" || notification.event === "orderDelivered") {
|
|
6894
7054
|
return sourceCollection === "orders" && typeof notification.orderId === "string" && notification.orderId.length > 0 && matchesOptionalId(data.orderId, sourceId) && matchesOptionalId(notification.orderId, sourceId) && matchesOptionalId(data.orderId, notification.orderId) && matchesOptionalId(changeSourceId, data.orderId ?? notification.orderId);
|
|
6895
7055
|
}
|
|
@@ -6958,80 +7118,8 @@ function createCustomerAuthWebhookHandler(handlers) {
|
|
|
6958
7118
|
await handlers.unhandled?.(event);
|
|
6959
7119
|
};
|
|
6960
7120
|
}
|
|
6961
|
-
async function verifySignature(payload, secret, signature, timestamp2, deliveryId) {
|
|
6962
|
-
const encoder = new TextEncoder();
|
|
6963
|
-
const key = await crypto.subtle.importKey(
|
|
6964
|
-
"raw",
|
|
6965
|
-
encoder.encode(secret),
|
|
6966
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
6967
|
-
false,
|
|
6968
|
-
["verify"]
|
|
6969
|
-
);
|
|
6970
|
-
if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
|
|
6971
|
-
return false;
|
|
6972
|
-
}
|
|
6973
|
-
const sigBytes = new Uint8Array(
|
|
6974
|
-
(signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
|
|
6975
|
-
);
|
|
6976
|
-
return crypto.subtle.verify(
|
|
6977
|
-
"HMAC",
|
|
6978
|
-
key,
|
|
6979
|
-
sigBytes,
|
|
6980
|
-
encoder.encode(`${timestamp2}.${deliveryId}.${payload}`)
|
|
6981
|
-
);
|
|
6982
|
-
}
|
|
6983
|
-
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6984
|
-
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6985
|
-
const timestampMs = Number(timestamp2);
|
|
6986
|
-
if (!Number.isFinite(timestampMs)) return false;
|
|
6987
|
-
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
6988
|
-
return skewMs <= toleranceSeconds * 1e3;
|
|
6989
|
-
}
|
|
6990
7121
|
async function handleWebhook(request, handler, options) {
|
|
6991
|
-
|
|
6992
|
-
const rawBody = await request.text();
|
|
6993
|
-
if (options?.secret) {
|
|
6994
|
-
const signature = request.headers.get("x-webhook-signature") || "";
|
|
6995
|
-
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
6996
|
-
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
6997
|
-
const toleranceSeconds = options.toleranceSeconds ?? 300;
|
|
6998
|
-
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(
|
|
6999
|
-
rawBody,
|
|
7000
|
-
options.secret,
|
|
7001
|
-
signature,
|
|
7002
|
-
timestamp2,
|
|
7003
|
-
deliveryId
|
|
7004
|
-
);
|
|
7005
|
-
if (!valid) {
|
|
7006
|
-
return new Response(
|
|
7007
|
-
JSON.stringify({ error: "Invalid webhook signature" }),
|
|
7008
|
-
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
7009
|
-
);
|
|
7010
|
-
}
|
|
7011
|
-
} else {
|
|
7012
|
-
console.warn(
|
|
7013
|
-
"[@01.software/sdk] Webhook signature verification is disabled. Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification."
|
|
7014
|
-
);
|
|
7015
|
-
}
|
|
7016
|
-
const body = JSON.parse(rawBody);
|
|
7017
|
-
if (!isValidWebhookEvent(body)) {
|
|
7018
|
-
return new Response(
|
|
7019
|
-
JSON.stringify({ error: "Invalid webhook event format" }),
|
|
7020
|
-
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
7021
|
-
);
|
|
7022
|
-
}
|
|
7023
|
-
await handler(body);
|
|
7024
|
-
return new Response(
|
|
7025
|
-
JSON.stringify({ success: true, message: "Webhook processed" }),
|
|
7026
|
-
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
7027
|
-
);
|
|
7028
|
-
} catch (error) {
|
|
7029
|
-
console.error("Webhook processing error:", error);
|
|
7030
|
-
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
7031
|
-
status: 500,
|
|
7032
|
-
headers: { "Content-Type": "application/json" }
|
|
7033
|
-
});
|
|
7034
|
-
}
|
|
7122
|
+
return handleSignedWebhook(request, handler, options);
|
|
7035
7123
|
}
|
|
7036
7124
|
function createTypedWebhookHandler(collection, handler) {
|
|
7037
7125
|
return async (event) => {
|
|
@@ -7071,6 +7159,7 @@ var INTERNAL_COLLECTIONS = [
|
|
|
7071
7159
|
"payment-event-inbox",
|
|
7072
7160
|
"payment-refund-attempts",
|
|
7073
7161
|
"portone-payment-interactions",
|
|
7162
|
+
"commerce-payment-webhook-routes",
|
|
7074
7163
|
"commerce-notification-intents",
|
|
7075
7164
|
"commerce-idempotency-records",
|
|
7076
7165
|
"product-collection-items",
|
|
@@ -7111,7 +7200,6 @@ var COLLECTIONS = [
|
|
|
7111
7200
|
"brands",
|
|
7112
7201
|
"customer-profiles",
|
|
7113
7202
|
"customer-profile-stats",
|
|
7114
|
-
"discounts",
|
|
7115
7203
|
"shipping-policies",
|
|
7116
7204
|
"shipping-zones",
|
|
7117
7205
|
"documents",
|
|
@@ -7187,6 +7275,9 @@ var SERVER_ONLY_COLLECTIONS = [
|
|
|
7187
7275
|
"cart-items",
|
|
7188
7276
|
"checkouts",
|
|
7189
7277
|
"checkout-items",
|
|
7278
|
+
// Raw discount definitions require a server credential. Browser discount
|
|
7279
|
+
// validation is exposed through the shaped POST /api/discounts/validate path.
|
|
7280
|
+
"discounts",
|
|
7190
7281
|
"draft-orders",
|
|
7191
7282
|
"draft-order-items",
|
|
7192
7283
|
"posts",
|
|
@@ -7352,160 +7443,6 @@ var RealtimeConnection = class {
|
|
|
7352
7443
|
}
|
|
7353
7444
|
};
|
|
7354
7445
|
|
|
7355
|
-
// src/utils/product-media.ts
|
|
7356
|
-
function mediaPointerOptionValues(values) {
|
|
7357
|
-
return (values ?? []).filter((value) => value != null && value !== "").map((value) => ({
|
|
7358
|
-
swatch: {
|
|
7359
|
-
type: "media",
|
|
7360
|
-
mediaItemId: value
|
|
7361
|
-
}
|
|
7362
|
-
}));
|
|
7363
|
-
}
|
|
7364
|
-
function resolveProductMedia(input) {
|
|
7365
|
-
const resolved = resolveProductSelectionMedia({
|
|
7366
|
-
...input,
|
|
7367
|
-
selectedVariant: input.selectedVariant ?? (input.variantFeaturedMediaItemId ? { images: [input.variantFeaturedMediaItemId] } : null),
|
|
7368
|
-
selectedOptionValues: input.selectedOptionValues ?? mediaPointerOptionValues(input.selectedOptionValueMediaItemIds)
|
|
7369
|
-
});
|
|
7370
|
-
if (resolved.source !== "none") {
|
|
7371
|
-
return {
|
|
7372
|
-
...resolved,
|
|
7373
|
-
source: resolved.source === "variant_media_selected" ? "variant_featured" : resolved.source
|
|
7374
|
-
};
|
|
7375
|
-
}
|
|
7376
|
-
const display = resolveProductDisplayMedia({
|
|
7377
|
-
productMediaPool: input.productMediaPool
|
|
7378
|
-
});
|
|
7379
|
-
return {
|
|
7380
|
-
primaryImage: display.primaryImage,
|
|
7381
|
-
images: display.images,
|
|
7382
|
-
source: display.source
|
|
7383
|
-
};
|
|
7384
|
-
}
|
|
7385
|
-
|
|
7386
|
-
// src/utils/product-gallery.ts
|
|
7387
|
-
function mediaId(value) {
|
|
7388
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
7389
|
-
return String(value);
|
|
7390
|
-
}
|
|
7391
|
-
if (typeof value === "object" && value !== null && "id" in value) {
|
|
7392
|
-
const id = value.id;
|
|
7393
|
-
if (typeof id === "string" || typeof id === "number") return String(id);
|
|
7394
|
-
}
|
|
7395
|
-
return null;
|
|
7396
|
-
}
|
|
7397
|
-
function relationshipIds(values) {
|
|
7398
|
-
if (!Array.isArray(values)) return [];
|
|
7399
|
-
return values.map((value) => mediaId(value)).filter((value) => Boolean(value));
|
|
7400
|
-
}
|
|
7401
|
-
function buildPoolById2(pool) {
|
|
7402
|
-
const poolById = /* @__PURE__ */ new Map();
|
|
7403
|
-
for (const item of pool) {
|
|
7404
|
-
const id = mediaId(item);
|
|
7405
|
-
if (id) poolById.set(id, item);
|
|
7406
|
-
}
|
|
7407
|
-
return poolById;
|
|
7408
|
-
}
|
|
7409
|
-
function mediaSetItemsInPool(mediaSet, poolById) {
|
|
7410
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7411
|
-
const items = [];
|
|
7412
|
-
const primaryId = mediaId(mediaSet.primaryMediaItemId);
|
|
7413
|
-
if (primaryId) {
|
|
7414
|
-
const primary = poolById.get(primaryId);
|
|
7415
|
-
if (primary) {
|
|
7416
|
-
seen.add(primaryId);
|
|
7417
|
-
items.push(primary);
|
|
7418
|
-
}
|
|
7419
|
-
}
|
|
7420
|
-
for (const itemId of relationshipIds(mediaSet.items)) {
|
|
7421
|
-
if (seen.has(itemId)) continue;
|
|
7422
|
-
const item = poolById.get(itemId);
|
|
7423
|
-
if (!item) continue;
|
|
7424
|
-
seen.add(itemId);
|
|
7425
|
-
items.push(item);
|
|
7426
|
-
}
|
|
7427
|
-
return items;
|
|
7428
|
-
}
|
|
7429
|
-
function resolveLegacyMediaSet(input) {
|
|
7430
|
-
if (!Array.isArray(input.mediaSets)) return null;
|
|
7431
|
-
const pool = input.productMediaPool ?? input.pool ?? [];
|
|
7432
|
-
const poolById = buildPoolById2(pool);
|
|
7433
|
-
const selectedVariantId = mediaId(input.selectedVariantId);
|
|
7434
|
-
if (selectedVariantId) {
|
|
7435
|
-
const exactSet = input.mediaSets.find(
|
|
7436
|
-
(set) => set.matchType === "exact-variant" && relationshipIds(set.variantIds).includes(selectedVariantId)
|
|
7437
|
-
);
|
|
7438
|
-
if (exactSet) {
|
|
7439
|
-
const images = mediaSetItemsInPool(exactSet, poolById);
|
|
7440
|
-
if (images.length > 0) {
|
|
7441
|
-
return {
|
|
7442
|
-
primaryImage: images[0] ?? null,
|
|
7443
|
-
images,
|
|
7444
|
-
source: "exact_variant_set"
|
|
7445
|
-
};
|
|
7446
|
-
}
|
|
7447
|
-
}
|
|
7448
|
-
}
|
|
7449
|
-
const selectedOptionValueIds = new Set(
|
|
7450
|
-
relationshipIds(input.selectedOptionValueIds)
|
|
7451
|
-
);
|
|
7452
|
-
const optionSetMatches = input.mediaSets.filter((set) => set.matchType === "option-values").map((set) => {
|
|
7453
|
-
const optionValueIds = relationshipIds(set.optionValueIds);
|
|
7454
|
-
if (optionValueIds.length === 0) return null;
|
|
7455
|
-
if (!optionValueIds.every((id) => selectedOptionValueIds.has(id))) {
|
|
7456
|
-
return null;
|
|
7457
|
-
}
|
|
7458
|
-
const images = mediaSetItemsInPool(set, poolById);
|
|
7459
|
-
if (images.length === 0) return null;
|
|
7460
|
-
return { optionValueCount: optionValueIds.length, images };
|
|
7461
|
-
}).filter(
|
|
7462
|
-
(match) => Boolean(match)
|
|
7463
|
-
).sort((a, b) => b.optionValueCount - a.optionValueCount);
|
|
7464
|
-
if (optionSetMatches.length > 0) {
|
|
7465
|
-
const images = optionSetMatches[0].images;
|
|
7466
|
-
return {
|
|
7467
|
-
primaryImage: images[0] ?? null,
|
|
7468
|
-
images,
|
|
7469
|
-
source: "option_value_set"
|
|
7470
|
-
};
|
|
7471
|
-
}
|
|
7472
|
-
const defaultSet = input.mediaSets.find((set) => set.matchType === "default");
|
|
7473
|
-
if (defaultSet) {
|
|
7474
|
-
const images = mediaSetItemsInPool(defaultSet, poolById);
|
|
7475
|
-
if (images.length > 0) {
|
|
7476
|
-
return {
|
|
7477
|
-
primaryImage: images[0] ?? null,
|
|
7478
|
-
images,
|
|
7479
|
-
source: "default_set"
|
|
7480
|
-
};
|
|
7481
|
-
}
|
|
7482
|
-
}
|
|
7483
|
-
return {
|
|
7484
|
-
primaryImage: null,
|
|
7485
|
-
images: [],
|
|
7486
|
-
source: "none"
|
|
7487
|
-
};
|
|
7488
|
-
}
|
|
7489
|
-
function resolveProductGallery(input) {
|
|
7490
|
-
const selectedVariantId = mediaId(input.selectedVariantId);
|
|
7491
|
-
const selectedOptionValueIds = relationshipIds(input.selectedOptionValueIds);
|
|
7492
|
-
const selection = resolveProductSelectionMedia({
|
|
7493
|
-
...input,
|
|
7494
|
-
productMediaPool: input.productMediaPool ?? input.pool ?? null,
|
|
7495
|
-
selectedVariant: input.selectedVariant ?? (selectedVariantId ? { id: selectedVariantId } : null),
|
|
7496
|
-
selectedOptionValues: input.selectedOptionValues ?? selectedOptionValueIds.map((id) => ({ id }))
|
|
7497
|
-
});
|
|
7498
|
-
if (selection.source !== "none") {
|
|
7499
|
-
return selection;
|
|
7500
|
-
}
|
|
7501
|
-
const legacyResolved = resolveLegacyMediaSet(input);
|
|
7502
|
-
if (legacyResolved && legacyResolved.source !== "none") return legacyResolved;
|
|
7503
|
-
return resolveProductDisplayMedia({
|
|
7504
|
-
productMediaPool: input.productMediaPool ?? input.pool ?? null,
|
|
7505
|
-
featuredImage: input.featuredImage
|
|
7506
|
-
});
|
|
7507
|
-
}
|
|
7508
|
-
|
|
7509
7446
|
// src/utils/image.ts
|
|
7510
7447
|
var IMAGE_SIZES = [200, 400, 800, 1200, 1600];
|
|
7511
7448
|
function imageSizeCandidates(sizes) {
|
|
@@ -7637,7 +7574,7 @@ function createAnalytics(config) {
|
|
|
7637
7574
|
}, destroy() {
|
|
7638
7575
|
} };
|
|
7639
7576
|
}
|
|
7640
|
-
const
|
|
7577
|
+
const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
|
|
7641
7578
|
const respectDnt = config.respectDnt !== false;
|
|
7642
7579
|
function isDntActive() {
|
|
7643
7580
|
if (!respectDnt) return false;
|
|
@@ -7678,10 +7615,10 @@ function createAnalytics(config) {
|
|
|
7678
7615
|
try {
|
|
7679
7616
|
if (typeof navigator.sendBeacon === "function") {
|
|
7680
7617
|
const blob = new Blob([body], { type: "text/plain" });
|
|
7681
|
-
const sent = navigator.sendBeacon(
|
|
7618
|
+
const sent = navigator.sendBeacon(endpoint, blob);
|
|
7682
7619
|
if (sent) return;
|
|
7683
7620
|
}
|
|
7684
|
-
fetch(
|
|
7621
|
+
fetch(endpoint, {
|
|
7685
7622
|
method: "POST",
|
|
7686
7623
|
keepalive: true,
|
|
7687
7624
|
headers: { "Content-Type": "application/json" },
|