@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.js
CHANGED
|
@@ -97,6 +97,7 @@ var COMMERCE_ERROR_CODES = [
|
|
|
97
97
|
"payment_session_not_cancelable",
|
|
98
98
|
"payment_session_conflict",
|
|
99
99
|
"provider_identity_mismatch",
|
|
100
|
+
"managed_refund_attestation_forbidden",
|
|
100
101
|
"payment_method_unavailable",
|
|
101
102
|
"provider_unavailable",
|
|
102
103
|
"lock_timeout",
|
|
@@ -639,11 +640,11 @@ function parseRetryAfter(response) {
|
|
|
639
640
|
permitsAutomaticRetry: seconds <= MAX_AUTOMATIC_RETRY_AFTER_SECONDS
|
|
640
641
|
};
|
|
641
642
|
}
|
|
642
|
-
function mapResponseToError(status, parsed, details, requestId, retryAfter,
|
|
643
|
+
function mapResponseToError(status, parsed, details, requestId, retryAfter, canonicalCommerceError) {
|
|
643
644
|
const errorDetails = {
|
|
644
645
|
...details,
|
|
645
646
|
...parsed.errors && { errors: parsed.errors },
|
|
646
|
-
|
|
647
|
+
...!canonicalCommerceError && parsed.body && { body: parsed.body }
|
|
647
648
|
};
|
|
648
649
|
const suggestion = getParsedErrorSuggestion(status, parsed);
|
|
649
650
|
const finalize = (error) => {
|
|
@@ -651,7 +652,7 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, erro
|
|
|
651
652
|
if (retryAfter !== void 0) {
|
|
652
653
|
Object.assign(withRequestId, { retryAfter });
|
|
653
654
|
}
|
|
654
|
-
return
|
|
655
|
+
return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(withRequestId, parsed.reason);
|
|
655
656
|
};
|
|
656
657
|
if (status === 400 || status === 422) {
|
|
657
658
|
return finalize(
|
|
@@ -757,6 +758,7 @@ async function httpFetch(url, options) {
|
|
|
757
758
|
retry,
|
|
758
759
|
onUnauthorized,
|
|
759
760
|
errorFamily,
|
|
761
|
+
typedCommerceErrorReasons,
|
|
760
762
|
...requestInit
|
|
761
763
|
} = options || {};
|
|
762
764
|
const baseUrl = resolveApiUrl(apiUrl);
|
|
@@ -810,7 +812,8 @@ async function httpFetch(url, options) {
|
|
|
810
812
|
});
|
|
811
813
|
if (!response.ok) {
|
|
812
814
|
const parsed = await parseErrorBody(response);
|
|
813
|
-
const
|
|
815
|
+
const canonicalCommerceError = errorFamily === "commerce" || typeof parsed.reason === "string" && typedCommerceErrorReasons?.includes(parsed.reason) === true;
|
|
816
|
+
const commerceEnvelope = canonicalCommerceError ? parseCommerceErrorEnvelope(parsed.body, requestId) : void 0;
|
|
814
817
|
if (isUsageLimitExceededResponse(response)) {
|
|
815
818
|
const limit = parseInt(
|
|
816
819
|
response.headers.get("X-Usage-Limit") || "0",
|
|
@@ -838,7 +841,7 @@ async function httpFetch(url, options) {
|
|
|
838
841
|
),
|
|
839
842
|
requestId
|
|
840
843
|
);
|
|
841
|
-
throw
|
|
844
|
+
throw canonicalCommerceError ? enhanceCommerceError(usageError, parsed.body, requestId) : enhanceNonCommerceError(usageError, parsed.reason);
|
|
842
845
|
}
|
|
843
846
|
if (response.status === 401 && onUnauthorized && customerToken && !hasRetried401 && (commerceEnvelope?.reason ?? parsed.reason) === "token_expired") {
|
|
844
847
|
hasRetried401 = true;
|
|
@@ -863,7 +866,7 @@ async function httpFetch(url, options) {
|
|
|
863
866
|
details,
|
|
864
867
|
requestId,
|
|
865
868
|
retryAfter.seconds,
|
|
866
|
-
|
|
869
|
+
canonicalCommerceError
|
|
867
870
|
);
|
|
868
871
|
const method2 = (requestInit.method || "GET").toUpperCase();
|
|
869
872
|
const isTerminal = error instanceof RateLimitError || error instanceof UsageLimitError;
|
|
@@ -1041,15 +1044,15 @@ var HttpClient = class {
|
|
|
1041
1044
|
throw err;
|
|
1042
1045
|
}
|
|
1043
1046
|
}
|
|
1044
|
-
buildUrl(
|
|
1045
|
-
if (!options) return
|
|
1047
|
+
buildUrl(endpoint, options) {
|
|
1048
|
+
if (!options) return endpoint;
|
|
1046
1049
|
const { fallbackLocale, ...rest } = options;
|
|
1047
1050
|
const queryOptions = fallbackLocale === void 0 ? rest : {
|
|
1048
1051
|
...rest,
|
|
1049
1052
|
"fallback-locale": fallbackLocale === false ? "none" : fallbackLocale
|
|
1050
1053
|
};
|
|
1051
1054
|
const queryString = stringify(queryOptions, { addQueryPrefix: true });
|
|
1052
|
-
return queryString ? `${
|
|
1055
|
+
return queryString ? `${endpoint}${queryString}` : endpoint;
|
|
1053
1056
|
}
|
|
1054
1057
|
assertJsonResponse(response) {
|
|
1055
1058
|
const contentType = response.headers.get("content-type");
|
|
@@ -1198,39 +1201,39 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1198
1201
|
from(collection) {
|
|
1199
1202
|
return new ReadOnlyCollectionQueryBuilder(this, collection);
|
|
1200
1203
|
}
|
|
1201
|
-
async requestFind(
|
|
1202
|
-
const url = this.buildUrl(
|
|
1204
|
+
async requestFind(endpoint, options) {
|
|
1205
|
+
const url = this.buildUrl(endpoint, options);
|
|
1203
1206
|
const response = await this.fetchWithTracking(url, {
|
|
1204
1207
|
...this.defaultOptions,
|
|
1205
1208
|
method: "GET"
|
|
1206
1209
|
});
|
|
1207
1210
|
return this.parseFindResponse(response);
|
|
1208
1211
|
}
|
|
1209
|
-
async requestFindEndpoint(
|
|
1210
|
-
const response = await this.fetchWithTracking(
|
|
1212
|
+
async requestFindEndpoint(endpoint, data) {
|
|
1213
|
+
const response = await this.fetchWithTracking(endpoint, {
|
|
1211
1214
|
...this.defaultOptions,
|
|
1212
1215
|
method: "POST",
|
|
1213
1216
|
body: data ? JSON.stringify(data) : void 0
|
|
1214
1217
|
});
|
|
1215
1218
|
return this.parseFindResponse(response);
|
|
1216
1219
|
}
|
|
1217
|
-
async requestFindEndpointGet(
|
|
1218
|
-
const response = await this.fetchWithTracking(
|
|
1220
|
+
async requestFindEndpointGet(endpoint) {
|
|
1221
|
+
const response = await this.fetchWithTracking(endpoint, {
|
|
1219
1222
|
...this.defaultOptions,
|
|
1220
1223
|
method: "GET"
|
|
1221
1224
|
});
|
|
1222
1225
|
return this.parseFindResponse(response);
|
|
1223
1226
|
}
|
|
1224
|
-
async requestFindById(
|
|
1225
|
-
const url = this.buildUrl(
|
|
1227
|
+
async requestFindById(endpoint, options) {
|
|
1228
|
+
const url = this.buildUrl(endpoint, options);
|
|
1226
1229
|
const response = await this.fetchWithTracking(url, {
|
|
1227
1230
|
...this.defaultOptions,
|
|
1228
1231
|
method: "GET"
|
|
1229
1232
|
});
|
|
1230
1233
|
return this.parseDocumentResponse(response);
|
|
1231
1234
|
}
|
|
1232
|
-
async requestCount(
|
|
1233
|
-
const url = this.buildUrl(
|
|
1235
|
+
async requestCount(endpoint, options) {
|
|
1236
|
+
const url = this.buildUrl(endpoint, options);
|
|
1234
1237
|
const response = await this.fetchWithTracking(url, {
|
|
1235
1238
|
...this.defaultOptions,
|
|
1236
1239
|
method: "GET"
|
|
@@ -1240,7 +1243,7 @@ var ReadOnlyCollectionClient = class extends HttpClient {
|
|
|
1240
1243
|
};
|
|
1241
1244
|
|
|
1242
1245
|
// src/core/api/parse-response.ts
|
|
1243
|
-
async function parseApiResponse(response,
|
|
1246
|
+
async function parseApiResponse(response, endpoint, options = {}) {
|
|
1244
1247
|
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
1245
1248
|
return void 0;
|
|
1246
1249
|
}
|
|
@@ -1249,7 +1252,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
|
|
|
1249
1252
|
parsed = await response.json();
|
|
1250
1253
|
} catch {
|
|
1251
1254
|
throw createApiError(
|
|
1252
|
-
`Invalid JSON response from ${
|
|
1255
|
+
`Invalid JSON response from ${endpoint}`,
|
|
1253
1256
|
response.status,
|
|
1254
1257
|
void 0,
|
|
1255
1258
|
"Server returned an invalid response.",
|
|
@@ -1299,6 +1302,7 @@ async function parseApiResponse(response, endpoint2, options = {}) {
|
|
|
1299
1302
|
|
|
1300
1303
|
// ../../internal/http-contracts/src/index.ts
|
|
1301
1304
|
var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
|
|
1305
|
+
var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
|
|
1302
1306
|
var operation = (collection, method, path, errorFamily) => Object.freeze({
|
|
1303
1307
|
[operationBrand]: true,
|
|
1304
1308
|
collection,
|
|
@@ -1307,6 +1311,10 @@ var operation = (collection, method, path, errorFamily) => Object.freeze({
|
|
|
1307
1311
|
...errorFamily && { errorFamily }
|
|
1308
1312
|
});
|
|
1309
1313
|
var strictCommerceOperation = (collection, method, path) => operation(collection, method, path, "commerce");
|
|
1314
|
+
var selectiveCommerceOperation = (collection, method, path, typedCommerceErrorReasons) => Object.freeze({
|
|
1315
|
+
...operation(collection, method, path),
|
|
1316
|
+
typedCommerceErrorReasons: Object.freeze([...typedCommerceErrorReasons])
|
|
1317
|
+
});
|
|
1310
1318
|
var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
1311
1319
|
products: {
|
|
1312
1320
|
detail: operation("products", "get", "/detail"),
|
|
@@ -1338,7 +1346,12 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1338
1346
|
confirmPayment: operation("orders", "post", "/confirm-payment"),
|
|
1339
1347
|
byPayment: operation("orders", "get", "/by-payment"),
|
|
1340
1348
|
cancel: operation("orders", "post", "/cancel"),
|
|
1341
|
-
resolveCancelRefund:
|
|
1349
|
+
resolveCancelRefund: selectiveCommerceOperation(
|
|
1350
|
+
"orders",
|
|
1351
|
+
"post",
|
|
1352
|
+
"/resolve-cancel-refund",
|
|
1353
|
+
["managed_refund_attestation_forbidden"]
|
|
1354
|
+
),
|
|
1342
1355
|
checkout: strictCommerceOperation("orders", "post", "/checkout"),
|
|
1343
1356
|
createFulfillment: operation("orders", "post", "/create-fulfillment"),
|
|
1344
1357
|
updateFulfillment: operation("orders", "post", "/update-fulfillment")
|
|
@@ -1409,6 +1422,16 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1409
1422
|
"payment-sessions",
|
|
1410
1423
|
"post",
|
|
1411
1424
|
"/server/confirm"
|
|
1425
|
+
),
|
|
1426
|
+
findPortOne: strictCommerceOperation(
|
|
1427
|
+
"payment-sessions",
|
|
1428
|
+
"post",
|
|
1429
|
+
"/server/portone/find"
|
|
1430
|
+
),
|
|
1431
|
+
reconcilePortOne: strictCommerceOperation(
|
|
1432
|
+
"payment-sessions",
|
|
1433
|
+
"post",
|
|
1434
|
+
"/server/portone/reconcile"
|
|
1412
1435
|
)
|
|
1413
1436
|
},
|
|
1414
1437
|
custom: {
|
|
@@ -1428,12 +1451,26 @@ var COMMERCE_ENDPOINT_OPERATIONS = {
|
|
|
1428
1451
|
validate: operation("discounts", "post", "/validate")
|
|
1429
1452
|
}
|
|
1430
1453
|
};
|
|
1454
|
+
var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
|
|
1455
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.create,
|
|
1456
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.retrieve,
|
|
1457
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.create,
|
|
1458
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.retrieve
|
|
1459
|
+
]);
|
|
1431
1460
|
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
1432
1461
|
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
1433
1462
|
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
1434
1463
|
me: operation(null, "get", "/memberships/me")
|
|
1435
1464
|
};
|
|
1465
|
+
var EMBEDDED_ADMIN_ENDPOINT_OPERATIONS = {
|
|
1466
|
+
show: operation("tenants", "get", "/embedded-admin-app"),
|
|
1467
|
+
configure: operation("tenants", "patch", "/embedded-admin-app"),
|
|
1468
|
+
disable: operation("tenants", "delete", "/embedded-admin-app")
|
|
1469
|
+
};
|
|
1436
1470
|
var EVENTS_ENDPOINT_OPERATIONS = {
|
|
1471
|
+
events: {
|
|
1472
|
+
convertSchedule: operation("events", "post", "/:id/schedule")
|
|
1473
|
+
},
|
|
1437
1474
|
occurrences: {
|
|
1438
1475
|
range: operation("event-occurrences", "get", "/range"),
|
|
1439
1476
|
admissionAvailability: operation(
|
|
@@ -1474,46 +1511,51 @@ function resolveOperationMethod(descriptor) {
|
|
|
1474
1511
|
}
|
|
1475
1512
|
|
|
1476
1513
|
// src/core/api/endpoints.ts
|
|
1477
|
-
var endpoint = (method, path) => ({ method, path });
|
|
1478
1514
|
var sharedEndpoint = (descriptor) => descriptor;
|
|
1479
|
-
function resolveOperationMethod2(descriptor) {
|
|
1480
|
-
return "collection" in descriptor ? resolveOperationMethod(descriptor) : descriptor.method;
|
|
1481
|
-
}
|
|
1482
1515
|
function resolveOperationErrorFamily(descriptor) {
|
|
1483
|
-
return
|
|
1484
|
-
}
|
|
1485
|
-
function resolveOperationPath2(descriptor, options) {
|
|
1486
|
-
if ("collection" in descriptor) {
|
|
1487
|
-
return resolveOperationPath(descriptor, options);
|
|
1488
|
-
}
|
|
1489
|
-
const query = options?.query?.toString().replace(/^\?/, "");
|
|
1490
|
-
return query ? `${descriptor.path}?${query}` : descriptor.path;
|
|
1516
|
+
return descriptor.errorFamily;
|
|
1491
1517
|
}
|
|
1492
1518
|
var COMMERCE_ENDPOINTS = {
|
|
1493
1519
|
products: {
|
|
1494
|
-
detail:
|
|
1495
|
-
detailCatalog:
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1520
|
+
detail: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.detail),
|
|
1521
|
+
detailCatalog: sharedEndpoint(
|
|
1522
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.detailCatalog
|
|
1523
|
+
),
|
|
1524
|
+
listingGroups: sharedEndpoint(
|
|
1525
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroups
|
|
1526
|
+
),
|
|
1527
|
+
listingGroupsCatalog: sharedEndpoint(
|
|
1528
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsCatalog
|
|
1529
|
+
),
|
|
1530
|
+
// The manifest keeps the GET read and the POST body-query apart; this
|
|
1531
|
+
// semantic name has always resolved to the GET one.
|
|
1532
|
+
listingGroupsQuery: sharedEndpoint(
|
|
1533
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryGet
|
|
1534
|
+
),
|
|
1535
|
+
listingGroupsQueryCatalog: sharedEndpoint(
|
|
1536
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.listingGroupsQueryCatalog
|
|
1537
|
+
),
|
|
1538
|
+
stockCheck: sharedEndpoint(
|
|
1539
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockCheck
|
|
1500
1540
|
),
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
"GET",
|
|
1504
|
-
"/api/products/listing-groups/query/catalog"
|
|
1541
|
+
stockSnapshot: sharedEndpoint(
|
|
1542
|
+
COMMERCE_ENDPOINT_OPERATIONS.products.stockSnapshot
|
|
1505
1543
|
),
|
|
1506
|
-
|
|
1507
|
-
stockSnapshot: endpoint("GET", "/api/products/stock"),
|
|
1508
|
-
upsert: endpoint("POST", "/api/products/upsert")
|
|
1544
|
+
upsert: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.products.upsert)
|
|
1509
1545
|
},
|
|
1510
1546
|
orders: {
|
|
1511
|
-
update:
|
|
1512
|
-
byPayment:
|
|
1513
|
-
cancel:
|
|
1514
|
-
resolveCancelRefund:
|
|
1515
|
-
|
|
1516
|
-
|
|
1547
|
+
update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.update),
|
|
1548
|
+
byPayment: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.byPayment),
|
|
1549
|
+
cancel: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.cancel),
|
|
1550
|
+
resolveCancelRefund: sharedEndpoint(
|
|
1551
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.resolveCancelRefund
|
|
1552
|
+
),
|
|
1553
|
+
createFulfillment: sharedEndpoint(
|
|
1554
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.createFulfillment
|
|
1555
|
+
),
|
|
1556
|
+
updateFulfillment: sharedEndpoint(
|
|
1557
|
+
COMMERCE_ENDPOINT_OPERATIONS.orders.updateFulfillment
|
|
1558
|
+
)
|
|
1517
1559
|
},
|
|
1518
1560
|
checkouts: {
|
|
1519
1561
|
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.orders.checkout),
|
|
@@ -1525,18 +1567,21 @@ var COMMERCE_ENDPOINTS = {
|
|
|
1525
1567
|
}
|
|
1526
1568
|
},
|
|
1527
1569
|
returns: {
|
|
1528
|
-
create:
|
|
1529
|
-
update:
|
|
1530
|
-
returnRefund:
|
|
1570
|
+
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.create),
|
|
1571
|
+
update: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.returns.update),
|
|
1572
|
+
returnRefund: sharedEndpoint(
|
|
1573
|
+
COMMERCE_ENDPOINT_OPERATIONS.returns.returnRefund
|
|
1574
|
+
)
|
|
1531
1575
|
},
|
|
1532
1576
|
fulfillmentOrders: {
|
|
1533
|
-
prepare:
|
|
1534
|
-
|
|
1535
|
-
"/api/fulfillment-orders/prepare-fulfillment-order"
|
|
1577
|
+
prepare: sharedEndpoint(
|
|
1578
|
+
COMMERCE_ENDPOINT_OPERATIONS.fulfillmentOrders.prepare
|
|
1536
1579
|
)
|
|
1537
1580
|
},
|
|
1538
1581
|
fulfillments: {
|
|
1539
|
-
bulkImport:
|
|
1582
|
+
bulkImport: sharedEndpoint(
|
|
1583
|
+
COMMERCE_ENDPOINT_OPERATIONS.fulfillments.bulkImport
|
|
1584
|
+
)
|
|
1540
1585
|
},
|
|
1541
1586
|
carts: {
|
|
1542
1587
|
create: sharedEndpoint(COMMERCE_ENDPOINT_OPERATIONS.carts.create),
|
|
@@ -1601,42 +1646,21 @@ var COMMERCE_ENDPOINTS = {
|
|
|
1601
1646
|
),
|
|
1602
1647
|
confirm: sharedEndpoint(
|
|
1603
1648
|
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.confirm
|
|
1649
|
+
),
|
|
1650
|
+
findPortOne: sharedEndpoint(
|
|
1651
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.findPortOne
|
|
1652
|
+
),
|
|
1653
|
+
reconcilePortOne: sharedEndpoint(
|
|
1654
|
+
COMMERCE_ENDPOINT_OPERATIONS.paymentSessions.server.reconcilePortOne
|
|
1604
1655
|
)
|
|
1605
1656
|
}
|
|
1606
1657
|
},
|
|
1607
1658
|
shippingPolicies: {
|
|
1608
|
-
calculate:
|
|
1659
|
+
calculate: sharedEndpoint(
|
|
1660
|
+
COMMERCE_ENDPOINT_OPERATIONS.shippingPolicies.calculate
|
|
1661
|
+
)
|
|
1609
1662
|
}
|
|
1610
1663
|
};
|
|
1611
|
-
function isCommerceEndpointDescriptor(value) {
|
|
1612
|
-
if (!value || typeof value !== "object") return false;
|
|
1613
|
-
const candidate = value;
|
|
1614
|
-
return typeof candidate.method === "string" && typeof candidate.path === "string";
|
|
1615
|
-
}
|
|
1616
|
-
function flattenEndpointPaths(value) {
|
|
1617
|
-
if (isCommerceEndpointDescriptor(value)) return [resolveOperationPath2(value)];
|
|
1618
|
-
if (!value || typeof value !== "object") return [];
|
|
1619
|
-
return Object.values(value).flatMap((entry) => flattenEndpointPaths(entry));
|
|
1620
|
-
}
|
|
1621
|
-
function flattenEndpointDescriptors(value) {
|
|
1622
|
-
if (isCommerceEndpointDescriptor(value)) return [value];
|
|
1623
|
-
if (!value || typeof value !== "object") return [];
|
|
1624
|
-
return Object.values(value).flatMap(
|
|
1625
|
-
(entry) => flattenEndpointDescriptors(entry)
|
|
1626
|
-
);
|
|
1627
|
-
}
|
|
1628
|
-
var COMMERCE_ENDPOINT_PATHS = flattenEndpointPaths(COMMERCE_ENDPOINTS);
|
|
1629
|
-
var COMMERCE_ENDPOINT_DESCRIPTORS = flattenEndpointDescriptors(COMMERCE_ENDPOINTS);
|
|
1630
|
-
var MEMBERSHIP_ENDPOINTS = {
|
|
1631
|
-
subscribe: "/api/memberships/subscribe",
|
|
1632
|
-
cancel: (id) => `/api/memberships/${id}/cancel`,
|
|
1633
|
-
me: "/api/memberships/me"
|
|
1634
|
-
};
|
|
1635
|
-
var MEMBERSHIP_ENDPOINT_PATHS = [
|
|
1636
|
-
MEMBERSHIP_ENDPOINTS.subscribe,
|
|
1637
|
-
MEMBERSHIP_ENDPOINTS.cancel(":id"),
|
|
1638
|
-
MEMBERSHIP_ENDPOINTS.me
|
|
1639
|
-
];
|
|
1640
1664
|
|
|
1641
1665
|
// src/core/api/customer-scoped-api.ts
|
|
1642
1666
|
var CustomerScopedTransport = class {
|
|
@@ -1657,10 +1681,10 @@ var CustomerScopedTransport = class {
|
|
|
1657
1681
|
this.onUnauthorized = options.onUnauthorized;
|
|
1658
1682
|
this.onRequestId = options.onRequestId;
|
|
1659
1683
|
}
|
|
1660
|
-
async request(
|
|
1684
|
+
async request(endpoint, options) {
|
|
1661
1685
|
const token = typeof this.customerToken === "function" ? this.customerToken() : this.customerToken;
|
|
1662
1686
|
try {
|
|
1663
|
-
const response = await httpFetch(
|
|
1687
|
+
const response = await httpFetch(endpoint, {
|
|
1664
1688
|
method: options.method,
|
|
1665
1689
|
apiUrl: this.apiUrl,
|
|
1666
1690
|
publishableKey: this.publishableKey,
|
|
@@ -1674,7 +1698,7 @@ var CustomerScopedTransport = class {
|
|
|
1674
1698
|
...options.errorFamily && { errorFamily: options.errorFamily }
|
|
1675
1699
|
});
|
|
1676
1700
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
1677
|
-
return parseApiResponse(response,
|
|
1701
|
+
return parseApiResponse(response, endpoint, {
|
|
1678
1702
|
errorFamily: options.errorFamily
|
|
1679
1703
|
});
|
|
1680
1704
|
} catch (err) {
|
|
@@ -1688,12 +1712,12 @@ var CustomerScopedApi = class {
|
|
|
1688
1712
|
constructor(apiName, options) {
|
|
1689
1713
|
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1690
1714
|
}
|
|
1691
|
-
requestEndpoint(
|
|
1692
|
-
return this.transport.request(
|
|
1693
|
-
method:
|
|
1715
|
+
requestEndpoint(endpoint, body, options) {
|
|
1716
|
+
return this.transport.request(resolveOperationPath(endpoint, options), {
|
|
1717
|
+
method: resolveOperationMethod(endpoint),
|
|
1694
1718
|
body,
|
|
1695
1719
|
headers: options?.headers,
|
|
1696
|
-
errorFamily: resolveOperationErrorFamily(
|
|
1720
|
+
errorFamily: resolveOperationErrorFamily(endpoint)
|
|
1697
1721
|
});
|
|
1698
1722
|
}
|
|
1699
1723
|
};
|
|
@@ -1701,8 +1725,8 @@ var RawCustomerScopedApi = class {
|
|
|
1701
1725
|
constructor(apiName, options) {
|
|
1702
1726
|
this.transport = new CustomerScopedTransport(apiName, options);
|
|
1703
1727
|
}
|
|
1704
|
-
request(
|
|
1705
|
-
return this.transport.request(
|
|
1728
|
+
request(endpoint, options) {
|
|
1729
|
+
return this.transport.request(endpoint, options);
|
|
1706
1730
|
}
|
|
1707
1731
|
};
|
|
1708
1732
|
|
|
@@ -1777,11 +1801,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
1777
1801
|
if (params.page !== void 0) urlParams.set("page", String(params.page));
|
|
1778
1802
|
return `/api/comments/public?${urlParams.toString()}`;
|
|
1779
1803
|
}
|
|
1780
|
-
async execute(
|
|
1781
|
-
return this.request(
|
|
1804
|
+
async execute(endpoint, method, body) {
|
|
1805
|
+
return this.request(endpoint, { method, body });
|
|
1782
1806
|
}
|
|
1783
|
-
async executeDoc(
|
|
1784
|
-
const response = await this.execute(
|
|
1807
|
+
async executeDoc(endpoint, method, body) {
|
|
1808
|
+
const response = await this.execute(endpoint, method, body);
|
|
1785
1809
|
return unwrapPayloadDoc(response);
|
|
1786
1810
|
}
|
|
1787
1811
|
createPost(params) {
|
|
@@ -2047,8 +2071,8 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
2047
2071
|
|
|
2048
2072
|
// src/core/content/content-client.ts
|
|
2049
2073
|
var PublicContentApi = class extends RawCustomerScopedApi {
|
|
2050
|
-
get(
|
|
2051
|
-
return this.request(
|
|
2074
|
+
get(endpoint) {
|
|
2075
|
+
return this.request(endpoint, { method: "GET" });
|
|
2052
2076
|
}
|
|
2053
2077
|
};
|
|
2054
2078
|
function appendCommonParams(search, options, defaultSort) {
|
|
@@ -2229,6 +2253,9 @@ function nullableString(value, resource, path) {
|
|
|
2229
2253
|
fail(resource, path, "string or null");
|
|
2230
2254
|
}
|
|
2231
2255
|
}
|
|
2256
|
+
function nullableNonEmptyString(value, resource, path) {
|
|
2257
|
+
if (value !== null) string(value, resource, path);
|
|
2258
|
+
}
|
|
2232
2259
|
function cartLineQuantity(value, resource, path) {
|
|
2233
2260
|
const quantity = positiveInteger(value, resource, path);
|
|
2234
2261
|
if (quantity > MAX_CART_LINE_QUANTITY) {
|
|
@@ -2738,8 +2765,8 @@ function validatePublicOrderItem(value, resource, path) {
|
|
|
2738
2765
|
validateReference(item.variant, resource, `${path}.variant`);
|
|
2739
2766
|
}
|
|
2740
2767
|
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2741
|
-
|
|
2742
|
-
|
|
2768
|
+
nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
2769
|
+
nullableNonEmptyString(item.sku, resource, `${path}.sku`);
|
|
2743
2770
|
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2744
2771
|
const quantity = positiveInteger(item.quantity, resource, `${path}.quantity`);
|
|
2745
2772
|
const unitPrice = safeMinor(
|
|
@@ -2990,8 +3017,8 @@ function validateCheckoutItem(value, resource, path) {
|
|
|
2990
3017
|
validateReference(item.product, resource, `${path}.product`);
|
|
2991
3018
|
validateReference(item.variant, resource, `${path}.variant`);
|
|
2992
3019
|
string(item.productTitle, resource, `${path}.productTitle`);
|
|
2993
|
-
|
|
2994
|
-
|
|
3020
|
+
nullableNonEmptyString(item.variantTitle, resource, `${path}.variantTitle`);
|
|
3021
|
+
nullableNonEmptyString(item.sku, resource, `${path}.sku`);
|
|
2995
3022
|
validateAdmissions(item.admissions, resource, `${path}.admissions`);
|
|
2996
3023
|
cartLineQuantity(item.quantity, resource, `${path}.quantity`);
|
|
2997
3024
|
const unitPrice = safeMinor(
|
|
@@ -3323,11 +3350,21 @@ function validateNextAction(value, provider, resource, path) {
|
|
|
3323
3350
|
const action = record(value, resource, path);
|
|
3324
3351
|
if (provider === "portone") {
|
|
3325
3352
|
if (action.type === "portone_sdk") {
|
|
3353
|
+
const hasCancelable = "cancelable" in action;
|
|
3354
|
+
const hasRetryPolicy = "retryPolicy" in action;
|
|
3355
|
+
if (hasCancelable !== hasRetryPolicy) {
|
|
3356
|
+
fail(
|
|
3357
|
+
resource,
|
|
3358
|
+
path,
|
|
3359
|
+
"exact released action or exact negotiated capability action"
|
|
3360
|
+
);
|
|
3361
|
+
}
|
|
3326
3362
|
exact(
|
|
3327
3363
|
action,
|
|
3328
3364
|
[
|
|
3329
3365
|
"type",
|
|
3330
3366
|
"version",
|
|
3367
|
+
...hasCancelable ? ["cancelable", "retryPolicy"] : [],
|
|
3331
3368
|
"storeId",
|
|
3332
3369
|
"channelKey",
|
|
3333
3370
|
"paymentId",
|
|
@@ -3342,6 +3379,11 @@ function validateNextAction(value, provider, resource, path) {
|
|
|
3342
3379
|
path
|
|
3343
3380
|
);
|
|
3344
3381
|
if (action.version !== "v2") fail(resource, `${path}.version`, "v2");
|
|
3382
|
+
if (hasCancelable && action.cancelable !== false)
|
|
3383
|
+
fail(resource, `${path}.cancelable`, "false");
|
|
3384
|
+
if (hasRetryPolicy && action.retryPolicy !== "same_action_only") {
|
|
3385
|
+
fail(resource, `${path}.retryPolicy`, "same_action_only");
|
|
3386
|
+
}
|
|
3345
3387
|
for (const key of ["storeId", "channelKey"]) {
|
|
3346
3388
|
boundedString(action[key], 255, resource, `${path}.${key}`);
|
|
3347
3389
|
}
|
|
@@ -3388,6 +3430,10 @@ function validateNextAction(value, provider, resource, path) {
|
|
|
3388
3430
|
"HTTPS or loopback URL without embedded credentials"
|
|
3389
3431
|
);
|
|
3390
3432
|
}
|
|
3433
|
+
if (!hasCancelable) {
|
|
3434
|
+
action.cancelable = false;
|
|
3435
|
+
action.retryPolicy = "same_action_only";
|
|
3436
|
+
}
|
|
3391
3437
|
return;
|
|
3392
3438
|
}
|
|
3393
3439
|
exact(action, ["type", "checkoutUrl"], [], resource, path);
|
|
@@ -4122,8 +4168,8 @@ var CartApi = class extends CustomerScopedApi {
|
|
|
4122
4168
|
endpoint(key) {
|
|
4123
4169
|
return this.serverTransport ? COMMERCE_ENDPOINTS.carts.server[key] : COMMERCE_ENDPOINTS.carts[key];
|
|
4124
4170
|
}
|
|
4125
|
-
execute(
|
|
4126
|
-
return this.requestEndpoint(
|
|
4171
|
+
execute(endpoint, body, idempotencyKey) {
|
|
4172
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4127
4173
|
...idempotencyKey && {
|
|
4128
4174
|
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4129
4175
|
}
|
|
@@ -4140,26 +4186,26 @@ var CartApi = class extends CustomerScopedApi {
|
|
|
4140
4186
|
);
|
|
4141
4187
|
}
|
|
4142
4188
|
mine(params = {}) {
|
|
4143
|
-
const
|
|
4144
|
-
return this.execute(
|
|
4189
|
+
const endpoint = this.endpoint("mine");
|
|
4190
|
+
return this.execute(endpoint, params).then(
|
|
4145
4191
|
(value) => validateCartMineResult(value)
|
|
4146
4192
|
);
|
|
4147
4193
|
}
|
|
4148
4194
|
merge(params) {
|
|
4149
4195
|
const { idempotencyKey, ...body } = params;
|
|
4150
4196
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4151
|
-
const
|
|
4152
|
-
return this.execute(
|
|
4197
|
+
const endpoint = this.endpoint("merge");
|
|
4198
|
+
return this.execute(endpoint, body, idempotencyKey).then(
|
|
4153
4199
|
(value) => validateCartMergeResult(value)
|
|
4154
4200
|
);
|
|
4155
4201
|
}
|
|
4156
4202
|
addItem(params) {
|
|
4157
4203
|
return this.mutate(this.endpoint("addItem"), params);
|
|
4158
4204
|
}
|
|
4159
|
-
mutate(
|
|
4205
|
+
mutate(endpoint, params) {
|
|
4160
4206
|
const { idempotencyKey, ...body } = params;
|
|
4161
4207
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4162
|
-
return this.execute(
|
|
4208
|
+
return this.execute(endpoint, body, idempotencyKey).then(
|
|
4163
4209
|
(value) => validateCartMutationResult(value)
|
|
4164
4210
|
);
|
|
4165
4211
|
}
|
|
@@ -4185,8 +4231,8 @@ var CheckoutApi = class extends CustomerScopedApi {
|
|
|
4185
4231
|
constructor(options) {
|
|
4186
4232
|
super("CheckoutApi", { ...options, requiresCredential: false });
|
|
4187
4233
|
}
|
|
4188
|
-
post(
|
|
4189
|
-
return this.requestEndpoint(
|
|
4234
|
+
post(endpoint, body, idempotencyKey) {
|
|
4235
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4190
4236
|
...idempotencyKey && {
|
|
4191
4237
|
headers: { "X-Idempotency-Key": idempotencyKey }
|
|
4192
4238
|
}
|
|
@@ -4253,11 +4299,15 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4253
4299
|
super("PaymentSessionApi", { ...options, requiresCredential: false });
|
|
4254
4300
|
this.serverTransport = Boolean(options.secretKey);
|
|
4255
4301
|
}
|
|
4256
|
-
post(
|
|
4257
|
-
|
|
4258
|
-
...idempotencyKey && {
|
|
4259
|
-
|
|
4302
|
+
post(endpoint, body, idempotencyKey, negotiateStandardActionCapabilities = false) {
|
|
4303
|
+
const headers = {
|
|
4304
|
+
...idempotencyKey && { "X-Idempotency-Key": idempotencyKey },
|
|
4305
|
+
...negotiateStandardActionCapabilities && {
|
|
4306
|
+
Accept: PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE
|
|
4260
4307
|
}
|
|
4308
|
+
};
|
|
4309
|
+
return this.requestEndpoint(endpoint, body, {
|
|
4310
|
+
...Object.keys(headers).length > 0 && { headers }
|
|
4261
4311
|
});
|
|
4262
4312
|
}
|
|
4263
4313
|
async paymentSession(result, expectedProvider) {
|
|
@@ -4282,40 +4332,41 @@ var PaymentSessionApi = class extends CustomerScopedApi {
|
|
|
4282
4332
|
this.post(
|
|
4283
4333
|
this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.create : COMMERCE_ENDPOINTS.paymentSessions.create,
|
|
4284
4334
|
body,
|
|
4285
|
-
idempotencyKey
|
|
4335
|
+
idempotencyKey,
|
|
4336
|
+
body.providerOptions.profile === "standard_v2"
|
|
4286
4337
|
),
|
|
4287
4338
|
"portone"
|
|
4288
4339
|
);
|
|
4289
4340
|
}
|
|
4290
4341
|
retrieve(params) {
|
|
4291
|
-
const
|
|
4342
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
4292
4343
|
return this.paymentSession(
|
|
4293
|
-
this.post(
|
|
4344
|
+
this.post(endpoint, params),
|
|
4294
4345
|
"toss"
|
|
4295
4346
|
);
|
|
4296
4347
|
}
|
|
4297
4348
|
retrievePortOne(params) {
|
|
4298
|
-
const
|
|
4349
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.retrieve : COMMERCE_ENDPOINTS.paymentSessions.retrieve;
|
|
4299
4350
|
return this.paymentSession(
|
|
4300
|
-
this.post(
|
|
4351
|
+
this.post(endpoint, params, void 0, true),
|
|
4301
4352
|
"portone"
|
|
4302
4353
|
);
|
|
4303
4354
|
}
|
|
4304
4355
|
cancel(params) {
|
|
4305
4356
|
const { idempotencyKey, ...body } = params;
|
|
4306
4357
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4307
|
-
const
|
|
4358
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4308
4359
|
return this.paymentSession(
|
|
4309
|
-
this.post(
|
|
4360
|
+
this.post(endpoint, body, idempotencyKey),
|
|
4310
4361
|
"toss"
|
|
4311
4362
|
);
|
|
4312
4363
|
}
|
|
4313
4364
|
cancelPortOne(params) {
|
|
4314
4365
|
const { idempotencyKey, ...body } = params;
|
|
4315
4366
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
4316
|
-
const
|
|
4367
|
+
const endpoint = this.serverTransport ? COMMERCE_ENDPOINTS.paymentSessions.server.cancel : COMMERCE_ENDPOINTS.paymentSessions.cancel;
|
|
4317
4368
|
return this.paymentSession(
|
|
4318
|
-
this.post(
|
|
4369
|
+
this.post(endpoint, body, idempotencyKey),
|
|
4319
4370
|
"portone"
|
|
4320
4371
|
);
|
|
4321
4372
|
}
|
|
@@ -4394,9 +4445,9 @@ function resolveVariantImageItems(variant, poolById) {
|
|
|
4394
4445
|
if (pooled) resolved.push(pooled);
|
|
4395
4446
|
continue;
|
|
4396
4447
|
}
|
|
4397
|
-
const
|
|
4398
|
-
if (
|
|
4399
|
-
const pooled = poolById.get(
|
|
4448
|
+
const mediaId = getMediaId(entry);
|
|
4449
|
+
if (mediaId) {
|
|
4450
|
+
const pooled = poolById.get(mediaId);
|
|
4400
4451
|
if (pooled) {
|
|
4401
4452
|
resolved.push(pooled);
|
|
4402
4453
|
}
|
|
@@ -4587,11 +4638,11 @@ function getFirstMediaId(values) {
|
|
|
4587
4638
|
}
|
|
4588
4639
|
return null;
|
|
4589
4640
|
}
|
|
4590
|
-
function inProductMediaPool(product,
|
|
4591
|
-
if (
|
|
4641
|
+
function inProductMediaPool(product, mediaId) {
|
|
4642
|
+
if (mediaId == null) return null;
|
|
4592
4643
|
const images = Array.isArray(product?.images) ? product.images : [];
|
|
4593
4644
|
for (const image of images) {
|
|
4594
|
-
if (extractEntityId(image) ===
|
|
4645
|
+
if (extractEntityId(image) === mediaId) return mediaId;
|
|
4595
4646
|
}
|
|
4596
4647
|
return null;
|
|
4597
4648
|
}
|
|
@@ -6172,8 +6223,8 @@ function isProductUpsertFieldValidationErrorBody(value) {
|
|
|
6172
6223
|
|
|
6173
6224
|
// src/core/commerce/commerce-client.ts
|
|
6174
6225
|
var BrowserCommerceApi = class extends CustomerScopedApi {
|
|
6175
|
-
requestEndpoint(
|
|
6176
|
-
return super.requestEndpoint(
|
|
6226
|
+
requestEndpoint(endpoint, body, options) {
|
|
6227
|
+
return super.requestEndpoint(endpoint, body, options);
|
|
6177
6228
|
}
|
|
6178
6229
|
};
|
|
6179
6230
|
var CommerceClient = class {
|
|
@@ -6373,11 +6424,11 @@ var EventsClient = class {
|
|
|
6373
6424
|
{ useCustomerAuth: false }
|
|
6374
6425
|
);
|
|
6375
6426
|
}
|
|
6376
|
-
async execute(
|
|
6427
|
+
async execute(endpoint, method, body, options = {}) {
|
|
6377
6428
|
const useCustomerAuth = options.useCustomerAuth === true;
|
|
6378
6429
|
const token = useCustomerAuth ? typeof this.customerToken === "function" ? this.customerToken() : this.customerToken : void 0;
|
|
6379
6430
|
try {
|
|
6380
|
-
const response = await httpFetch(
|
|
6431
|
+
const response = await httpFetch(endpoint, {
|
|
6381
6432
|
method,
|
|
6382
6433
|
apiUrl: this.apiUrl,
|
|
6383
6434
|
publishableKey: this.publishableKey,
|
|
@@ -6386,7 +6437,7 @@ var EventsClient = class {
|
|
|
6386
6437
|
...body !== void 0 && { body: JSON.stringify(body) }
|
|
6387
6438
|
});
|
|
6388
6439
|
this.onRequestId?.(response.headers.get("x-request-id") ?? null);
|
|
6389
|
-
return parseApiResponse(response,
|
|
6440
|
+
return parseApiResponse(response, endpoint);
|
|
6390
6441
|
} catch (err) {
|
|
6391
6442
|
const id = err instanceof SDKError ? err.requestId ?? null : null;
|
|
6392
6443
|
this.onRequestId?.(id);
|
|
@@ -6644,13 +6695,106 @@ function mergeProductDetailWithStock(catalog, snapshot) {
|
|
|
6644
6695
|
};
|
|
6645
6696
|
}
|
|
6646
6697
|
|
|
6698
|
+
// src/core/webhook/validation.ts
|
|
6699
|
+
function isValidWebhookEventData(data) {
|
|
6700
|
+
if (typeof data !== "object" || data === null) return false;
|
|
6701
|
+
const event = data;
|
|
6702
|
+
return typeof event.collection === "string" && typeof event.operation === "string" && event.operation.length > 0 && typeof event.data === "object" && event.data !== null;
|
|
6703
|
+
}
|
|
6704
|
+
|
|
6705
|
+
// src/core/webhook/receiver.ts
|
|
6706
|
+
async function verifySignature(rawBody, secret, signature, timestamp2, deliveryId) {
|
|
6707
|
+
const encoder = new TextEncoder();
|
|
6708
|
+
const signedPrefix = encoder.encode(`${timestamp2}.${deliveryId}.`);
|
|
6709
|
+
const signedPayload = new Uint8Array(signedPrefix.length + rawBody.length);
|
|
6710
|
+
signedPayload.set(signedPrefix);
|
|
6711
|
+
signedPayload.set(rawBody, signedPrefix.length);
|
|
6712
|
+
const key = await crypto.subtle.importKey(
|
|
6713
|
+
"raw",
|
|
6714
|
+
encoder.encode(secret),
|
|
6715
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
6716
|
+
false,
|
|
6717
|
+
["verify"]
|
|
6718
|
+
);
|
|
6719
|
+
if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
|
|
6720
|
+
return false;
|
|
6721
|
+
}
|
|
6722
|
+
const sigBytes = new Uint8Array(
|
|
6723
|
+
(signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
|
|
6724
|
+
);
|
|
6725
|
+
return crypto.subtle.verify("HMAC", key, sigBytes, signedPayload);
|
|
6726
|
+
}
|
|
6727
|
+
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6728
|
+
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6729
|
+
const timestampMs = Number(timestamp2);
|
|
6730
|
+
if (!Number.isFinite(timestampMs)) return false;
|
|
6731
|
+
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
6732
|
+
return skewMs <= toleranceSeconds * 1e3;
|
|
6733
|
+
}
|
|
6734
|
+
var MAX_TOLERANCE_SECONDS = 86400;
|
|
6735
|
+
function toleranceIsValid(toleranceSeconds) {
|
|
6736
|
+
return typeof toleranceSeconds === "number" && Number.isFinite(toleranceSeconds) && toleranceSeconds >= 0 && toleranceSeconds <= MAX_TOLERANCE_SECONDS;
|
|
6737
|
+
}
|
|
6738
|
+
async function processWebhookRequest(request, handler, verify) {
|
|
6739
|
+
try {
|
|
6740
|
+
const rawBody = new Uint8Array(await request.arrayBuffer());
|
|
6741
|
+
const verificationFailure = await verify?.(rawBody);
|
|
6742
|
+
if (verificationFailure) return verificationFailure;
|
|
6743
|
+
const body = JSON.parse(new TextDecoder().decode(rawBody));
|
|
6744
|
+
if (!isValidWebhookEventData(body)) {
|
|
6745
|
+
return new Response(
|
|
6746
|
+
JSON.stringify({ error: "Invalid webhook event format" }),
|
|
6747
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
6748
|
+
);
|
|
6749
|
+
}
|
|
6750
|
+
await handler(body);
|
|
6751
|
+
return new Response(
|
|
6752
|
+
JSON.stringify({ success: true, message: "Webhook processed" }),
|
|
6753
|
+
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
6754
|
+
);
|
|
6755
|
+
} catch (error) {
|
|
6756
|
+
console.error("Webhook processing error:", error);
|
|
6757
|
+
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
6758
|
+
status: 500,
|
|
6759
|
+
headers: { "Content-Type": "application/json" }
|
|
6760
|
+
});
|
|
6761
|
+
}
|
|
6762
|
+
}
|
|
6763
|
+
async function handleSignedWebhook(request, handler, options) {
|
|
6764
|
+
const secret = options?.secret;
|
|
6765
|
+
const configuredTolerance = options?.toleranceSeconds;
|
|
6766
|
+
const toleranceSeconds = configuredTolerance ?? 300;
|
|
6767
|
+
if (typeof secret !== "string" || secret.trim().length === 0) {
|
|
6768
|
+
return new Response(
|
|
6769
|
+
JSON.stringify({ error: "Webhook signing secret is not configured" }),
|
|
6770
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
6771
|
+
);
|
|
6772
|
+
}
|
|
6773
|
+
if (!toleranceIsValid(toleranceSeconds)) {
|
|
6774
|
+
return new Response(
|
|
6775
|
+
JSON.stringify({ error: "Webhook signature tolerance is not valid" }),
|
|
6776
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
6777
|
+
);
|
|
6778
|
+
}
|
|
6779
|
+
return processWebhookRequest(request, handler, async (rawBody) => {
|
|
6780
|
+
const signature = request.headers.get("x-webhook-signature") || "";
|
|
6781
|
+
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
6782
|
+
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
6783
|
+
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(rawBody, secret, signature, timestamp2, deliveryId);
|
|
6784
|
+
if (!valid) {
|
|
6785
|
+
return new Response(
|
|
6786
|
+
JSON.stringify({ error: "Invalid webhook signature" }),
|
|
6787
|
+
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
6788
|
+
);
|
|
6789
|
+
}
|
|
6790
|
+
});
|
|
6791
|
+
}
|
|
6792
|
+
|
|
6647
6793
|
// src/core/webhook/index.ts
|
|
6648
6794
|
var ORDER_CHANGED_EVENT_TYPE = "collection.orderChanged";
|
|
6649
6795
|
var COMMERCE_NOTIFICATION_EVENT_TYPE = "commerce.notification";
|
|
6650
6796
|
function isValidWebhookEvent(data) {
|
|
6651
|
-
|
|
6652
|
-
const obj = data;
|
|
6653
|
-
return typeof obj.collection === "string" && typeof obj.operation === "string" && obj.operation.length > 0 && typeof obj.data === "object" && obj.data !== null;
|
|
6797
|
+
return isValidWebhookEventData(data);
|
|
6654
6798
|
}
|
|
6655
6799
|
var COMMERCE_NOTIFICATION_OPERATION = "notification";
|
|
6656
6800
|
var COMMERCE_NOTIFICATION_EVENTS = [
|
|
@@ -6662,7 +6806,9 @@ var COMMERCE_NOTIFICATION_EVENTS = [
|
|
|
6662
6806
|
"returnApproved",
|
|
6663
6807
|
"returnRejected",
|
|
6664
6808
|
"returnCanceled",
|
|
6665
|
-
"returnCompleted"
|
|
6809
|
+
"returnCompleted",
|
|
6810
|
+
"paymentReconciliationRequired",
|
|
6811
|
+
"paymentRefundRequiresAttention"
|
|
6666
6812
|
];
|
|
6667
6813
|
function isStringOrNumber(value) {
|
|
6668
6814
|
return typeof value === "string" || typeof value === "number";
|
|
@@ -6692,18 +6838,25 @@ function isCommerceNotificationEventName(value) {
|
|
|
6692
6838
|
return typeof value === "string" && COMMERCE_NOTIFICATION_EVENTS.includes(value);
|
|
6693
6839
|
}
|
|
6694
6840
|
function isCommerceNotificationSourceCollection(value) {
|
|
6695
|
-
return value === "orders" || value === "fulfillments" || value === "returns";
|
|
6841
|
+
return value === "orders" || value === "fulfillments" || value === "returns" || value === "payment-sessions" || value === "payment-refund-attempts";
|
|
6696
6842
|
}
|
|
6697
6843
|
function isCommerceNotificationData(value) {
|
|
6698
6844
|
if (!isRecord(value)) return false;
|
|
6699
6845
|
if (value.source !== void 0 && (!isRecord(value.source) || !isCommerceNotificationSourceCollection(value.source.collection) || !isStringOrNumber(value.source.id))) {
|
|
6700
6846
|
return false;
|
|
6701
6847
|
}
|
|
6702
|
-
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");
|
|
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") && (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");
|
|
6703
6849
|
}
|
|
6704
6850
|
function isCommerceNotification(value) {
|
|
6705
6851
|
if (!isRecord(value)) return false;
|
|
6706
|
-
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");
|
|
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") && (value.paymentSessionId === void 0 || typeof value.paymentSessionId === "string") && (value.refundAttemptId === void 0 || typeof value.refundAttemptId === "string");
|
|
6853
|
+
}
|
|
6854
|
+
function isPaymentIncidentNotificationData(value, event) {
|
|
6855
|
+
const reconciliation = event === "paymentReconciliationRequired";
|
|
6856
|
+
const expectedCollection = reconciliation ? "payment-sessions" : "payment-refund-attempts";
|
|
6857
|
+
const expectedStatus = reconciliation ? "reconciliation_required" : "requires_attention";
|
|
6858
|
+
const expectedReason = reconciliation ? "orderless_capture" : "local_commit_ambiguous";
|
|
6859
|
+
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);
|
|
6707
6860
|
}
|
|
6708
6861
|
function isWebhookCommerceNotificationChange(value) {
|
|
6709
6862
|
if (!isRecord(value)) return false;
|
|
@@ -6744,6 +6897,15 @@ function isCommerceNotificationWebhookEvent(event) {
|
|
|
6744
6897
|
if (!matchesOptionalId(change.sourceId, sourceId)) return false;
|
|
6745
6898
|
}
|
|
6746
6899
|
const changeSourceId = isWebhookCommerceNotificationChange(change) ? change.sourceId : void 0;
|
|
6900
|
+
if (notification.event === "paymentReconciliationRequired" || notification.event === "paymentRefundRequiresAttention") {
|
|
6901
|
+
if (!isPaymentIncidentNotificationData(data, notification.event)) {
|
|
6902
|
+
return false;
|
|
6903
|
+
}
|
|
6904
|
+
const incidentData = data;
|
|
6905
|
+
const expectedCollection = notification.event === "paymentReconciliationRequired" ? "payment-sessions" : "payment-refund-attempts";
|
|
6906
|
+
const notificationSourceId = notification.event === "paymentReconciliationRequired" ? notification.paymentSessionId : notification.refundAttemptId;
|
|
6907
|
+
return sourceCollection === expectedCollection && typeof notification.paymentSessionId === "string" && notification.paymentSessionId === incidentData.paymentSessionId && typeof notificationSourceId === "string" && notificationSourceId === incidentData.source.id && matchesOptionalId(changeSourceId, incidentData.source.id);
|
|
6908
|
+
}
|
|
6747
6909
|
if (notification.event === "orderPaid" || notification.event === "orderCanceled" || notification.event === "orderDelivered") {
|
|
6748
6910
|
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);
|
|
6749
6911
|
}
|
|
@@ -6812,80 +6974,8 @@ function createCustomerAuthWebhookHandler(handlers) {
|
|
|
6812
6974
|
await handlers.unhandled?.(event);
|
|
6813
6975
|
};
|
|
6814
6976
|
}
|
|
6815
|
-
async function verifySignature(payload, secret, signature, timestamp2, deliveryId) {
|
|
6816
|
-
const encoder = new TextEncoder();
|
|
6817
|
-
const key = await crypto.subtle.importKey(
|
|
6818
|
-
"raw",
|
|
6819
|
-
encoder.encode(secret),
|
|
6820
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
6821
|
-
false,
|
|
6822
|
-
["verify"]
|
|
6823
|
-
);
|
|
6824
|
-
if (signature.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(signature)) {
|
|
6825
|
-
return false;
|
|
6826
|
-
}
|
|
6827
|
-
const sigBytes = new Uint8Array(
|
|
6828
|
-
(signature.match(/.{2}/g) ?? []).map((byte) => parseInt(byte, 16))
|
|
6829
|
-
);
|
|
6830
|
-
return crypto.subtle.verify(
|
|
6831
|
-
"HMAC",
|
|
6832
|
-
key,
|
|
6833
|
-
sigBytes,
|
|
6834
|
-
encoder.encode(`${timestamp2}.${deliveryId}.${payload}`)
|
|
6835
|
-
);
|
|
6836
|
-
}
|
|
6837
|
-
function timestampIsFresh(timestamp2, toleranceSeconds) {
|
|
6838
|
-
if (!/^\d+$/.test(timestamp2)) return false;
|
|
6839
|
-
const timestampMs = Number(timestamp2);
|
|
6840
|
-
if (!Number.isFinite(timestampMs)) return false;
|
|
6841
|
-
const skewMs = Math.abs(Date.now() - timestampMs);
|
|
6842
|
-
return skewMs <= toleranceSeconds * 1e3;
|
|
6843
|
-
}
|
|
6844
6977
|
async function handleWebhook(request, handler, options) {
|
|
6845
|
-
|
|
6846
|
-
const rawBody = await request.text();
|
|
6847
|
-
if (options?.secret) {
|
|
6848
|
-
const signature = request.headers.get("x-webhook-signature") || "";
|
|
6849
|
-
const timestamp2 = request.headers.get("x-webhook-timestamp") || "";
|
|
6850
|
-
const deliveryId = request.headers.get("x-webhook-delivery-id") || "";
|
|
6851
|
-
const toleranceSeconds = options.toleranceSeconds ?? 300;
|
|
6852
|
-
const valid = Boolean(timestamp2 && deliveryId) && timestampIsFresh(timestamp2, toleranceSeconds) && await verifySignature(
|
|
6853
|
-
rawBody,
|
|
6854
|
-
options.secret,
|
|
6855
|
-
signature,
|
|
6856
|
-
timestamp2,
|
|
6857
|
-
deliveryId
|
|
6858
|
-
);
|
|
6859
|
-
if (!valid) {
|
|
6860
|
-
return new Response(
|
|
6861
|
-
JSON.stringify({ error: "Invalid webhook signature" }),
|
|
6862
|
-
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
6863
|
-
);
|
|
6864
|
-
}
|
|
6865
|
-
} else {
|
|
6866
|
-
console.warn(
|
|
6867
|
-
"[@01.software/sdk] Webhook signature verification is disabled. Set { secret } in handleWebhook() options to enable HMAC-SHA256 verification."
|
|
6868
|
-
);
|
|
6869
|
-
}
|
|
6870
|
-
const body = JSON.parse(rawBody);
|
|
6871
|
-
if (!isValidWebhookEvent(body)) {
|
|
6872
|
-
return new Response(
|
|
6873
|
-
JSON.stringify({ error: "Invalid webhook event format" }),
|
|
6874
|
-
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
6875
|
-
);
|
|
6876
|
-
}
|
|
6877
|
-
await handler(body);
|
|
6878
|
-
return new Response(
|
|
6879
|
-
JSON.stringify({ success: true, message: "Webhook processed" }),
|
|
6880
|
-
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
6881
|
-
);
|
|
6882
|
-
} catch (error) {
|
|
6883
|
-
console.error("Webhook processing error:", error);
|
|
6884
|
-
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
6885
|
-
status: 500,
|
|
6886
|
-
headers: { "Content-Type": "application/json" }
|
|
6887
|
-
});
|
|
6888
|
-
}
|
|
6978
|
+
return handleSignedWebhook(request, handler, options);
|
|
6889
6979
|
}
|
|
6890
6980
|
function createTypedWebhookHandler(collection, handler) {
|
|
6891
6981
|
return async (event) => {
|
|
@@ -6925,6 +7015,7 @@ var INTERNAL_COLLECTIONS = [
|
|
|
6925
7015
|
"payment-event-inbox",
|
|
6926
7016
|
"payment-refund-attempts",
|
|
6927
7017
|
"portone-payment-interactions",
|
|
7018
|
+
"commerce-payment-webhook-routes",
|
|
6928
7019
|
"commerce-notification-intents",
|
|
6929
7020
|
"commerce-idempotency-records",
|
|
6930
7021
|
"product-collection-items",
|
|
@@ -6965,7 +7056,6 @@ var COLLECTIONS = [
|
|
|
6965
7056
|
"brands",
|
|
6966
7057
|
"customer-profiles",
|
|
6967
7058
|
"customer-profile-stats",
|
|
6968
|
-
"discounts",
|
|
6969
7059
|
"shipping-policies",
|
|
6970
7060
|
"shipping-zones",
|
|
6971
7061
|
"documents",
|
|
@@ -7041,6 +7131,9 @@ var SERVER_ONLY_COLLECTIONS = [
|
|
|
7041
7131
|
"cart-items",
|
|
7042
7132
|
"checkouts",
|
|
7043
7133
|
"checkout-items",
|
|
7134
|
+
// Raw discount definitions require a server credential. Browser discount
|
|
7135
|
+
// validation is exposed through the shaped POST /api/discounts/validate path.
|
|
7136
|
+
"discounts",
|
|
7044
7137
|
"draft-orders",
|
|
7045
7138
|
"draft-order-items",
|
|
7046
7139
|
"posts",
|
|
@@ -7206,160 +7299,6 @@ var RealtimeConnection = class {
|
|
|
7206
7299
|
}
|
|
7207
7300
|
};
|
|
7208
7301
|
|
|
7209
|
-
// src/utils/product-media.ts
|
|
7210
|
-
function mediaPointerOptionValues(values) {
|
|
7211
|
-
return (values ?? []).filter((value) => value != null && value !== "").map((value) => ({
|
|
7212
|
-
swatch: {
|
|
7213
|
-
type: "media",
|
|
7214
|
-
mediaItemId: value
|
|
7215
|
-
}
|
|
7216
|
-
}));
|
|
7217
|
-
}
|
|
7218
|
-
function resolveProductMedia(input) {
|
|
7219
|
-
const resolved = resolveProductSelectionMedia({
|
|
7220
|
-
...input,
|
|
7221
|
-
selectedVariant: input.selectedVariant ?? (input.variantFeaturedMediaItemId ? { images: [input.variantFeaturedMediaItemId] } : null),
|
|
7222
|
-
selectedOptionValues: input.selectedOptionValues ?? mediaPointerOptionValues(input.selectedOptionValueMediaItemIds)
|
|
7223
|
-
});
|
|
7224
|
-
if (resolved.source !== "none") {
|
|
7225
|
-
return {
|
|
7226
|
-
...resolved,
|
|
7227
|
-
source: resolved.source === "variant_media_selected" ? "variant_featured" : resolved.source
|
|
7228
|
-
};
|
|
7229
|
-
}
|
|
7230
|
-
const display = resolveProductDisplayMedia({
|
|
7231
|
-
productMediaPool: input.productMediaPool
|
|
7232
|
-
});
|
|
7233
|
-
return {
|
|
7234
|
-
primaryImage: display.primaryImage,
|
|
7235
|
-
images: display.images,
|
|
7236
|
-
source: display.source
|
|
7237
|
-
};
|
|
7238
|
-
}
|
|
7239
|
-
|
|
7240
|
-
// src/utils/product-gallery.ts
|
|
7241
|
-
function mediaId(value) {
|
|
7242
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
7243
|
-
return String(value);
|
|
7244
|
-
}
|
|
7245
|
-
if (typeof value === "object" && value !== null && "id" in value) {
|
|
7246
|
-
const id = value.id;
|
|
7247
|
-
if (typeof id === "string" || typeof id === "number") return String(id);
|
|
7248
|
-
}
|
|
7249
|
-
return null;
|
|
7250
|
-
}
|
|
7251
|
-
function relationshipIds(values) {
|
|
7252
|
-
if (!Array.isArray(values)) return [];
|
|
7253
|
-
return values.map((value) => mediaId(value)).filter((value) => Boolean(value));
|
|
7254
|
-
}
|
|
7255
|
-
function buildPoolById2(pool) {
|
|
7256
|
-
const poolById = /* @__PURE__ */ new Map();
|
|
7257
|
-
for (const item of pool) {
|
|
7258
|
-
const id = mediaId(item);
|
|
7259
|
-
if (id) poolById.set(id, item);
|
|
7260
|
-
}
|
|
7261
|
-
return poolById;
|
|
7262
|
-
}
|
|
7263
|
-
function mediaSetItemsInPool(mediaSet, poolById) {
|
|
7264
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7265
|
-
const items = [];
|
|
7266
|
-
const primaryId = mediaId(mediaSet.primaryMediaItemId);
|
|
7267
|
-
if (primaryId) {
|
|
7268
|
-
const primary = poolById.get(primaryId);
|
|
7269
|
-
if (primary) {
|
|
7270
|
-
seen.add(primaryId);
|
|
7271
|
-
items.push(primary);
|
|
7272
|
-
}
|
|
7273
|
-
}
|
|
7274
|
-
for (const itemId of relationshipIds(mediaSet.items)) {
|
|
7275
|
-
if (seen.has(itemId)) continue;
|
|
7276
|
-
const item = poolById.get(itemId);
|
|
7277
|
-
if (!item) continue;
|
|
7278
|
-
seen.add(itemId);
|
|
7279
|
-
items.push(item);
|
|
7280
|
-
}
|
|
7281
|
-
return items;
|
|
7282
|
-
}
|
|
7283
|
-
function resolveLegacyMediaSet(input) {
|
|
7284
|
-
if (!Array.isArray(input.mediaSets)) return null;
|
|
7285
|
-
const pool = input.productMediaPool ?? input.pool ?? [];
|
|
7286
|
-
const poolById = buildPoolById2(pool);
|
|
7287
|
-
const selectedVariantId = mediaId(input.selectedVariantId);
|
|
7288
|
-
if (selectedVariantId) {
|
|
7289
|
-
const exactSet = input.mediaSets.find(
|
|
7290
|
-
(set) => set.matchType === "exact-variant" && relationshipIds(set.variantIds).includes(selectedVariantId)
|
|
7291
|
-
);
|
|
7292
|
-
if (exactSet) {
|
|
7293
|
-
const images = mediaSetItemsInPool(exactSet, poolById);
|
|
7294
|
-
if (images.length > 0) {
|
|
7295
|
-
return {
|
|
7296
|
-
primaryImage: images[0] ?? null,
|
|
7297
|
-
images,
|
|
7298
|
-
source: "exact_variant_set"
|
|
7299
|
-
};
|
|
7300
|
-
}
|
|
7301
|
-
}
|
|
7302
|
-
}
|
|
7303
|
-
const selectedOptionValueIds = new Set(
|
|
7304
|
-
relationshipIds(input.selectedOptionValueIds)
|
|
7305
|
-
);
|
|
7306
|
-
const optionSetMatches = input.mediaSets.filter((set) => set.matchType === "option-values").map((set) => {
|
|
7307
|
-
const optionValueIds = relationshipIds(set.optionValueIds);
|
|
7308
|
-
if (optionValueIds.length === 0) return null;
|
|
7309
|
-
if (!optionValueIds.every((id) => selectedOptionValueIds.has(id))) {
|
|
7310
|
-
return null;
|
|
7311
|
-
}
|
|
7312
|
-
const images = mediaSetItemsInPool(set, poolById);
|
|
7313
|
-
if (images.length === 0) return null;
|
|
7314
|
-
return { optionValueCount: optionValueIds.length, images };
|
|
7315
|
-
}).filter(
|
|
7316
|
-
(match) => Boolean(match)
|
|
7317
|
-
).sort((a, b) => b.optionValueCount - a.optionValueCount);
|
|
7318
|
-
if (optionSetMatches.length > 0) {
|
|
7319
|
-
const images = optionSetMatches[0].images;
|
|
7320
|
-
return {
|
|
7321
|
-
primaryImage: images[0] ?? null,
|
|
7322
|
-
images,
|
|
7323
|
-
source: "option_value_set"
|
|
7324
|
-
};
|
|
7325
|
-
}
|
|
7326
|
-
const defaultSet = input.mediaSets.find((set) => set.matchType === "default");
|
|
7327
|
-
if (defaultSet) {
|
|
7328
|
-
const images = mediaSetItemsInPool(defaultSet, poolById);
|
|
7329
|
-
if (images.length > 0) {
|
|
7330
|
-
return {
|
|
7331
|
-
primaryImage: images[0] ?? null,
|
|
7332
|
-
images,
|
|
7333
|
-
source: "default_set"
|
|
7334
|
-
};
|
|
7335
|
-
}
|
|
7336
|
-
}
|
|
7337
|
-
return {
|
|
7338
|
-
primaryImage: null,
|
|
7339
|
-
images: [],
|
|
7340
|
-
source: "none"
|
|
7341
|
-
};
|
|
7342
|
-
}
|
|
7343
|
-
function resolveProductGallery(input) {
|
|
7344
|
-
const selectedVariantId = mediaId(input.selectedVariantId);
|
|
7345
|
-
const selectedOptionValueIds = relationshipIds(input.selectedOptionValueIds);
|
|
7346
|
-
const selection = resolveProductSelectionMedia({
|
|
7347
|
-
...input,
|
|
7348
|
-
productMediaPool: input.productMediaPool ?? input.pool ?? null,
|
|
7349
|
-
selectedVariant: input.selectedVariant ?? (selectedVariantId ? { id: selectedVariantId } : null),
|
|
7350
|
-
selectedOptionValues: input.selectedOptionValues ?? selectedOptionValueIds.map((id) => ({ id }))
|
|
7351
|
-
});
|
|
7352
|
-
if (selection.source !== "none") {
|
|
7353
|
-
return selection;
|
|
7354
|
-
}
|
|
7355
|
-
const legacyResolved = resolveLegacyMediaSet(input);
|
|
7356
|
-
if (legacyResolved && legacyResolved.source !== "none") return legacyResolved;
|
|
7357
|
-
return resolveProductDisplayMedia({
|
|
7358
|
-
productMediaPool: input.productMediaPool ?? input.pool ?? null,
|
|
7359
|
-
featuredImage: input.featuredImage
|
|
7360
|
-
});
|
|
7361
|
-
}
|
|
7362
|
-
|
|
7363
7302
|
// src/utils/image.ts
|
|
7364
7303
|
var IMAGE_SIZES = [200, 400, 800, 1200, 1600];
|
|
7365
7304
|
function imageSizeCandidates(sizes) {
|
|
@@ -7491,7 +7430,7 @@ function createAnalytics(config) {
|
|
|
7491
7430
|
}, destroy() {
|
|
7492
7431
|
} };
|
|
7493
7432
|
}
|
|
7494
|
-
const
|
|
7433
|
+
const endpoint = config.endpoint ?? `${resolveApiUrl()}/api/analytics/collect`;
|
|
7495
7434
|
const respectDnt = config.respectDnt !== false;
|
|
7496
7435
|
function isDntActive() {
|
|
7497
7436
|
if (!respectDnt) return false;
|
|
@@ -7532,10 +7471,10 @@ function createAnalytics(config) {
|
|
|
7532
7471
|
try {
|
|
7533
7472
|
if (typeof navigator.sendBeacon === "function") {
|
|
7534
7473
|
const blob = new Blob([body], { type: "text/plain" });
|
|
7535
|
-
const sent = navigator.sendBeacon(
|
|
7474
|
+
const sent = navigator.sendBeacon(endpoint, blob);
|
|
7536
7475
|
if (sent) return;
|
|
7537
7476
|
}
|
|
7538
|
-
fetch(
|
|
7477
|
+
fetch(endpoint, {
|
|
7539
7478
|
method: "POST",
|
|
7540
7479
|
keepalive: true,
|
|
7541
7480
|
headers: { "Content-Type": "application/json" },
|
|
@@ -7792,8 +7731,6 @@ export {
|
|
|
7792
7731
|
projectProductToListingShape,
|
|
7793
7732
|
resolveFeaturedImagePointer,
|
|
7794
7733
|
resolveProductDisplayMedia,
|
|
7795
|
-
resolveProductGallery,
|
|
7796
|
-
resolveProductMedia,
|
|
7797
7734
|
resolveProductSelection,
|
|
7798
7735
|
resolveProductSelectionFromMatrix,
|
|
7799
7736
|
resolveProductSelectionMedia,
|