@01.software/sdk 0.70.1 → 0.72.1
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 +143 -0
- package/MIGRATION.md +28 -0
- package/README.md +253 -11
- package/dist/client.cjs +396 -26
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +7 -6
- package/dist/client.d.ts +7 -6
- package/dist/client.js +396 -26
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-BHLStm1K.d.cts → collection-client-B3CnqMDQ.d.cts} +14 -18
- package/dist/{collection-client-B1FSJ24_.d.ts → collection-client-uOgS_1bC.d.ts} +14 -18
- package/dist/{const-ty8u0TDI.d.ts → const-BJBK7jBl.d.ts} +1 -1
- package/dist/{const-BfQfV-rr.d.cts → const-_ZfJjRQG.d.cts} +1 -1
- package/dist/embedded-admin/server.cjs +117 -2
- package/dist/embedded-admin/server.cjs.map +1 -1
- package/dist/embedded-admin/server.d.cts +30 -2
- package/dist/embedded-admin/server.d.ts +30 -2
- package/dist/embedded-admin/server.js +117 -2
- package/dist/embedded-admin/server.js.map +1 -1
- package/dist/embedded-admin.cjs +135 -7
- package/dist/embedded-admin.cjs.map +1 -1
- package/dist/embedded-admin.d.cts +35 -2
- package/dist/embedded-admin.d.ts +35 -2
- package/dist/embedded-admin.js +135 -7
- package/dist/embedded-admin.js.map +1 -1
- package/dist/errors.cjs +2 -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 +2 -0
- package/dist/errors.js.map +1 -1
- package/dist/{index-DnKgjPGM.d.ts → index-CBaP4q8r.d.ts} +3 -3
- package/dist/{index-CX6si6YC.d.cts → index-CI_LFWiG.d.cts} +3 -3
- package/dist/index.cjs +396 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -9
- package/dist/index.d.ts +24 -9
- package/dist/index.js +396 -26
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-DTAaWKrp.d.cts → payload-types-BRg8Yary.d.cts} +262 -177
- package/dist/{payload-types-DTAaWKrp.d.ts → payload-types-BRg8Yary.d.ts} +262 -177
- package/dist/query.cjs +20 -0
- 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 +20 -0
- 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 +459 -46
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +10 -8
- package/dist/server.d.ts +10 -8
- package/dist/server.js +459 -46
- package/dist/server.js.map +1 -1
- package/dist/storefront-cache.cjs +2 -0
- package/dist/storefront-cache.cjs.map +1 -1
- package/dist/storefront-cache.js +2 -0
- package/dist/storefront-cache.js.map +1 -1
- package/dist/{types-DdlhpNVv.d.ts → types-Cmnxxvuv.d.ts} +238 -21
- package/dist/{types-Bzgf4mTo.d.cts → types-CnkJQUez.d.cts} +238 -21
- package/dist/{types-DX8Z44yQ.d.ts → types-DLjSqL0P.d.ts} +2 -2
- package/dist/{types-CpSiyJud.d.cts → types-FyklqLAk.d.cts} +2 -2
- 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.d.cts +5 -5
- package/dist/webhook.d.ts +5 -5
- package/package.json +2 -4
package/dist/index.cjs
CHANGED
|
@@ -228,6 +228,7 @@ var COMMERCE_ERROR_CODES = [
|
|
|
228
228
|
"cart_not_active",
|
|
229
229
|
"cart_locked",
|
|
230
230
|
"cart_empty",
|
|
231
|
+
"shipping_address_required",
|
|
231
232
|
"cart_market_unavailable",
|
|
232
233
|
"cart_market_mismatch",
|
|
233
234
|
"checkout_not_open",
|
|
@@ -244,6 +245,7 @@ var COMMERCE_ERROR_CODES = [
|
|
|
244
245
|
"price_changed",
|
|
245
246
|
"pricing_fact_in_use",
|
|
246
247
|
"insufficient_stock",
|
|
248
|
+
"credit_insufficient",
|
|
247
249
|
"reservation_conflict",
|
|
248
250
|
"stock_lock_unavailable",
|
|
249
251
|
"variant_not_found",
|
|
@@ -707,6 +709,8 @@ async function parseErrorBody(response) {
|
|
|
707
709
|
try {
|
|
708
710
|
const body = await response.json();
|
|
709
711
|
const reason = typeof body.reason === "string" ? body.reason : typeof body.code === "string" ? body.code : void 0;
|
|
712
|
+
const payloadErrorReason = Array.isArray(body.errors) ? readPayloadErrorReason(body.errors) : void 0;
|
|
713
|
+
const payloadReasonField = payloadErrorReason !== void 0 ? { payloadErrorReason } : {};
|
|
710
714
|
if (body.errors && Array.isArray(body.errors)) {
|
|
711
715
|
const fieldErrors = [];
|
|
712
716
|
for (const e of body.errors) {
|
|
@@ -729,6 +733,7 @@ async function parseErrorBody(response) {
|
|
|
729
733
|
errorMessage: `HTTP ${response.status}: ${details}`,
|
|
730
734
|
userMessage: details,
|
|
731
735
|
reason,
|
|
736
|
+
...payloadReasonField,
|
|
732
737
|
body,
|
|
733
738
|
errors: fieldErrors.length > 0 ? fieldErrors : body.errors
|
|
734
739
|
};
|
|
@@ -739,6 +744,7 @@ async function parseErrorBody(response) {
|
|
|
739
744
|
errorMessage: `HTTP ${response.status}: ${body.error}`,
|
|
740
745
|
userMessage: body.error,
|
|
741
746
|
reason,
|
|
747
|
+
...payloadReasonField,
|
|
742
748
|
body
|
|
743
749
|
};
|
|
744
750
|
}
|
|
@@ -747,14 +753,23 @@ async function parseErrorBody(response) {
|
|
|
747
753
|
errorMessage: `HTTP ${response.status}: ${body.message}`,
|
|
748
754
|
userMessage: body.message,
|
|
749
755
|
reason,
|
|
756
|
+
...payloadReasonField,
|
|
750
757
|
body
|
|
751
758
|
};
|
|
752
759
|
}
|
|
753
|
-
return { ...fallback, reason, body };
|
|
760
|
+
return { ...fallback, reason, ...payloadReasonField, body };
|
|
754
761
|
} catch {
|
|
755
762
|
return fallback;
|
|
756
763
|
}
|
|
757
764
|
}
|
|
765
|
+
function readPayloadErrorReason(errors) {
|
|
766
|
+
const data = errors[0]?.data;
|
|
767
|
+
if (!data || typeof data !== "object") return void 0;
|
|
768
|
+
const { reason, code } = data;
|
|
769
|
+
if (typeof reason === "string") return reason;
|
|
770
|
+
if (typeof code === "string") return code;
|
|
771
|
+
return void 0;
|
|
772
|
+
}
|
|
758
773
|
function getParsedErrorSuggestion(status, parsed) {
|
|
759
774
|
if (status === 403 && parsed.reason === "origin_not_allowed") {
|
|
760
775
|
return "Add the request origin to the tenant Browser API origins, then retry the browser request.";
|
|
@@ -800,7 +815,10 @@ function mapResponseToError(status, parsed, details, requestId, retryAfter, cano
|
|
|
800
815
|
if (retryAfter !== void 0) {
|
|
801
816
|
Object.assign(withRequestId, { retryAfter });
|
|
802
817
|
}
|
|
803
|
-
return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(
|
|
818
|
+
return canonicalCommerceError ? enhanceCommerceError(withRequestId, parsed.body, requestId) : enhanceNonCommerceError(
|
|
819
|
+
withRequestId,
|
|
820
|
+
parsed.reason ?? parsed.payloadErrorReason
|
|
821
|
+
);
|
|
804
822
|
};
|
|
805
823
|
if (status === 400 || status === 422) {
|
|
806
824
|
return finalize(
|
|
@@ -1219,6 +1237,7 @@ async function parseApiResponse(response, endpoint, options = {}) {
|
|
|
1219
1237
|
// ../../internal/http-contracts/src/index.ts
|
|
1220
1238
|
var operationBrand = /* @__PURE__ */ Symbol("sdk-http-operation");
|
|
1221
1239
|
var PORTONE_STANDARD_ACTION_CAPABILITIES_MEDIA_TYPE = "application/vnd.01software.portone-action-capabilities.v1+json";
|
|
1240
|
+
var CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE = "application/vnd.01software.credit-funding.v1+json";
|
|
1222
1241
|
var operation = (collection, method, path, errorFamily) => Object.freeze({
|
|
1223
1242
|
[operationBrand]: true,
|
|
1224
1243
|
collection,
|
|
@@ -1382,6 +1401,11 @@ var portOneStandardActionCapabilityOperations = /* @__PURE__ */ new Set([
|
|
|
1382
1401
|
]);
|
|
1383
1402
|
var MEMBERSHIP_ENDPOINT_OPERATIONS = {
|
|
1384
1403
|
subscribe: operation(null, "post", "/memberships/subscribe"),
|
|
1404
|
+
endSubscribeIntent: operation(
|
|
1405
|
+
null,
|
|
1406
|
+
"post",
|
|
1407
|
+
"/memberships/subscribe-intent/end"
|
|
1408
|
+
),
|
|
1385
1409
|
billingCustody: operation(null, "post", "/memberships/billing-custody"),
|
|
1386
1410
|
cancel: operation(null, "post", "/memberships/:id/cancel"),
|
|
1387
1411
|
me: operation(null, "get", "/memberships/me"),
|
|
@@ -1427,6 +1451,19 @@ var BENEFIT_VOUCHER_ENDPOINT_OPERATIONS = {
|
|
|
1427
1451
|
void: operation("customers", "post", "/benefit-vouchers/void"),
|
|
1428
1452
|
listMine: operation("customers", "get", "/me/benefit-vouchers")
|
|
1429
1453
|
};
|
|
1454
|
+
var CUSTOMER_CREDIT_ENDPOINT_OPERATIONS = {
|
|
1455
|
+
grant: strictCommerceOperation("customers", "post", "/credits/grant"),
|
|
1456
|
+
getGrant: strictCommerceOperation("customers", "post", "/credits/get-grant"),
|
|
1457
|
+
getAccount: strictCommerceOperation("customers", "post", "/credits/account"),
|
|
1458
|
+
revoke: strictCommerceOperation("customers", "post", "/credits/revoke"),
|
|
1459
|
+
mine: strictCommerceOperation("customers", "get", "/me/credits"),
|
|
1460
|
+
history: strictCommerceOperation("customers", "get", "/me/credits/history"),
|
|
1461
|
+
configure: strictCommerceOperation(
|
|
1462
|
+
"customers",
|
|
1463
|
+
"post",
|
|
1464
|
+
"/credits/configuration"
|
|
1465
|
+
)
|
|
1466
|
+
};
|
|
1430
1467
|
var CUSTOMER_GROUP_ENDPOINT_OPERATIONS = {
|
|
1431
1468
|
members: operation("customer-groups", "get", "/:id/members"),
|
|
1432
1469
|
grant: operation("customer-groups", "post", "/:id/members/grant"),
|
|
@@ -1816,6 +1853,140 @@ var CustomerBenefitVouchersApi = class extends CustomerScopedApi {
|
|
|
1816
1853
|
}
|
|
1817
1854
|
};
|
|
1818
1855
|
|
|
1856
|
+
// src/core/api/customer-credit-types.ts
|
|
1857
|
+
function invalid() {
|
|
1858
|
+
throw createApiError("Invalid customer credit response", 502);
|
|
1859
|
+
}
|
|
1860
|
+
function object2(value, keys) {
|
|
1861
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(value, key)))
|
|
1862
|
+
invalid();
|
|
1863
|
+
return value;
|
|
1864
|
+
}
|
|
1865
|
+
function money(value) {
|
|
1866
|
+
return typeof value === "string" && /^(0|[1-9][0-9]*)$/.test(value);
|
|
1867
|
+
}
|
|
1868
|
+
function uuid2(value) {
|
|
1869
|
+
return typeof value === "string" && /^([0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i.test(
|
|
1870
|
+
value
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
function time2(value) {
|
|
1874
|
+
if (typeof value !== "string") return false;
|
|
1875
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z$/.exec(value);
|
|
1876
|
+
if (!match) return false;
|
|
1877
|
+
const [, year, month, day, hour, minute, second = "0"] = match;
|
|
1878
|
+
const y = Number(year), m = Number(month), d = Number(day);
|
|
1879
|
+
const days = [
|
|
1880
|
+
31,
|
|
1881
|
+
y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 29 : 28,
|
|
1882
|
+
31,
|
|
1883
|
+
30,
|
|
1884
|
+
31,
|
|
1885
|
+
30,
|
|
1886
|
+
31,
|
|
1887
|
+
31,
|
|
1888
|
+
30,
|
|
1889
|
+
31,
|
|
1890
|
+
30,
|
|
1891
|
+
31
|
|
1892
|
+
];
|
|
1893
|
+
return m >= 1 && m <= 12 && d >= 1 && d <= days[m - 1] && Number(hour) < 24 && Number(minute) < 60 && Number(second) < 60;
|
|
1894
|
+
}
|
|
1895
|
+
var states = ["available", "held", "spent", "expired", "revoked"];
|
|
1896
|
+
function balances(value) {
|
|
1897
|
+
const data = object2(value, states);
|
|
1898
|
+
if (states.some((key) => !money(data[key]))) invalid();
|
|
1899
|
+
}
|
|
1900
|
+
function page(value) {
|
|
1901
|
+
if (value.currency !== "KRW" || !time2(value.evaluatedAt) || !Number.isSafeInteger(value.page) || value.page < 1 || typeof value.hasNextPage !== "boolean")
|
|
1902
|
+
invalid();
|
|
1903
|
+
}
|
|
1904
|
+
function parseMyCustomerCredits(value) {
|
|
1905
|
+
const data = object2(value, [
|
|
1906
|
+
"currency",
|
|
1907
|
+
"evaluatedAt",
|
|
1908
|
+
"granted",
|
|
1909
|
+
"balances",
|
|
1910
|
+
"buckets",
|
|
1911
|
+
"page",
|
|
1912
|
+
"hasNextPage"
|
|
1913
|
+
]);
|
|
1914
|
+
page(data);
|
|
1915
|
+
balances(data.balances);
|
|
1916
|
+
if (!money(data.granted) || !Array.isArray(data.buckets) || data.buckets.length > 50)
|
|
1917
|
+
invalid();
|
|
1918
|
+
for (const value2 of data.buckets) {
|
|
1919
|
+
const bucket = object2(value2, [
|
|
1920
|
+
"id",
|
|
1921
|
+
"grantId",
|
|
1922
|
+
"kind",
|
|
1923
|
+
"grantedAt",
|
|
1924
|
+
"expiresAt",
|
|
1925
|
+
"isRevoked",
|
|
1926
|
+
"balances"
|
|
1927
|
+
]);
|
|
1928
|
+
if (!uuid2(bucket.id) || !uuid2(bucket.grantId) || !["original", "grace"].includes(bucket.kind) || !time2(bucket.grantedAt) || !time2(bucket.expiresAt) || typeof bucket.isRevoked !== "boolean")
|
|
1929
|
+
invalid();
|
|
1930
|
+
balances(bucket.balances);
|
|
1931
|
+
}
|
|
1932
|
+
return value;
|
|
1933
|
+
}
|
|
1934
|
+
function parseMyCustomerCreditHistory(value) {
|
|
1935
|
+
const data = object2(value, [
|
|
1936
|
+
"currency",
|
|
1937
|
+
"evaluatedAt",
|
|
1938
|
+
"entries",
|
|
1939
|
+
"page",
|
|
1940
|
+
"hasNextPage"
|
|
1941
|
+
]);
|
|
1942
|
+
page(data);
|
|
1943
|
+
if (!Array.isArray(data.entries) || data.entries.length > 50) invalid();
|
|
1944
|
+
for (const value2 of data.entries) {
|
|
1945
|
+
const entry = object2(value2, [
|
|
1946
|
+
"id",
|
|
1947
|
+
"grantId",
|
|
1948
|
+
"kind",
|
|
1949
|
+
"amount",
|
|
1950
|
+
"fromState",
|
|
1951
|
+
"toState",
|
|
1952
|
+
"createdAt"
|
|
1953
|
+
]);
|
|
1954
|
+
if (!uuid2(entry.id) || !uuid2(entry.grantId) || !money(entry.amount) || !time2(entry.createdAt) || ![
|
|
1955
|
+
"grant",
|
|
1956
|
+
"reserve",
|
|
1957
|
+
"consume",
|
|
1958
|
+
"release",
|
|
1959
|
+
"restore",
|
|
1960
|
+
"expire",
|
|
1961
|
+
"revoke"
|
|
1962
|
+
].includes(entry.kind) || entry.fromState !== null && !states.includes(entry.fromState) || entry.toState !== null && !states.includes(entry.toState))
|
|
1963
|
+
invalid();
|
|
1964
|
+
}
|
|
1965
|
+
return value;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
// src/core/api/customer-credits-api.ts
|
|
1969
|
+
var CustomerCreditsApi = class extends CustomerScopedApi {
|
|
1970
|
+
async mine(params = {}) {
|
|
1971
|
+
const query = new URLSearchParams();
|
|
1972
|
+
if (params.page !== void 0) query.set("page", String(params.page));
|
|
1973
|
+
return parseMyCustomerCredits(
|
|
1974
|
+
await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.mine, void 0, {
|
|
1975
|
+
query
|
|
1976
|
+
})
|
|
1977
|
+
);
|
|
1978
|
+
}
|
|
1979
|
+
async history(params = {}) {
|
|
1980
|
+
const query = new URLSearchParams();
|
|
1981
|
+
if (params.page !== void 0) query.set("page", String(params.page));
|
|
1982
|
+
return parseMyCustomerCreditHistory(
|
|
1983
|
+
await this.requestEndpoint(CUSTOMER_CREDIT_ENDPOINT_OPERATIONS.history, void 0, {
|
|
1984
|
+
query
|
|
1985
|
+
})
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
|
|
1819
1990
|
// src/core/collection/http-client.ts
|
|
1820
1991
|
var import_qs_esm = require("qs-esm");
|
|
1821
1992
|
function validateWhere(where) {
|
|
@@ -2273,11 +2444,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
2273
2444
|
* - `rootComment`: comments belonging to a thread rooted at that comment.
|
|
2274
2445
|
*/
|
|
2275
2446
|
listComments(params) {
|
|
2276
|
-
const { postId, page, limit, rootComment, topLevelOnly, sort } = params;
|
|
2447
|
+
const { postId, page: page2, limit, rootComment, topLevelOnly, sort } = params;
|
|
2277
2448
|
return this.execute(
|
|
2278
2449
|
this.buildCommentsListQuery({
|
|
2279
2450
|
postId,
|
|
2280
|
-
page,
|
|
2451
|
+
page: page2,
|
|
2281
2452
|
limit,
|
|
2282
2453
|
rootComment,
|
|
2283
2454
|
topLevelOnly,
|
|
@@ -2288,11 +2459,11 @@ var CommunityClient = class extends RawCustomerScopedApi {
|
|
|
2288
2459
|
}
|
|
2289
2460
|
/** Direct replies to a comment (`where[parent][equals]`). */
|
|
2290
2461
|
listReplies(params) {
|
|
2291
|
-
const { commentId, page, limit, sort } = params;
|
|
2462
|
+
const { commentId, page: page2, limit, sort } = params;
|
|
2292
2463
|
return this.execute(
|
|
2293
2464
|
this.buildCommentsListQuery({
|
|
2294
2465
|
parentId: commentId,
|
|
2295
|
-
page,
|
|
2466
|
+
page: page2,
|
|
2296
2467
|
limit,
|
|
2297
2468
|
sort
|
|
2298
2469
|
}),
|
|
@@ -2549,7 +2720,18 @@ var ABANDONED_REASONS = ["expired", "customer", "operator"];
|
|
|
2549
2720
|
function managedPaymentProviders(providers) {
|
|
2550
2721
|
return providers;
|
|
2551
2722
|
}
|
|
2552
|
-
var PAYMENT_PROVIDERS = managedPaymentProviders([
|
|
2723
|
+
var PAYMENT_PROVIDERS = managedPaymentProviders([
|
|
2724
|
+
"toss",
|
|
2725
|
+
"portone",
|
|
2726
|
+
"stripe"
|
|
2727
|
+
]);
|
|
2728
|
+
var CANCEL_RECOVERY_METHODS = {
|
|
2729
|
+
toss: "cancel()",
|
|
2730
|
+
portone: "cancelPortOne()",
|
|
2731
|
+
stripe: null
|
|
2732
|
+
};
|
|
2733
|
+
var STRIPE_RETURN_URL_RAW_CHARACTERS = /^[^\s\u0000-\u001F\u007F\\]+$/;
|
|
2734
|
+
var STRIPE_RETURN_URL_AUTHORITY = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+(?:[/?#]|$)/;
|
|
2553
2735
|
var PAYMENT_PROVIDER_STATUSES = [
|
|
2554
2736
|
"requires_payment_method",
|
|
2555
2737
|
"requires_action",
|
|
@@ -2598,11 +2780,8 @@ function fail(resource, path, expected) {
|
|
|
2598
2780
|
invalidCanonicalResponse(resource, { path, expected });
|
|
2599
2781
|
}
|
|
2600
2782
|
function providerMismatch(resource, expected, actual, operation2) {
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
toss: "cancel()",
|
|
2604
|
-
portone: "cancelPortOne()"
|
|
2605
|
-
}[actual];
|
|
2783
|
+
const method = CANCEL_RECOVERY_METHODS[actual];
|
|
2784
|
+
if (operation2 === "cancel" && method !== null) {
|
|
2606
2785
|
throw createApiError(
|
|
2607
2786
|
`Canonical ${resource} response provider mismatch: expected ${expected}, received ${actual}.`,
|
|
2608
2787
|
502,
|
|
@@ -2631,6 +2810,17 @@ function exact(value, required, optional, resource, path) {
|
|
|
2631
2810
|
const unexpected = Object.keys(value).find((key) => !allowed.has(key));
|
|
2632
2811
|
if (unexpected) fail(resource, `${path}.${unexpected}`, "no unknown fields");
|
|
2633
2812
|
}
|
|
2813
|
+
function responseExtensionKeys(value, keys, resource, path) {
|
|
2814
|
+
if (!keys.some((key) => Object.prototype.hasOwnProperty.call(value, key)))
|
|
2815
|
+
return [];
|
|
2816
|
+
enumValue(
|
|
2817
|
+
value.deliveryMethod,
|
|
2818
|
+
["shipping", "pickup"],
|
|
2819
|
+
resource,
|
|
2820
|
+
`${path}.deliveryMethod`
|
|
2821
|
+
);
|
|
2822
|
+
return [...keys];
|
|
2823
|
+
}
|
|
2634
2824
|
function string(value, resource, path) {
|
|
2635
2825
|
if (typeof value !== "string" || value.length === 0) {
|
|
2636
2826
|
fail(resource, path, "non-empty string");
|
|
@@ -2970,6 +3160,12 @@ function validatePublicCart(value, resource = "Cart") {
|
|
|
2970
3160
|
exact(
|
|
2971
3161
|
cart,
|
|
2972
3162
|
[
|
|
3163
|
+
...responseExtensionKeys(
|
|
3164
|
+
cart,
|
|
3165
|
+
["deliveryMethod", "shippingMinor", "totalMinor"],
|
|
3166
|
+
resource,
|
|
3167
|
+
"$"
|
|
3168
|
+
),
|
|
2973
3169
|
"id",
|
|
2974
3170
|
"status",
|
|
2975
3171
|
"revision",
|
|
@@ -3040,6 +3236,13 @@ function validatePublicCart(value, resource = "Cart") {
|
|
|
3040
3236
|
if (expectedSubtotal - BigInt(discount) < 0n || BigInt(estimatedTotal) !== expectedSubtotal - BigInt(discount)) {
|
|
3041
3237
|
fail(resource, "$.estimatedTotalMinor", "subtotalMinor - discountMinor");
|
|
3042
3238
|
}
|
|
3239
|
+
if ("deliveryMethod" in cart) {
|
|
3240
|
+
const shipping = safeMinor(cart.shippingMinor, resource, "$.shippingMinor");
|
|
3241
|
+
const total = safeMinor(cart.totalMinor, resource, "$.totalMinor");
|
|
3242
|
+
if (BigInt(total) !== BigInt(estimatedTotal) + BigInt(shipping)) {
|
|
3243
|
+
fail(resource, "$.totalMinor", "estimatedTotalMinor + shippingMinor");
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3043
3246
|
timestamp(cart.expiresAt, resource, "$.expiresAt");
|
|
3044
3247
|
timestamp(cart.createdAt, resource, "$.createdAt");
|
|
3045
3248
|
timestamp(cart.updatedAt, resource, "$.updatedAt");
|
|
@@ -3198,6 +3401,12 @@ function validatePublicOrderAt(value, resource, path) {
|
|
|
3198
3401
|
exact(
|
|
3199
3402
|
order,
|
|
3200
3403
|
[
|
|
3404
|
+
...responseExtensionKeys(
|
|
3405
|
+
order,
|
|
3406
|
+
["deliveryMethod", "pickup", "source"],
|
|
3407
|
+
resource,
|
|
3408
|
+
path
|
|
3409
|
+
),
|
|
3201
3410
|
"id",
|
|
3202
3411
|
"orderNumber",
|
|
3203
3412
|
"amounts",
|
|
@@ -3219,6 +3428,37 @@ function validatePublicOrderAt(value, resource, path) {
|
|
|
3219
3428
|
resource,
|
|
3220
3429
|
path
|
|
3221
3430
|
);
|
|
3431
|
+
if ("deliveryMethod" in order) {
|
|
3432
|
+
enumValue(
|
|
3433
|
+
order.source,
|
|
3434
|
+
["web", "app", "manual", "api", "import", "in_person"],
|
|
3435
|
+
resource,
|
|
3436
|
+
`${path}.source`
|
|
3437
|
+
);
|
|
3438
|
+
if (order.deliveryMethod === "shipping") {
|
|
3439
|
+
if (order.pickup !== null)
|
|
3440
|
+
fail(resource, `${path}.pickup`, "null for shipping");
|
|
3441
|
+
} else {
|
|
3442
|
+
const pickup = record(order.pickup, resource, `${path}.pickup`);
|
|
3443
|
+
exact(
|
|
3444
|
+
pickup,
|
|
3445
|
+
["status", "readyAt", "pickedUpAt"],
|
|
3446
|
+
[],
|
|
3447
|
+
resource,
|
|
3448
|
+
`${path}.pickup`
|
|
3449
|
+
);
|
|
3450
|
+
enumValue(
|
|
3451
|
+
pickup.status,
|
|
3452
|
+
["pending", "ready_for_pickup", "picked_up", "canceled"],
|
|
3453
|
+
resource,
|
|
3454
|
+
`${path}.pickup.status`
|
|
3455
|
+
);
|
|
3456
|
+
for (const key of ["readyAt", "pickedUpAt"]) {
|
|
3457
|
+
if (pickup[key] !== null)
|
|
3458
|
+
timestamp(pickup[key], resource, `${path}.pickup.${key}`);
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
}
|
|
3222
3462
|
string(order.id, resource, `${path}.id`);
|
|
3223
3463
|
string(order.orderNumber, resource, `${path}.orderNumber`);
|
|
3224
3464
|
const amounts = record(order.amounts, resource, `${path}.amounts`);
|
|
@@ -3539,6 +3779,17 @@ function validateCheckoutCore(value, resource, list, server) {
|
|
|
3539
3779
|
"$.status"
|
|
3540
3780
|
);
|
|
3541
3781
|
const keys = checkoutVariantKeys(status, checkout.placedVia);
|
|
3782
|
+
keys.required.push(
|
|
3783
|
+
...responseExtensionKeys(
|
|
3784
|
+
checkout,
|
|
3785
|
+
["deliveryMethod", "source"],
|
|
3786
|
+
resource,
|
|
3787
|
+
"$"
|
|
3788
|
+
)
|
|
3789
|
+
);
|
|
3790
|
+
if ("deliveryMethod" in checkout)
|
|
3791
|
+
enumValue(checkout.source, ["web", "in_person"], resource, "$.source");
|
|
3792
|
+
keys.optional.push("funding");
|
|
3542
3793
|
if (list) {
|
|
3543
3794
|
keys.required = keys.required.filter(
|
|
3544
3795
|
(key) => !["items", "shippingAddress", "attributes"].includes(key)
|
|
@@ -3550,6 +3801,33 @@ function validateCheckoutCore(value, resource, list, server) {
|
|
|
3550
3801
|
exact(checkout, keys.required, keys.optional, resource, "$");
|
|
3551
3802
|
string(checkout.id, resource, "$.id");
|
|
3552
3803
|
validateCheckoutAmounts(checkout.amounts, resource, "$.amounts");
|
|
3804
|
+
if (Object.prototype.hasOwnProperty.call(checkout, "funding")) {
|
|
3805
|
+
const funding = record(checkout.funding, resource, "$.funding");
|
|
3806
|
+
exact(
|
|
3807
|
+
funding,
|
|
3808
|
+
["creditAmount", "providerPayableAmount"],
|
|
3809
|
+
[],
|
|
3810
|
+
resource,
|
|
3811
|
+
"$.funding"
|
|
3812
|
+
);
|
|
3813
|
+
const credit = safeMinor(
|
|
3814
|
+
funding.creditAmount,
|
|
3815
|
+
resource,
|
|
3816
|
+
"$.funding.creditAmount"
|
|
3817
|
+
);
|
|
3818
|
+
const provider = safeMinor(
|
|
3819
|
+
funding.providerPayableAmount,
|
|
3820
|
+
resource,
|
|
3821
|
+
"$.funding.providerPayableAmount"
|
|
3822
|
+
);
|
|
3823
|
+
const amounts = checkout.amounts;
|
|
3824
|
+
if (BigInt(credit) + BigInt(provider) !== BigInt(amounts.totalMinor) || credit > 0 && amounts.currency !== "KRW")
|
|
3825
|
+
fail(
|
|
3826
|
+
resource,
|
|
3827
|
+
"$.funding",
|
|
3828
|
+
"exact purchase total split; positive credits require KRW"
|
|
3829
|
+
);
|
|
3830
|
+
}
|
|
3553
3831
|
if (!list) {
|
|
3554
3832
|
const items = array(checkout.items, resource, "$.items");
|
|
3555
3833
|
if (items.length === 0) fail(resource, "$.items", "non-empty array");
|
|
@@ -3708,10 +3986,10 @@ function validateCheckoutQueryResult(value) {
|
|
|
3708
3986
|
return value;
|
|
3709
3987
|
}
|
|
3710
3988
|
function validateMoney(value, resource, path) {
|
|
3711
|
-
const
|
|
3712
|
-
exact(
|
|
3713
|
-
safeMinor(
|
|
3714
|
-
currency(
|
|
3989
|
+
const money2 = record(value, resource, path);
|
|
3990
|
+
exact(money2, ["amountMinor", "currency"], [], resource, path);
|
|
3991
|
+
safeMinor(money2.amountMinor, resource, `${path}.amountMinor`);
|
|
3992
|
+
currency(money2.currency, resource, `${path}.currency`);
|
|
3715
3993
|
}
|
|
3716
3994
|
function validateCaptureEvidence(value, resource, path) {
|
|
3717
3995
|
const evidence = record(value, resource, path);
|
|
@@ -3747,6 +4025,65 @@ function validateRequiredReconciliation(value, allowed, resource, path) {
|
|
|
3747
4025
|
}
|
|
3748
4026
|
function validateNextAction(value, provider, resource, path) {
|
|
3749
4027
|
const action = record(value, resource, path);
|
|
4028
|
+
if (provider === "stripe") {
|
|
4029
|
+
exact(
|
|
4030
|
+
action,
|
|
4031
|
+
["type", "clientSecret", "publishableKey", "returnUrl"],
|
|
4032
|
+
[],
|
|
4033
|
+
resource,
|
|
4034
|
+
path
|
|
4035
|
+
);
|
|
4036
|
+
if (action.type !== "stripe_payment_element")
|
|
4037
|
+
fail(resource, `${path}.type`, "stripe_payment_element");
|
|
4038
|
+
const clientSecret = boundedString(
|
|
4039
|
+
action.clientSecret,
|
|
4040
|
+
255,
|
|
4041
|
+
resource,
|
|
4042
|
+
`${path}.clientSecret`
|
|
4043
|
+
);
|
|
4044
|
+
if (!/^pi_[A-Za-z0-9]+_secret_[A-Za-z0-9]+$/.test(clientSecret)) {
|
|
4045
|
+
fail(
|
|
4046
|
+
resource,
|
|
4047
|
+
`${path}.clientSecret`,
|
|
4048
|
+
"Stripe PaymentIntent client secret"
|
|
4049
|
+
);
|
|
4050
|
+
}
|
|
4051
|
+
const publishableKey = boundedString(
|
|
4052
|
+
action.publishableKey,
|
|
4053
|
+
255,
|
|
4054
|
+
resource,
|
|
4055
|
+
`${path}.publishableKey`
|
|
4056
|
+
);
|
|
4057
|
+
if (!/^pk_(?:test|live)_[A-Za-z0-9]+$/.test(publishableKey)) {
|
|
4058
|
+
fail(resource, `${path}.publishableKey`, "Stripe publishable key");
|
|
4059
|
+
}
|
|
4060
|
+
const returnUrl = boundedString(
|
|
4061
|
+
action.returnUrl,
|
|
4062
|
+
2048,
|
|
4063
|
+
resource,
|
|
4064
|
+
`${path}.returnUrl`
|
|
4065
|
+
);
|
|
4066
|
+
if (!STRIPE_RETURN_URL_RAW_CHARACTERS.test(returnUrl) || !STRIPE_RETURN_URL_AUTHORITY.test(returnUrl)) {
|
|
4067
|
+
fail(
|
|
4068
|
+
resource,
|
|
4069
|
+
`${path}.returnUrl`,
|
|
4070
|
+
"HTTPS or loopback URL without embedded credentials"
|
|
4071
|
+
);
|
|
4072
|
+
}
|
|
4073
|
+
try {
|
|
4074
|
+
const parsed = new URL(returnUrl);
|
|
4075
|
+
const loopback = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
|
|
4076
|
+
if (!loopback && parsed.protocol !== "https:" || parsed.username || parsed.password)
|
|
4077
|
+
throw new Error("unsafe return URL");
|
|
4078
|
+
} catch {
|
|
4079
|
+
fail(
|
|
4080
|
+
resource,
|
|
4081
|
+
`${path}.returnUrl`,
|
|
4082
|
+
"HTTPS or loopback URL without embedded credentials"
|
|
4083
|
+
);
|
|
4084
|
+
}
|
|
4085
|
+
return;
|
|
4086
|
+
}
|
|
3750
4087
|
if (provider === "portone") {
|
|
3751
4088
|
if (action.type === "portone_sdk") {
|
|
3752
4089
|
const hasCancelable = "cancelable" in action;
|
|
@@ -4122,7 +4459,7 @@ function validatePublicPaymentSession(value, expectedProvider, operation2) {
|
|
|
4122
4459
|
);
|
|
4123
4460
|
}
|
|
4124
4461
|
if (expectedProvider !== void 0 && provider !== expectedProvider) {
|
|
4125
|
-
if (operation2 === "cancel" && status !== "canceling" && status !== "canceled") {
|
|
4462
|
+
if (operation2 === "cancel" && CANCEL_RECOVERY_METHODS[provider] !== null && status !== "canceling" && status !== "canceled") {
|
|
4126
4463
|
fail(
|
|
4127
4464
|
resource,
|
|
4128
4465
|
"$.providerStatus",
|
|
@@ -5018,8 +5355,9 @@ var CheckoutApi = class extends CustomerScopedApi {
|
|
|
5018
5355
|
}
|
|
5019
5356
|
post(endpoint, body, idempotencyKey) {
|
|
5020
5357
|
return this.requestEndpoint(endpoint, body, {
|
|
5021
|
-
|
|
5022
|
-
|
|
5358
|
+
headers: {
|
|
5359
|
+
Accept: CUSTOMER_CREDIT_FUNDING_MEDIA_TYPE,
|
|
5360
|
+
...idempotencyKey && { "X-Idempotency-Key": idempotencyKey }
|
|
5023
5361
|
}
|
|
5024
5362
|
});
|
|
5025
5363
|
}
|
|
@@ -5029,34 +5367,58 @@ var CheckoutApi = class extends CustomerScopedApi {
|
|
|
5029
5367
|
async serverCheckout(result) {
|
|
5030
5368
|
return validateServerCheckout(await result);
|
|
5031
5369
|
}
|
|
5032
|
-
async createResult(result) {
|
|
5033
|
-
|
|
5370
|
+
async createResult(result, creditAmount) {
|
|
5371
|
+
const parsed = validateCreateCheckoutResult(
|
|
5034
5372
|
await result,
|
|
5035
5373
|
false
|
|
5036
5374
|
);
|
|
5375
|
+
this.assertRequestedCredit(parsed.checkout, creditAmount);
|
|
5376
|
+
return parsed;
|
|
5037
5377
|
}
|
|
5038
|
-
async createServerResult(result) {
|
|
5039
|
-
|
|
5378
|
+
async createServerResult(result, creditAmount) {
|
|
5379
|
+
const parsed = validateCreateCheckoutResult(
|
|
5040
5380
|
await result,
|
|
5041
5381
|
true
|
|
5042
5382
|
);
|
|
5383
|
+
this.assertRequestedCredit(parsed.checkout, creditAmount);
|
|
5384
|
+
return parsed;
|
|
5385
|
+
}
|
|
5386
|
+
assertCreditInput(amount) {
|
|
5387
|
+
if (amount !== void 0 && (!Number.isSafeInteger(amount) || amount <= 0))
|
|
5388
|
+
throw createValidationError(
|
|
5389
|
+
"creditAmount must be a positive safe integer."
|
|
5390
|
+
);
|
|
5391
|
+
}
|
|
5392
|
+
assertRequestedCredit(checkout, requested) {
|
|
5393
|
+
if (requested !== void 0 && checkout.funding?.creditAmount !== requested)
|
|
5394
|
+
throw createApiError(
|
|
5395
|
+
"Credit funding was not confirmed by the server.",
|
|
5396
|
+
502,
|
|
5397
|
+
{ resource: "Checkout", path: "$.funding" },
|
|
5398
|
+
"The response does not confirm the requested credit funding.",
|
|
5399
|
+
"Retry the same create with the original idempotency key and credit amount, or retrieve the Checkout; never retry without credit."
|
|
5400
|
+
);
|
|
5043
5401
|
}
|
|
5044
5402
|
create(params) {
|
|
5045
5403
|
const { idempotencyKey, ...body } = params;
|
|
5046
5404
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
5405
|
+
this.assertCreditInput(body.creditAmount);
|
|
5047
5406
|
return this.createResult(
|
|
5048
|
-
this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey)
|
|
5407
|
+
this.post(COMMERCE_ENDPOINTS.checkouts.create, body, idempotencyKey),
|
|
5408
|
+
body.creditAmount
|
|
5049
5409
|
);
|
|
5050
5410
|
}
|
|
5051
5411
|
createServer(params) {
|
|
5052
5412
|
const { idempotencyKey, ...body } = params;
|
|
5053
5413
|
assertCommerceIdempotencyKey(idempotencyKey);
|
|
5414
|
+
this.assertCreditInput(body.creditAmount);
|
|
5054
5415
|
return this.createServerResult(
|
|
5055
5416
|
this.post(
|
|
5056
5417
|
COMMERCE_ENDPOINTS.checkouts.server.create,
|
|
5057
5418
|
body,
|
|
5058
5419
|
idempotencyKey
|
|
5059
|
-
)
|
|
5420
|
+
),
|
|
5421
|
+
body.creditAmount
|
|
5060
5422
|
);
|
|
5061
5423
|
}
|
|
5062
5424
|
retrieve(params) {
|
|
@@ -7434,6 +7796,13 @@ var Client = class _Client {
|
|
|
7434
7796
|
this.markets = new MarketDiscovery(
|
|
7435
7797
|
(options2) => this.collections.from("markets").find(options2)
|
|
7436
7798
|
);
|
|
7799
|
+
this.credits = new CustomerCreditsApi("CustomerCreditsApi", {
|
|
7800
|
+
publishableKey: this.config.publishableKey,
|
|
7801
|
+
apiUrl: this.config.apiUrl,
|
|
7802
|
+
customerToken: () => this.customer.auth.getToken(),
|
|
7803
|
+
onUnauthorized,
|
|
7804
|
+
onRequestId
|
|
7805
|
+
});
|
|
7437
7806
|
this.benefitVouchers = new CustomerBenefitVouchersApi(
|
|
7438
7807
|
"CustomerBenefitVouchersApi",
|
|
7439
7808
|
{
|
|
@@ -7464,7 +7833,8 @@ var Client = class _Client {
|
|
|
7464
7833
|
...this.config,
|
|
7465
7834
|
customer: this.config.customer?.persist === false ? {
|
|
7466
7835
|
...this.config.customer,
|
|
7467
|
-
token: this.customer.auth.getToken() ?? void 0
|
|
7836
|
+
token: this.customer.auth.getToken() ?? void 0,
|
|
7837
|
+
refreshToken: this.customer.auth.getRefreshToken() ?? void 0
|
|
7468
7838
|
} : this.config.customer,
|
|
7469
7839
|
market
|
|
7470
7840
|
});
|