@cimplify/sdk 0.104.0 → 0.104.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/dist/advanced.d.mts +3 -7
- package/dist/advanced.d.ts +3 -7
- package/dist/advanced.js +23 -23
- package/dist/advanced.mjs +4 -4
- package/dist/{client-BuLcOWLv.d.ts → catalogue-BlQ85Uma.d.mts} +415 -763
- package/dist/{client-D5AoobFc.d.mts → catalogue-C8TqOj9K.d.ts} +415 -763
- package/dist/{payment-g0HFkEDU.d.mts → checkout-BqK9XUz5.d.mts} +3824 -1446
- package/dist/{payment-g0HFkEDU.d.ts → checkout-BqK9XUz5.d.ts} +3824 -1446
- package/dist/{chunk-GOHSXBKW.mjs → chunk-33VCYWVL.mjs} +25 -1
- package/dist/{chunk-2WPVUIHX.mjs → chunk-6G3ANKQA.mjs} +1030 -360
- package/dist/{chunk-E4K2VQDD.js → chunk-BWEIMKLF.js} +541 -16
- package/dist/{chunk-IQFFSKE2.js → chunk-DQEXY542.js} +1345 -746
- package/dist/{chunk-CNN7Z2IP.js → chunk-EV2EVOYS.js} +27 -0
- package/dist/{chunk-YVAEY3VC.js → chunk-HYFA67A7.js} +1034 -364
- package/dist/{chunk-5RT4HYMP.mjs → chunk-L5SNEU2O.mjs} +524 -15
- package/dist/{chunk-4BKOKHE3.js → chunk-RBNBSQI7.mjs} +217 -19
- package/dist/{chunk-H3RATH4B.mjs → chunk-SFUJMS5E.js} +261 -2
- package/dist/{chunk-DYIAX3WI.mjs → chunk-U54CWUUT.mjs} +11 -2
- package/dist/{chunk-OKADBZAI.mjs → chunk-UFOWPN3D.mjs} +808 -574
- package/dist/{chunk-OCCNG6MO.mjs → chunk-V4457OKB.mjs} +1310 -722
- package/dist/{chunk-5BDYDZ4U.js → chunk-WXREIBFW.js} +892 -657
- package/dist/{chunk-7PDEX54K.js → chunk-XAUSDMMZ.js} +13 -3
- package/dist/{client-BVNWjk6W.d.ts → client-DhXeiUrf.d.ts} +2 -2
- package/dist/{client-fM716k7G.d.mts → client-mXiUrV4X.d.mts} +2 -2
- package/dist/{index-BtcoqrY1.d.ts → index-B0AdZvrM.d.mts} +9 -4
- package/dist/{index-D7Tf3v7c.d.mts → index-CK8Nk5uQ.d.ts} +9 -4
- package/dist/index-DPWI5XcU.d.ts +8 -0
- package/dist/index-DVfUh-ci.d.mts +8 -0
- package/dist/index.d.mts +31 -14
- package/dist/index.d.ts +31 -14
- package/dist/index.js +305 -133
- package/dist/index.mjs +6 -6
- package/dist/mock/cli.mjs +1442 -386
- package/dist/mock/library.js +1168 -352
- package/dist/mock/library.mjs +1168 -352
- package/dist/mock/msw.js +1168 -352
- package/dist/mock/msw.mjs +1168 -352
- package/dist/{price-BLIeAb8K.d.ts → price-6hQIIac9.d.ts} +1 -1
- package/dist/{price-Czq_cTC_.d.mts → price-BUDv1rI7.d.mts} +1 -1
- package/dist/react.d.mts +10 -5
- package/dist/react.d.ts +10 -5
- package/dist/react.js +227 -197
- package/dist/react.mjs +90 -60
- package/dist/{server-DKK_D-PP.d.ts → server-DJ0mSs9i.d.mts} +31 -57
- package/dist/{server-BkVhOIwn.d.mts → server-DSTX76Ki.d.ts} +31 -57
- package/dist/server.d.mts +3 -4
- package/dist/server.d.ts +3 -4
- package/dist/server.js +11 -11
- package/dist/server.mjs +5 -5
- package/dist/styles.css +2 -2
- package/dist/testing/msw.d.mts +2 -2
- package/dist/testing/msw.d.ts +2 -2
- package/dist/testing/msw.js +4 -4
- package/dist/testing/msw.mjs +3 -3
- package/dist/testing/suite.d.mts +5 -6
- package/dist/testing/suite.d.ts +5 -6
- package/dist/testing/suite.js +29 -28
- package/dist/testing/suite.mjs +10 -9
- package/dist/testing.d.mts +2177 -14
- package/dist/testing.d.ts +2177 -14
- package/dist/testing.js +167 -89
- package/dist/testing.mjs +24 -10
- package/dist/utils.d.mts +3 -4
- package/dist/utils.d.ts +3 -4
- package/dist/utils.js +35 -31
- package/dist/utils.mjs +2 -2
- package/package.json +9 -9
- package/registry/order-history.json +1 -1
- package/registry/order-summary.json +1 -1
- package/dist/link-D9iSVxt5.d.mts +0 -308
- package/dist/link-D9iSVxt5.d.ts +0 -308
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { messagePreview } from './chunk-U4MW6PYU.mjs';
|
|
2
|
-
import { PAYMENT_METHOD } from './chunk-
|
|
3
|
-
import { ErrorCode } from './chunk-
|
|
2
|
+
import { AUTHORIZATION_TYPE, CHECKOUT_ORDER_RESULT_STATUS, CHECKOUT_NEXT_ACTION, PAYMENT_METHOD, DEFAULT_CURRENCY } from './chunk-33VCYWVL.mjs';
|
|
3
|
+
import { PURCHASE_INTENT_MOBILE_MONEY_NETWORK, ErrorCode, PURCHASE_INTENT_CONFIRM_STATUS, PURCHASE_INTENT_STATUS, PAYMENT_OPTION_STATUS, CHECKOUT_TERMS_COMPONENT, CHECKOUT_TERMS_DELTA_KIND, CHECKOUT_INVALIDATION_REASON, PURCHASE_INTENT_SOURCE_KIND, PURCHASE_INTENT_PAYMENT_METHOD, PURCHASE_INTENT_PAYMENT_PROVIDER, currencyCode, PURCHASE_INTENT_LINE_CONFIGURATION_KIND, PURCHASE_INTENT_SELLABLE_KIND, PURCHASING_PRINCIPAL_KIND, LEGACY_CHECKOUT_PAYMENT_STATUS, CHECKOUT_COMPLIANCE_REASON, CHECKOUT_COMPLIANCE_LANE, MOBILE_MONEY_TENDER_AUTHORITY_KIND, PAYMENT_OPTION_NEXT_ACTION, PAYMENT_COLLECTION_MODE } from './chunk-RBNBSQI7.mjs';
|
|
4
4
|
import { __publicField, __privateAdd, __privateSet, __privateGet, __privateMethod, __privateWrapper } from './chunk-3G6RQLXK.mjs';
|
|
5
5
|
|
|
6
|
-
// ../node_modules/.bun/hono@4.
|
|
6
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/compose.js
|
|
7
7
|
var compose = (middleware, onError, onNotFound) => {
|
|
8
8
|
return (context, next) => {
|
|
9
9
|
let index = -1;
|
|
@@ -47,21 +47,46 @@ var compose = (middleware, onError, onNotFound) => {
|
|
|
47
47
|
};
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
// ../node_modules/.bun/hono@4.
|
|
50
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/request/constants.js
|
|
51
51
|
var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
|
|
52
52
|
|
|
53
|
-
// ../node_modules/.bun/hono@4.
|
|
53
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/buffer.js
|
|
54
|
+
var bufferToFormData = (arrayBuffer, contentType) => {
|
|
55
|
+
const response = new Response(arrayBuffer, {
|
|
56
|
+
headers: {
|
|
57
|
+
// Normalize the media type (case-insensitive) while keeping parameters like the boundary
|
|
58
|
+
"Content-Type": contentType.replace(/^[^;]+/, (mediaType) => mediaType.toLowerCase())
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return response.formData();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/body.js
|
|
65
|
+
var isRawRequest = (request) => "headers" in request;
|
|
54
66
|
var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
|
|
55
67
|
const { all = false, dot = false } = options;
|
|
56
|
-
const headers = request
|
|
68
|
+
const headers = isRawRequest(request) ? request.headers : request.raw.headers;
|
|
57
69
|
const contentType = headers.get("Content-Type");
|
|
58
|
-
|
|
70
|
+
const mediaType = contentType?.split(";")[0].trim().toLowerCase();
|
|
71
|
+
if (mediaType === "multipart/form-data" || mediaType === "application/x-www-form-urlencoded") {
|
|
59
72
|
return parseFormData(request, { all, dot });
|
|
60
73
|
}
|
|
61
74
|
return {};
|
|
62
75
|
};
|
|
63
76
|
async function parseFormData(request, options) {
|
|
64
|
-
|
|
77
|
+
if (!isRawRequest(request) && request.bodyCache.formData) {
|
|
78
|
+
return convertFormDataToBodyData(
|
|
79
|
+
await request.bodyCache.formData,
|
|
80
|
+
options
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
const headers = isRawRequest(request) ? request.headers : request.raw.headers;
|
|
84
|
+
const arrayBuffer = await request.arrayBuffer();
|
|
85
|
+
const formDataPromise = bufferToFormData(arrayBuffer, headers.get("Content-Type") || "");
|
|
86
|
+
if (!isRawRequest(request)) {
|
|
87
|
+
request.bodyCache.formData = formDataPromise;
|
|
88
|
+
}
|
|
89
|
+
const formData = await formDataPromise;
|
|
65
90
|
if (formData) {
|
|
66
91
|
return convertFormDataToBodyData(formData, options);
|
|
67
92
|
}
|
|
@@ -121,7 +146,7 @@ var handleParsingNestedValues = (form, key, value) => {
|
|
|
121
146
|
});
|
|
122
147
|
};
|
|
123
148
|
|
|
124
|
-
// ../node_modules/.bun/hono@4.
|
|
149
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/url.js
|
|
125
150
|
var splitPath = (path) => {
|
|
126
151
|
const paths = path.split("/");
|
|
127
152
|
if (paths[0] === "") {
|
|
@@ -227,13 +252,13 @@ var checkOptionalParameter = (path) => {
|
|
|
227
252
|
if (segment !== "" && !/\:/.test(segment)) {
|
|
228
253
|
basePath += "/" + segment;
|
|
229
254
|
} else if (/\:/.test(segment)) {
|
|
230
|
-
if (
|
|
255
|
+
if (segment.charCodeAt(segment.length - 1) === 63) {
|
|
231
256
|
if (results.length === 0 && basePath === "") {
|
|
232
257
|
results.push("/");
|
|
233
258
|
} else {
|
|
234
259
|
results.push(basePath);
|
|
235
260
|
}
|
|
236
|
-
const optionalSegment = segment.
|
|
261
|
+
const optionalSegment = segment.slice(0, -1);
|
|
237
262
|
basePath += "/" + optionalSegment;
|
|
238
263
|
results.push(basePath);
|
|
239
264
|
} else {
|
|
@@ -243,18 +268,16 @@ var checkOptionalParameter = (path) => {
|
|
|
243
268
|
});
|
|
244
269
|
return results.filter((v, i, a) => a.indexOf(v) === i);
|
|
245
270
|
};
|
|
271
|
+
var tryDecodeURIComponent = (str) => str.indexOf("%") !== -1 ? tryDecode(str, decodeURIComponent_) : str;
|
|
246
272
|
var _decodeURI = (value) => {
|
|
247
|
-
if (!/[%+]/.test(value)) {
|
|
248
|
-
return value;
|
|
249
|
-
}
|
|
250
273
|
if (value.indexOf("+") !== -1) {
|
|
251
274
|
value = value.replace(/\+/g, " ");
|
|
252
275
|
}
|
|
253
|
-
return
|
|
276
|
+
return tryDecodeURIComponent(value);
|
|
254
277
|
};
|
|
255
278
|
var _getQueryParam = (url, key, multiple) => {
|
|
256
279
|
let encoded;
|
|
257
|
-
if (!multiple && key &&
|
|
280
|
+
if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
|
|
258
281
|
let keyIndex2 = url.indexOf("?", 8);
|
|
259
282
|
if (keyIndex2 === -1) {
|
|
260
283
|
return void 0;
|
|
@@ -278,7 +301,7 @@ var _getQueryParam = (url, key, multiple) => {
|
|
|
278
301
|
return void 0;
|
|
279
302
|
}
|
|
280
303
|
}
|
|
281
|
-
const results =
|
|
304
|
+
const results = /* @__PURE__ */ Object.create(null);
|
|
282
305
|
encoded ?? (encoded = /[%+]/.test(url));
|
|
283
306
|
let keyIndex = url.indexOf("?", 8);
|
|
284
307
|
while (keyIndex !== -1) {
|
|
@@ -324,8 +347,7 @@ var getQueryParams = (url, key) => {
|
|
|
324
347
|
};
|
|
325
348
|
var decodeURIComponent_ = decodeURIComponent;
|
|
326
349
|
|
|
327
|
-
// ../node_modules/.bun/hono@4.
|
|
328
|
-
var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
|
|
350
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/request.js
|
|
329
351
|
var _validatedData, _matchResult, _HonoRequest_instances, getDecodedParam_fn, getAllDecodedParams_fn, getParamValue_fn, _cachedBody, _a;
|
|
330
352
|
var HonoRequest = (_a = class {
|
|
331
353
|
constructor(request, path = "/", matchResult = [[]]) {
|
|
@@ -369,8 +391,7 @@ var HonoRequest = (_a = class {
|
|
|
369
391
|
if (cachedBody) {
|
|
370
392
|
return cachedBody;
|
|
371
393
|
}
|
|
372
|
-
const anyCachedKey
|
|
373
|
-
if (anyCachedKey) {
|
|
394
|
+
for (const anyCachedKey in bodyCache) {
|
|
374
395
|
return bodyCache[anyCachedKey].then((body) => {
|
|
375
396
|
if (anyCachedKey === "json") {
|
|
376
397
|
body = JSON.stringify(body);
|
|
@@ -383,7 +404,6 @@ var HonoRequest = (_a = class {
|
|
|
383
404
|
this.raw = request;
|
|
384
405
|
this.path = path;
|
|
385
406
|
__privateSet(this, _matchResult, matchResult);
|
|
386
|
-
__privateSet(this, _validatedData, {});
|
|
387
407
|
}
|
|
388
408
|
param(key) {
|
|
389
409
|
return key ? __privateMethod(this, _HonoRequest_instances, getDecodedParam_fn).call(this, key) : __privateMethod(this, _HonoRequest_instances, getAllDecodedParams_fn).call(this);
|
|
@@ -398,7 +418,7 @@ var HonoRequest = (_a = class {
|
|
|
398
418
|
if (name) {
|
|
399
419
|
return this.raw.headers.get(name) ?? void 0;
|
|
400
420
|
}
|
|
401
|
-
const headerData =
|
|
421
|
+
const headerData = /* @__PURE__ */ Object.create(null);
|
|
402
422
|
this.raw.headers.forEach((value, key) => {
|
|
403
423
|
headerData[key] = value;
|
|
404
424
|
});
|
|
@@ -500,10 +520,10 @@ var HonoRequest = (_a = class {
|
|
|
500
520
|
* @param data - The validated data to add.
|
|
501
521
|
*/
|
|
502
522
|
addValidatedData(target, data) {
|
|
503
|
-
__privateGet(this, _validatedData)[target] = data;
|
|
523
|
+
(__privateGet(this, _validatedData) ?? __privateSet(this, _validatedData, {}))[target] = data;
|
|
504
524
|
}
|
|
505
525
|
valid(target) {
|
|
506
|
-
return __privateGet(this, _validatedData)[target];
|
|
526
|
+
return __privateGet(this, _validatedData)?.[target];
|
|
507
527
|
}
|
|
508
528
|
/**
|
|
509
529
|
* `.url()` can get the request url strings.
|
|
@@ -591,14 +611,14 @@ var HonoRequest = (_a = class {
|
|
|
591
611
|
}, _validatedData = new WeakMap(), _matchResult = new WeakMap(), _HonoRequest_instances = new WeakSet(), getDecodedParam_fn = function(key) {
|
|
592
612
|
const paramKey = __privateGet(this, _matchResult)[0][this.routeIndex][1][key];
|
|
593
613
|
const param = __privateMethod(this, _HonoRequest_instances, getParamValue_fn).call(this, paramKey);
|
|
594
|
-
return param &&
|
|
614
|
+
return param && tryDecodeURIComponent(param);
|
|
595
615
|
}, getAllDecodedParams_fn = function() {
|
|
596
616
|
const decoded = {};
|
|
597
617
|
const keys = Object.keys(__privateGet(this, _matchResult)[0][this.routeIndex][1]);
|
|
598
618
|
for (const key of keys) {
|
|
599
619
|
const value = __privateMethod(this, _HonoRequest_instances, getParamValue_fn).call(this, __privateGet(this, _matchResult)[0][this.routeIndex][1][key]);
|
|
600
620
|
if (value !== void 0) {
|
|
601
|
-
decoded[key] =
|
|
621
|
+
decoded[key] = tryDecodeURIComponent(value);
|
|
602
622
|
}
|
|
603
623
|
}
|
|
604
624
|
return decoded;
|
|
@@ -606,7 +626,7 @@ var HonoRequest = (_a = class {
|
|
|
606
626
|
return __privateGet(this, _matchResult)[1] ? __privateGet(this, _matchResult)[1][paramKey] : paramKey;
|
|
607
627
|
}, _cachedBody = new WeakMap(), _a);
|
|
608
628
|
|
|
609
|
-
// ../node_modules/.bun/hono@4.
|
|
629
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/html.js
|
|
610
630
|
var HtmlEscapedCallbackPhase = {
|
|
611
631
|
Stringify: 1};
|
|
612
632
|
var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
|
|
@@ -637,7 +657,7 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
|
|
|
637
657
|
}
|
|
638
658
|
};
|
|
639
659
|
|
|
640
|
-
// ../node_modules/.bun/hono@4.
|
|
660
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/context.js
|
|
641
661
|
var TEXT_PLAIN = "text/plain; charset=UTF-8";
|
|
642
662
|
var setDefaultContentType = (contentType, headers) => {
|
|
643
663
|
return {
|
|
@@ -1010,11 +1030,11 @@ var Context = (_a2 = class {
|
|
|
1010
1030
|
return Object.fromEntries(__privateGet(this, _var));
|
|
1011
1031
|
}
|
|
1012
1032
|
}, _rawRequest = new WeakMap(), _req = new WeakMap(), _var = new WeakMap(), _status = new WeakMap(), _executionCtx = new WeakMap(), _res = new WeakMap(), _layout = new WeakMap(), _renderer = new WeakMap(), _notFoundHandler = new WeakMap(), _preparedHeaders = new WeakMap(), _matchResult2 = new WeakMap(), _path = new WeakMap(), _Context_instances = new WeakSet(), newResponse_fn = function(data, arg, headers) {
|
|
1013
|
-
|
|
1014
|
-
if (typeof arg === "object" &&
|
|
1015
|
-
|
|
1016
|
-
for (const [key, value] of
|
|
1017
|
-
if (key
|
|
1033
|
+
let responseHeaders = __privateGet(this, _res) ? new Headers(__privateGet(this, _res).headers) : __privateGet(this, _preparedHeaders);
|
|
1034
|
+
if (typeof arg === "object" && arg.headers) {
|
|
1035
|
+
responseHeaders ?? (responseHeaders = new Headers());
|
|
1036
|
+
for (const [key, value] of new Headers(arg.headers)) {
|
|
1037
|
+
if (key === "set-cookie") {
|
|
1018
1038
|
responseHeaders.append(key, value);
|
|
1019
1039
|
} else {
|
|
1020
1040
|
responseHeaders.set(key, value);
|
|
@@ -1022,33 +1042,48 @@ var Context = (_a2 = class {
|
|
|
1022
1042
|
}
|
|
1023
1043
|
}
|
|
1024
1044
|
if (headers) {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1045
|
+
if (!responseHeaders) {
|
|
1046
|
+
let count = 0;
|
|
1047
|
+
for (const k in headers) {
|
|
1048
|
+
if (++count > 1 || typeof headers[k] !== "string") {
|
|
1049
|
+
responseHeaders = new Headers();
|
|
1050
|
+
break;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
if (responseHeaders) {
|
|
1055
|
+
for (const k in headers) {
|
|
1056
|
+
const v = headers[k];
|
|
1057
|
+
if (typeof v === "string") {
|
|
1058
|
+
responseHeaders.set(k, v);
|
|
1059
|
+
} else {
|
|
1060
|
+
responseHeaders.delete(k);
|
|
1061
|
+
for (const v2 of v) {
|
|
1062
|
+
responseHeaders.append(k, v2);
|
|
1063
|
+
}
|
|
1032
1064
|
}
|
|
1033
1065
|
}
|
|
1034
1066
|
}
|
|
1035
1067
|
}
|
|
1036
1068
|
const status = typeof arg === "number" ? arg : arg?.status ?? __privateGet(this, _status);
|
|
1037
|
-
return createResponseInstance(data, {
|
|
1069
|
+
return createResponseInstance(data, {
|
|
1070
|
+
status,
|
|
1071
|
+
headers: responseHeaders ?? headers
|
|
1072
|
+
});
|
|
1038
1073
|
}, _a2);
|
|
1039
1074
|
|
|
1040
|
-
// ../node_modules/.bun/hono@4.
|
|
1075
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router.js
|
|
1041
1076
|
var METHOD_NAME_ALL = "ALL";
|
|
1042
1077
|
var METHOD_NAME_ALL_LOWERCASE = "all";
|
|
1043
|
-
var METHODS = ["get", "post", "put", "delete", "options", "patch"];
|
|
1078
|
+
var METHODS = ["get", "post", "put", "delete", "options", "patch", "query"];
|
|
1044
1079
|
var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
|
|
1045
1080
|
var UnsupportedPathError = class extends Error {
|
|
1046
1081
|
};
|
|
1047
1082
|
|
|
1048
|
-
// ../node_modules/.bun/hono@4.
|
|
1083
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/constants.js
|
|
1049
1084
|
var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
|
|
1050
1085
|
|
|
1051
|
-
// ../node_modules/.bun/hono@4.
|
|
1086
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/hono-base.js
|
|
1052
1087
|
var notFoundHandler = (c) => {
|
|
1053
1088
|
return c.text("404 Not Found", 404);
|
|
1054
1089
|
};
|
|
@@ -1070,6 +1105,7 @@ var Hono = (_a3 = class {
|
|
|
1070
1105
|
__publicField(this, "delete");
|
|
1071
1106
|
__publicField(this, "options");
|
|
1072
1107
|
__publicField(this, "patch");
|
|
1108
|
+
__publicField(this, "query");
|
|
1073
1109
|
__publicField(this, "all");
|
|
1074
1110
|
__publicField(this, "on");
|
|
1075
1111
|
__publicField(this, "use");
|
|
@@ -1131,8 +1167,8 @@ var Hono = (_a3 = class {
|
|
|
1131
1167
|
* @see {@link https://hono.dev/docs/api/hono#fetch}
|
|
1132
1168
|
*
|
|
1133
1169
|
* @param {Request} request - request Object of request
|
|
1134
|
-
* @param {Env}
|
|
1135
|
-
* @param {ExecutionContext} - context of execution
|
|
1170
|
+
* @param {Env} env - env Object
|
|
1171
|
+
* @param {ExecutionContext} executionCtx - context of execution
|
|
1136
1172
|
* @returns {Response | Promise<Response>} response of request
|
|
1137
1173
|
*
|
|
1138
1174
|
*/
|
|
@@ -1423,7 +1459,7 @@ var Hono = (_a3 = class {
|
|
|
1423
1459
|
})();
|
|
1424
1460
|
}, _a3);
|
|
1425
1461
|
|
|
1426
|
-
// ../node_modules/.bun/hono@4.
|
|
1462
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/matcher.js
|
|
1427
1463
|
var emptyParam = [];
|
|
1428
1464
|
function match(method, path) {
|
|
1429
1465
|
const matchers = this.buildAllMatchers();
|
|
@@ -1444,7 +1480,7 @@ function match(method, path) {
|
|
|
1444
1480
|
return match2(method, path);
|
|
1445
1481
|
}
|
|
1446
1482
|
|
|
1447
|
-
// ../node_modules/.bun/hono@4.
|
|
1483
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/node.js
|
|
1448
1484
|
var LABEL_REG_EXP_STR = "[^/]+";
|
|
1449
1485
|
var ONLY_WILDCARD_REG_EXP_STR = ".*";
|
|
1450
1486
|
var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
|
|
@@ -1458,7 +1494,7 @@ function compareKey(a, b) {
|
|
|
1458
1494
|
return 1;
|
|
1459
1495
|
}
|
|
1460
1496
|
if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
|
|
1461
|
-
return 1;
|
|
1497
|
+
return b === TAIL_WILDCARD_REG_EXP_STR ? -1 : 1;
|
|
1462
1498
|
} else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
|
|
1463
1499
|
return -1;
|
|
1464
1500
|
}
|
|
@@ -1472,77 +1508,76 @@ function compareKey(a, b) {
|
|
|
1472
1508
|
var _index, _varIndex, _children, _a4;
|
|
1473
1509
|
var Node = (_a4 = class {
|
|
1474
1510
|
constructor() {
|
|
1511
|
+
// handler index of a dynamic path, or -1 for a static path terminal
|
|
1475
1512
|
__privateAdd(this, _index);
|
|
1476
1513
|
__privateAdd(this, _varIndex);
|
|
1477
1514
|
__privateAdd(this, _children, /* @__PURE__ */ Object.create(null));
|
|
1478
1515
|
}
|
|
1479
|
-
insert(tokens, index, paramMap, context,
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
}
|
|
1500
|
-
regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
|
|
1501
|
-
if (/\((?!\?:)/.test(regexpStr)) {
|
|
1502
|
-
throw PATH_ERROR;
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
node = __privateGet(this, _children)[regexpStr];
|
|
1506
|
-
if (!node) {
|
|
1507
|
-
if (Object.keys(__privateGet(this, _children)).some(
|
|
1508
|
-
(k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
|
|
1509
|
-
)) {
|
|
1510
|
-
throw PATH_ERROR;
|
|
1516
|
+
insert(tokens, index, paramMap, context, isStatic) {
|
|
1517
|
+
let node = this;
|
|
1518
|
+
for (let i = 0, len = tokens.length; i < len; i++) {
|
|
1519
|
+
const token = tokens[i];
|
|
1520
|
+
const pattern = token.length === 1 ? token === "*" ? i === len - 1 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : null : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
|
|
1521
|
+
let nextNode;
|
|
1522
|
+
if (pattern) {
|
|
1523
|
+
const name = pattern[1];
|
|
1524
|
+
let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
|
|
1525
|
+
if (name && pattern[2]) {
|
|
1526
|
+
if (regexpStr === ".*") {
|
|
1527
|
+
throw PATH_ERROR;
|
|
1528
|
+
}
|
|
1529
|
+
regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
|
|
1530
|
+
if (/\((?!\?:)/.test(regexpStr)) {
|
|
1531
|
+
throw PATH_ERROR;
|
|
1532
|
+
}
|
|
1533
|
+
if (regexpStr.length === 1 && regExpMetaChars.has(regexpStr)) {
|
|
1534
|
+
throw PATH_ERROR;
|
|
1535
|
+
}
|
|
1511
1536
|
}
|
|
1512
|
-
|
|
1513
|
-
|
|
1537
|
+
nextNode = __privateGet(node, _children)[regexpStr];
|
|
1538
|
+
if (!nextNode) {
|
|
1539
|
+
if (regexpStr !== ONLY_WILDCARD_REG_EXP_STR && regexpStr !== TAIL_WILDCARD_REG_EXP_STR) {
|
|
1540
|
+
for (const k in __privateGet(node, _children)) {
|
|
1541
|
+
if (
|
|
1542
|
+
// a single-char pattern coexists with single-char literals as a literal does
|
|
1543
|
+
(regexpStr.length > 1 || k.length > 1) && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
|
|
1544
|
+
) {
|
|
1545
|
+
throw PATH_ERROR;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
nextNode = __privateGet(node, _children)[regexpStr] = new _a4();
|
|
1514
1550
|
}
|
|
1515
|
-
node = __privateGet(this, _children)[regexpStr] = new _a4();
|
|
1516
1551
|
if (name !== "") {
|
|
1517
|
-
__privateSet(
|
|
1552
|
+
__privateGet(nextNode, _varIndex) ?? __privateSet(nextNode, _varIndex, context.varIndex++);
|
|
1553
|
+
paramMap.push([name, __privateGet(nextNode, _varIndex)]);
|
|
1518
1554
|
}
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
)) {
|
|
1529
|
-
throw PATH_ERROR;
|
|
1530
|
-
}
|
|
1531
|
-
if (pathErrorCheckOnly) {
|
|
1532
|
-
return;
|
|
1555
|
+
} else {
|
|
1556
|
+
nextNode = __privateGet(node, _children)[token];
|
|
1557
|
+
if (!nextNode) {
|
|
1558
|
+
for (const k in __privateGet(node, _children)) {
|
|
1559
|
+
if (k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR) {
|
|
1560
|
+
throw PATH_ERROR;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
nextNode = __privateGet(node, _children)[token] = new _a4();
|
|
1533
1564
|
}
|
|
1534
|
-
node = __privateGet(this, _children)[token] = new _a4();
|
|
1535
1565
|
}
|
|
1566
|
+
node = nextNode;
|
|
1536
1567
|
}
|
|
1537
|
-
node
|
|
1568
|
+
if (__privateGet(node, _index) !== void 0) {
|
|
1569
|
+
throw PATH_ERROR;
|
|
1570
|
+
}
|
|
1571
|
+
__privateSet(node, _index, isStatic ? -1 : index);
|
|
1538
1572
|
}
|
|
1539
1573
|
buildRegExpStr() {
|
|
1540
1574
|
const childKeys = Object.keys(__privateGet(this, _children)).sort(compareKey);
|
|
1541
1575
|
const strList = childKeys.map((k) => {
|
|
1542
1576
|
const c = __privateGet(this, _children)[k];
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1577
|
+
const childStr = c.buildRegExpStr();
|
|
1578
|
+
return childStr === "" ? "" : (typeof __privateGet(c, _varIndex) === "number" ? `(${k})@${__privateGet(c, _varIndex)}` : regExpMetaChars.has(k) ? `\\${k}` : k) + childStr;
|
|
1579
|
+
}).filter(Boolean);
|
|
1580
|
+
if (typeof __privateGet(this, _index) === "number" && __privateGet(this, _index) !== -1) {
|
|
1546
1581
|
strList.unshift(`#${__privateGet(this, _index)}`);
|
|
1547
1582
|
}
|
|
1548
1583
|
if (strList.length === 0) {
|
|
@@ -1555,19 +1590,27 @@ var Node = (_a4 = class {
|
|
|
1555
1590
|
}
|
|
1556
1591
|
}, _index = new WeakMap(), _varIndex = new WeakMap(), _children = new WeakMap(), _a4);
|
|
1557
1592
|
|
|
1558
|
-
// ../node_modules/.bun/hono@4.
|
|
1559
|
-
var _context, _root, _a5;
|
|
1593
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/trie.js
|
|
1594
|
+
var _context, _root, _index2, _a5;
|
|
1560
1595
|
var Trie = (_a5 = class {
|
|
1561
1596
|
constructor() {
|
|
1562
1597
|
__privateAdd(this, _context, { varIndex: 0 });
|
|
1563
1598
|
__privateAdd(this, _root, new Node());
|
|
1599
|
+
__privateAdd(this, _index2, 0);
|
|
1600
|
+
// dynamic path -> [handler index, param assoc]; static paths are not registered
|
|
1601
|
+
__publicField(this, "paths", /* @__PURE__ */ Object.create(null));
|
|
1564
1602
|
}
|
|
1565
|
-
insert(path,
|
|
1603
|
+
insert(path, isStatic) {
|
|
1604
|
+
if (isStatic) {
|
|
1605
|
+
__privateGet(this, _root).insert(path.split(""), 0, [], __privateGet(this, _context), true);
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1566
1608
|
const paramAssoc = [];
|
|
1567
1609
|
const groups = [];
|
|
1610
|
+
let markedPath = path;
|
|
1568
1611
|
for (let i = 0; ; ) {
|
|
1569
1612
|
let replaced = false;
|
|
1570
|
-
|
|
1613
|
+
markedPath = markedPath.replace(/\{[^}]+\}/g, (m) => {
|
|
1571
1614
|
const mark = `@\\${i}`;
|
|
1572
1615
|
groups[i] = [mark, m];
|
|
1573
1616
|
i++;
|
|
@@ -1578,7 +1621,7 @@ var Trie = (_a5 = class {
|
|
|
1578
1621
|
break;
|
|
1579
1622
|
}
|
|
1580
1623
|
}
|
|
1581
|
-
const tokens =
|
|
1624
|
+
const tokens = markedPath.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
|
|
1582
1625
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
1583
1626
|
const [mark] = groups[i];
|
|
1584
1627
|
for (let j = tokens.length - 1; j >= 0; j--) {
|
|
@@ -1588,8 +1631,8 @@ var Trie = (_a5 = class {
|
|
|
1588
1631
|
}
|
|
1589
1632
|
}
|
|
1590
1633
|
}
|
|
1591
|
-
__privateGet(this, _root).insert(tokens,
|
|
1592
|
-
|
|
1634
|
+
__privateGet(this, _root).insert(tokens, __privateGet(this, _index2), paramAssoc, __privateGet(this, _context), false);
|
|
1635
|
+
this.paths[path] = [__privateWrapper(this, _index2)._++, paramAssoc];
|
|
1593
1636
|
}
|
|
1594
1637
|
buildRegExp() {
|
|
1595
1638
|
let regexp = __privateGet(this, _root).buildRegExpStr();
|
|
@@ -1612,10 +1655,9 @@ var Trie = (_a5 = class {
|
|
|
1612
1655
|
});
|
|
1613
1656
|
return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
|
|
1614
1657
|
}
|
|
1615
|
-
}, _context = new WeakMap(), _root = new WeakMap(), _a5);
|
|
1658
|
+
}, _context = new WeakMap(), _root = new WeakMap(), _index2 = new WeakMap(), _a5);
|
|
1616
1659
|
|
|
1617
|
-
// ../node_modules/.bun/hono@4.
|
|
1618
|
-
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
|
|
1660
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/router.js
|
|
1619
1661
|
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
1620
1662
|
function buildWildcardRegExp(path) {
|
|
1621
1663
|
return wildcardRegExpCache[path] ?? (wildcardRegExpCache[path] = new RegExp(
|
|
@@ -1628,63 +1670,6 @@ function buildWildcardRegExp(path) {
|
|
|
1628
1670
|
function clearWildcardRegExpCache() {
|
|
1629
1671
|
wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
1630
1672
|
}
|
|
1631
|
-
function buildMatcherFromPreprocessedRoutes(routes) {
|
|
1632
|
-
const trie = new Trie();
|
|
1633
|
-
const handlerData = [];
|
|
1634
|
-
if (routes.length === 0) {
|
|
1635
|
-
return nullMatcher;
|
|
1636
|
-
}
|
|
1637
|
-
const routesWithStaticPathFlag = routes.map(
|
|
1638
|
-
(route) => [!/\*|\/:/.test(route[0]), ...route]
|
|
1639
|
-
).sort(
|
|
1640
|
-
([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
|
|
1641
|
-
);
|
|
1642
|
-
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
1643
|
-
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
|
1644
|
-
const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
|
|
1645
|
-
if (pathErrorCheckOnly) {
|
|
1646
|
-
staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
1647
|
-
} else {
|
|
1648
|
-
j++;
|
|
1649
|
-
}
|
|
1650
|
-
let paramAssoc;
|
|
1651
|
-
try {
|
|
1652
|
-
paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
|
|
1653
|
-
} catch (e) {
|
|
1654
|
-
throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
|
|
1655
|
-
}
|
|
1656
|
-
if (pathErrorCheckOnly) {
|
|
1657
|
-
continue;
|
|
1658
|
-
}
|
|
1659
|
-
handlerData[j] = handlers.map(([h, paramCount]) => {
|
|
1660
|
-
const paramIndexMap = /* @__PURE__ */ Object.create(null);
|
|
1661
|
-
paramCount -= 1;
|
|
1662
|
-
for (; paramCount >= 0; paramCount--) {
|
|
1663
|
-
const [key, value] = paramAssoc[paramCount];
|
|
1664
|
-
paramIndexMap[key] = value;
|
|
1665
|
-
}
|
|
1666
|
-
return [h, paramIndexMap];
|
|
1667
|
-
});
|
|
1668
|
-
}
|
|
1669
|
-
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
|
|
1670
|
-
for (let i = 0, len = handlerData.length; i < len; i++) {
|
|
1671
|
-
for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
|
|
1672
|
-
const map = handlerData[i][j]?.[1];
|
|
1673
|
-
if (!map) {
|
|
1674
|
-
continue;
|
|
1675
|
-
}
|
|
1676
|
-
const keys = Object.keys(map);
|
|
1677
|
-
for (let k = 0, len3 = keys.length; k < len3; k++) {
|
|
1678
|
-
map[keys[k]] = paramReplacementMap[map[keys[k]]];
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
}
|
|
1682
|
-
const handlerMap = [];
|
|
1683
|
-
for (const i in indexReplacementMap) {
|
|
1684
|
-
handlerMap[i] = handlerData[indexReplacementMap[i]];
|
|
1685
|
-
}
|
|
1686
|
-
return [regexp, handlerMap, staticMap];
|
|
1687
|
-
}
|
|
1688
1673
|
function findMiddleware(middleware, path) {
|
|
1689
1674
|
if (!middleware) {
|
|
1690
1675
|
return void 0;
|
|
@@ -1696,29 +1681,32 @@ function findMiddleware(middleware, path) {
|
|
|
1696
1681
|
}
|
|
1697
1682
|
return void 0;
|
|
1698
1683
|
}
|
|
1699
|
-
var _middleware, _routes, _RegExpRouter_instances, buildMatcher_fn, _a6;
|
|
1684
|
+
var _middleware, _routes, _tries, _RegExpRouter_instances, insertPath_fn, buildMatcher_fn, _a6;
|
|
1700
1685
|
var RegExpRouter = (_a6 = class {
|
|
1701
1686
|
constructor() {
|
|
1702
1687
|
__privateAdd(this, _RegExpRouter_instances);
|
|
1703
1688
|
__publicField(this, "name", "RegExpRouter");
|
|
1704
1689
|
__privateAdd(this, _middleware);
|
|
1705
1690
|
__privateAdd(this, _routes);
|
|
1691
|
+
__privateAdd(this, _tries);
|
|
1706
1692
|
__publicField(this, "match", match);
|
|
1707
1693
|
__privateSet(this, _middleware, { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) });
|
|
1708
1694
|
__privateSet(this, _routes, { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) });
|
|
1695
|
+
__privateSet(this, _tries, { [METHOD_NAME_ALL]: new Trie() });
|
|
1709
1696
|
}
|
|
1710
1697
|
add(method, path, handler) {
|
|
1711
|
-
var _a10;
|
|
1712
1698
|
const middleware = __privateGet(this, _middleware);
|
|
1713
1699
|
const routes = __privateGet(this, _routes);
|
|
1714
1700
|
if (!middleware || !routes) {
|
|
1715
1701
|
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
|
|
1716
1702
|
}
|
|
1717
1703
|
if (!middleware[method]) {
|
|
1704
|
+
__privateGet(this, _tries)[method] = new Trie();
|
|
1718
1705
|
[middleware, routes].forEach((handlerMap) => {
|
|
1719
1706
|
handlerMap[method] = /* @__PURE__ */ Object.create(null);
|
|
1720
1707
|
Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
|
|
1721
1708
|
handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
|
|
1709
|
+
__privateMethod(this, _RegExpRouter_instances, insertPath_fn).call(this, method, p);
|
|
1722
1710
|
});
|
|
1723
1711
|
});
|
|
1724
1712
|
}
|
|
@@ -1728,14 +1716,12 @@ var RegExpRouter = (_a6 = class {
|
|
|
1728
1716
|
const paramCount = (path.match(/\/:/g) || []).length;
|
|
1729
1717
|
if (/\*$/.test(path)) {
|
|
1730
1718
|
const re = buildWildcardRegExp(path);
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
(_a10 = middleware[method])[path] || (_a10[path] = findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || []);
|
|
1738
|
-
}
|
|
1719
|
+
Object.keys(middleware).forEach((m) => {
|
|
1720
|
+
if ((method === METHOD_NAME_ALL || method === m) && !middleware[m][path]) {
|
|
1721
|
+
__privateMethod(this, _RegExpRouter_instances, insertPath_fn).call(this, m, path);
|
|
1722
|
+
middleware[m][path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
|
|
1723
|
+
}
|
|
1724
|
+
});
|
|
1739
1725
|
Object.keys(middleware).forEach((m) => {
|
|
1740
1726
|
if (method === METHOD_NAME_ALL || method === m) {
|
|
1741
1727
|
Object.keys(middleware[m]).forEach((p) => {
|
|
@@ -1756,11 +1742,13 @@ var RegExpRouter = (_a6 = class {
|
|
|
1756
1742
|
for (let i = 0, len = paths.length; i < len; i++) {
|
|
1757
1743
|
const path2 = paths[i];
|
|
1758
1744
|
Object.keys(routes).forEach((m) => {
|
|
1759
|
-
var _a11;
|
|
1760
1745
|
if (method === METHOD_NAME_ALL || method === m) {
|
|
1761
|
-
(
|
|
1762
|
-
|
|
1763
|
-
|
|
1746
|
+
if (!routes[m][path2]) {
|
|
1747
|
+
__privateMethod(this, _RegExpRouter_instances, insertPath_fn).call(this, m, path2);
|
|
1748
|
+
routes[m][path2] = [
|
|
1749
|
+
...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
|
|
1750
|
+
];
|
|
1751
|
+
}
|
|
1764
1752
|
routes[m][path2].push([handler, paramCount - len + i + 1]);
|
|
1765
1753
|
}
|
|
1766
1754
|
});
|
|
@@ -1771,32 +1759,63 @@ var RegExpRouter = (_a6 = class {
|
|
|
1771
1759
|
Object.keys(__privateGet(this, _routes)).concat(Object.keys(__privateGet(this, _middleware))).forEach((method) => {
|
|
1772
1760
|
matchers[method] || (matchers[method] = __privateMethod(this, _RegExpRouter_instances, buildMatcher_fn).call(this, method));
|
|
1773
1761
|
});
|
|
1774
|
-
__privateSet(this, _middleware, __privateSet(this, _routes, void 0));
|
|
1762
|
+
__privateSet(this, _middleware, __privateSet(this, _routes, __privateSet(this, _tries, void 0)));
|
|
1775
1763
|
clearWildcardRegExpCache();
|
|
1776
1764
|
return matchers;
|
|
1777
1765
|
}
|
|
1778
|
-
}, _middleware = new WeakMap(), _routes = new WeakMap(), _RegExpRouter_instances = new WeakSet(),
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1766
|
+
}, _middleware = new WeakMap(), _routes = new WeakMap(), _tries = new WeakMap(), _RegExpRouter_instances = new WeakSet(), insertPath_fn = function(method, path) {
|
|
1767
|
+
try {
|
|
1768
|
+
__privateGet(this, _tries)[method].insert(path, !/\*|\/:/.test(path));
|
|
1769
|
+
} catch (e) {
|
|
1770
|
+
throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
|
|
1771
|
+
}
|
|
1772
|
+
}, buildMatcher_fn = function(method) {
|
|
1773
|
+
const middleware = __privateGet(this, _middleware)[method];
|
|
1774
|
+
const routes = __privateGet(this, _routes)[method];
|
|
1775
|
+
const trie = __privateGet(this, _tries)[method];
|
|
1776
|
+
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
1777
|
+
const handlerData = [];
|
|
1778
|
+
[middleware, routes].forEach((r) => {
|
|
1779
|
+
for (const path in r) {
|
|
1780
|
+
const handlers = r[path];
|
|
1781
|
+
const pathData = trie.paths[path];
|
|
1782
|
+
if (!pathData) {
|
|
1783
|
+
staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
1784
|
+
continue;
|
|
1785
|
+
}
|
|
1786
|
+
const paramAssoc = pathData[1];
|
|
1787
|
+
handlerData[pathData[0]] = handlers.map(([h, paramCount]) => {
|
|
1788
|
+
const paramIndexMap = /* @__PURE__ */ Object.create(null);
|
|
1789
|
+
paramCount -= 1;
|
|
1790
|
+
for (; paramCount >= 0; paramCount--) {
|
|
1791
|
+
const [key, value] = paramAssoc[paramCount];
|
|
1792
|
+
paramIndexMap[key] = value;
|
|
1793
|
+
}
|
|
1794
|
+
return [h, paramIndexMap];
|
|
1795
|
+
});
|
|
1790
1796
|
}
|
|
1791
1797
|
});
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1798
|
+
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
|
|
1799
|
+
for (let i = 0, len = handlerData.length; i < len; i++) {
|
|
1800
|
+
for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
|
|
1801
|
+
const map = handlerData[i][j]?.[1];
|
|
1802
|
+
if (!map) {
|
|
1803
|
+
continue;
|
|
1804
|
+
}
|
|
1805
|
+
const keys = Object.keys(map);
|
|
1806
|
+
for (let k = 0, len3 = keys.length; k < len3; k++) {
|
|
1807
|
+
map[keys[k]] = paramReplacementMap[map[keys[k]]];
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1796
1810
|
}
|
|
1811
|
+
const handlerMap = [];
|
|
1812
|
+
for (const i in indexReplacementMap) {
|
|
1813
|
+
handlerMap[i] = handlerData[indexReplacementMap[i]];
|
|
1814
|
+
}
|
|
1815
|
+
return [regexp, handlerMap, staticMap];
|
|
1797
1816
|
}, _a6);
|
|
1798
1817
|
|
|
1799
|
-
// ../node_modules/.bun/hono@4.
|
|
1818
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/smart-router/router.js
|
|
1800
1819
|
var _routers, _routes2, _a7;
|
|
1801
1820
|
var SmartRouter = (_a7 = class {
|
|
1802
1821
|
constructor(init) {
|
|
@@ -1852,7 +1871,7 @@ var SmartRouter = (_a7 = class {
|
|
|
1852
1871
|
}
|
|
1853
1872
|
}, _routers = new WeakMap(), _routes2 = new WeakMap(), _a7);
|
|
1854
1873
|
|
|
1855
|
-
// ../node_modules/.bun/hono@4.
|
|
1874
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/trie-router/node.js
|
|
1856
1875
|
var emptyParams = /* @__PURE__ */ Object.create(null);
|
|
1857
1876
|
var hasChildren = (children) => {
|
|
1858
1877
|
for (const _ in children) {
|
|
@@ -1969,9 +1988,12 @@ var Node2 = (_a8 = class {
|
|
|
1969
1988
|
if (m) {
|
|
1970
1989
|
params[name] = m[0];
|
|
1971
1990
|
__privateMethod(this, __Node_instances, pushHandlerSets_fn).call(this, handlerSets, child, method, __privateGet(node, _params), params);
|
|
1991
|
+
if (m[0].length === restPathString.length && __privateGet(child, _children2)["*"]) {
|
|
1992
|
+
__privateMethod(this, __Node_instances, pushHandlerSets_fn).call(this, handlerSets, __privateGet(child, _children2)["*"], method, __privateGet(node, _params), params);
|
|
1993
|
+
}
|
|
1972
1994
|
if (hasChildren(__privateGet(child, _children2))) {
|
|
1973
1995
|
__privateSet(child, _params, params);
|
|
1974
|
-
const componentCount = m[0].match(/\//)?.length ?? 0;
|
|
1996
|
+
const componentCount = m[0].match(/\//g)?.length ?? 0;
|
|
1975
1997
|
const targetCurNodes = curNodesQueue[componentCount] || (curNodesQueue[componentCount] = []);
|
|
1976
1998
|
targetCurNodes.push(child);
|
|
1977
1999
|
}
|
|
@@ -2022,7 +2044,7 @@ var Node2 = (_a8 = class {
|
|
|
2022
2044
|
}
|
|
2023
2045
|
}, _a8);
|
|
2024
2046
|
|
|
2025
|
-
// ../node_modules/.bun/hono@4.
|
|
2047
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/trie-router/router.js
|
|
2026
2048
|
var _node, _a9;
|
|
2027
2049
|
var TrieRouter = (_a9 = class {
|
|
2028
2050
|
constructor() {
|
|
@@ -2045,7 +2067,7 @@ var TrieRouter = (_a9 = class {
|
|
|
2045
2067
|
}
|
|
2046
2068
|
}, _node = new WeakMap(), _a9);
|
|
2047
2069
|
|
|
2048
|
-
// ../node_modules/.bun/hono@4.
|
|
2070
|
+
// ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/hono.js
|
|
2049
2071
|
var Hono2 = class extends Hono {
|
|
2050
2072
|
/**
|
|
2051
2073
|
* Creates an instance of the Hono class.
|
|
@@ -2090,7 +2112,7 @@ function authMiddleware(deps) {
|
|
|
2090
2112
|
await next();
|
|
2091
2113
|
};
|
|
2092
2114
|
}
|
|
2093
|
-
var IDEMPOTENT_PATH_RE = /\/(cart\/items|cart\/coupons|checkout|payments\/authorization|auth\/(request-otp|verify-otp|profile|logout))(\/|$)/;
|
|
2115
|
+
var IDEMPOTENT_PATH_RE = /\/(cart\/items|cart\/coupons|checkout|purchase-intents|payments\/authorization|auth\/(request-otp|verify-otp|profile|logout))(\/|$)/;
|
|
2094
2116
|
var IDEMPOTENCY_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2095
2117
|
function idempotencyMiddleware(deps) {
|
|
2096
2118
|
return async (c, next) => {
|
|
@@ -2100,7 +2122,8 @@ function idempotencyMiddleware(deps) {
|
|
|
2100
2122
|
const key = c.req.header("idempotency-key") ?? c.req.header("Idempotency-Key");
|
|
2101
2123
|
if (!key || key.length > 200) return next();
|
|
2102
2124
|
const session = c.var.session;
|
|
2103
|
-
const
|
|
2125
|
+
const routeScope = c.req.path.includes("/purchase-intents") ? `:${c.req.path}` : "";
|
|
2126
|
+
const recordId = `${session.id}${routeScope}:${key}`;
|
|
2104
2127
|
const existing = deps.registry.idempotency.get(recordId);
|
|
2105
2128
|
if (existing) {
|
|
2106
2129
|
const expiresAt = Date.parse(existing.expires_at);
|
|
@@ -2174,6 +2197,21 @@ function getQueryNum(c, key) {
|
|
|
2174
2197
|
}
|
|
2175
2198
|
|
|
2176
2199
|
// src/mock/routes/v1.ts
|
|
2200
|
+
var PURCHASE_INTENT_ROUTE = {
|
|
2201
|
+
COLLECTION: "/purchase-intents",
|
|
2202
|
+
MEMBER: "/purchase-intents/:intent_id",
|
|
2203
|
+
REFRESH: "/purchase-intents/:intent_id/refresh",
|
|
2204
|
+
CONFIRM: "/purchase-intents/:intent_id/confirm",
|
|
2205
|
+
ACTION: "/purchase-intents/:intent_id/attempts/:attempt_id/actions"
|
|
2206
|
+
};
|
|
2207
|
+
var PURCHASE_INTENT_ROUTE_PARAM = {
|
|
2208
|
+
INTENT_ID: "intent_id",
|
|
2209
|
+
ATTEMPT_ID: "attempt_id"
|
|
2210
|
+
};
|
|
2211
|
+
var PAYMENT_ROUTE = {
|
|
2212
|
+
COLLECTION_OPTIONS: "/payments/collection-options",
|
|
2213
|
+
AUTHORIZATION: "/payments/authorization"
|
|
2214
|
+
};
|
|
2177
2215
|
function buildV1(deps) {
|
|
2178
2216
|
const app = new Hono2();
|
|
2179
2217
|
app.use("*", chaosMiddleware(deps));
|
|
@@ -2546,28 +2584,81 @@ function buildV1(deps) {
|
|
|
2546
2584
|
"/subscriptions/:subscription_id/skip",
|
|
2547
2585
|
(c) => tryRoute(c, () => deps.subscriptions.skipNext(c.req.param("subscription_id")))
|
|
2548
2586
|
);
|
|
2549
|
-
app.get(
|
|
2587
|
+
app.get(PAYMENT_ROUTE.COLLECTION_OPTIONS, async (c) => {
|
|
2550
2588
|
const currency = c.req.query("currency")?.trim().toUpperCase();
|
|
2551
2589
|
if (!currency || !/^[A-Z]{3}$/.test(currency)) {
|
|
2552
2590
|
return fail(c, validation("currency must be a canonical three-letter code"));
|
|
2553
2591
|
}
|
|
2554
2592
|
return tryRoute(c, () => ({
|
|
2555
2593
|
presentment_currency: currency,
|
|
2556
|
-
options: currency ===
|
|
2594
|
+
options: currency === DEFAULT_CURRENCY ? [
|
|
2557
2595
|
{ method: PAYMENT_METHOD.CARD, network: null },
|
|
2558
|
-
{
|
|
2559
|
-
|
|
2560
|
-
|
|
2596
|
+
{
|
|
2597
|
+
method: PAYMENT_METHOD.MOBILE_MONEY,
|
|
2598
|
+
network: PURCHASE_INTENT_MOBILE_MONEY_NETWORK.MTN
|
|
2599
|
+
},
|
|
2600
|
+
{
|
|
2601
|
+
method: PAYMENT_METHOD.MOBILE_MONEY,
|
|
2602
|
+
network: PURCHASE_INTENT_MOBILE_MONEY_NETWORK.TELECEL
|
|
2603
|
+
},
|
|
2604
|
+
{
|
|
2605
|
+
method: PAYMENT_METHOD.MOBILE_MONEY,
|
|
2606
|
+
network: PURCHASE_INTENT_MOBILE_MONEY_NETWORK.AIRTEL
|
|
2607
|
+
}
|
|
2561
2608
|
] : currency === "USD" ? [{ method: PAYMENT_METHOD.CARD, network: null }] : []
|
|
2562
2609
|
}));
|
|
2563
2610
|
});
|
|
2564
|
-
app.post(
|
|
2611
|
+
app.post(PURCHASE_INTENT_ROUTE.COLLECTION, async (c) => {
|
|
2612
|
+
const body = await c.req.json().catch(() => ({}));
|
|
2613
|
+
return tryRoute(c, () => deps.purchaseIntents.mint(c.var.session, body));
|
|
2614
|
+
});
|
|
2615
|
+
app.get(
|
|
2616
|
+
PURCHASE_INTENT_ROUTE.MEMBER,
|
|
2617
|
+
(c) => tryRoute(
|
|
2618
|
+
c,
|
|
2619
|
+
() => deps.purchaseIntents.get(
|
|
2620
|
+
c.var.session,
|
|
2621
|
+
c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID)
|
|
2622
|
+
)
|
|
2623
|
+
)
|
|
2624
|
+
);
|
|
2625
|
+
app.post(PURCHASE_INTENT_ROUTE.REFRESH, async (c) => {
|
|
2626
|
+
const body = await c.req.json().catch(() => ({}));
|
|
2627
|
+
return tryRoute(
|
|
2628
|
+
c,
|
|
2629
|
+
() => deps.purchaseIntents.refresh(
|
|
2630
|
+
c.var.session,
|
|
2631
|
+
c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID),
|
|
2632
|
+
body.expected_intent_revision
|
|
2633
|
+
)
|
|
2634
|
+
);
|
|
2635
|
+
});
|
|
2636
|
+
app.post(PURCHASE_INTENT_ROUTE.CONFIRM, async (c) => {
|
|
2637
|
+
const body = await c.req.json().catch(() => ({}));
|
|
2638
|
+
return tryRoute(
|
|
2639
|
+
c,
|
|
2640
|
+
() => deps.purchaseIntents.confirm(
|
|
2641
|
+
c.var.session,
|
|
2642
|
+
c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID),
|
|
2643
|
+
body
|
|
2644
|
+
)
|
|
2645
|
+
);
|
|
2646
|
+
});
|
|
2647
|
+
app.post(PURCHASE_INTENT_ROUTE.ACTION, async (c) => {
|
|
2565
2648
|
const body = await c.req.json().catch(() => ({}));
|
|
2566
|
-
return tryRoute(
|
|
2649
|
+
return tryRoute(
|
|
2650
|
+
c,
|
|
2651
|
+
() => deps.purchaseIntents.submitAction(
|
|
2652
|
+
c.var.session,
|
|
2653
|
+
c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID),
|
|
2654
|
+
c.req.param(PURCHASE_INTENT_ROUTE_PARAM.ATTEMPT_ID),
|
|
2655
|
+
body
|
|
2656
|
+
)
|
|
2657
|
+
);
|
|
2567
2658
|
});
|
|
2568
|
-
app.post(
|
|
2659
|
+
app.post(PAYMENT_ROUTE.AUTHORIZATION, async (c) => {
|
|
2569
2660
|
const body = await c.req.json().catch(() => ({}));
|
|
2570
|
-
return tryRoute(c, () => deps.
|
|
2661
|
+
return tryRoute(c, () => deps.payments.authorize(body));
|
|
2571
2662
|
});
|
|
2572
2663
|
app.get("/auth/status", (c) => tryRoute(c, () => deps.auth.status(c.var.session.token)));
|
|
2573
2664
|
app.post("/auth/request-otp", async (c) => {
|
|
@@ -2873,6 +2964,7 @@ function createStateRegistry() {
|
|
|
2873
2964
|
collections: createMemoryStore(),
|
|
2874
2965
|
carts: createMemoryStore(),
|
|
2875
2966
|
orders: createMemoryStore(),
|
|
2967
|
+
purchaseIntents: createMemoryStore(),
|
|
2876
2968
|
subscriptions: createMemoryStore(),
|
|
2877
2969
|
bookings: createMemoryStore(),
|
|
2878
2970
|
services: createMemoryStore(),
|
|
@@ -3022,9 +3114,9 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3022
3114
|
// injected into the HTML page served by the mock. Edit this file directly \u2014
|
|
3023
3115
|
// type-check via tsgo + the IframeToParentMessage shape from the SDK.
|
|
3024
3116
|
(function () {
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3117
|
+
const TYPE = window.__CIMPLIFY_MOCK_ELEMENT__;
|
|
3118
|
+
const DEFAULT_BUSINESS = window.__CIMPLIFY_MOCK_BUSINESS__;
|
|
3119
|
+
const MSG = {
|
|
3028
3120
|
INIT: "init", SET_TOKEN: "set_token", SET_CART: "set_cart", GET_DATA: "get_data",
|
|
3029
3121
|
REFRESH_TOKEN: "refresh_token", LOGOUT: "logout",
|
|
3030
3122
|
PROCESS_CHECKOUT: "process_checkout", ABORT_CHECKOUT: "abort_checkout",
|
|
@@ -3037,12 +3129,36 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3037
3129
|
CHECKOUT_STATUS: "checkout_status", CHECKOUT_COMPLETE: "checkout_complete",
|
|
3038
3130
|
ORDER_TYPE_CHANGED: "order_type_changed", REQUEST_SUBMIT: "request_submit"
|
|
3039
3131
|
};
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3132
|
+
const PURCHASE_INTENT = {
|
|
3133
|
+
PATH: "/api/v1/purchase-intents",
|
|
3134
|
+
ORDER_CREATED: "order_created",
|
|
3135
|
+
CARD_POPUP_REQUIRED: "card_popup_required",
|
|
3136
|
+
AUTHORIZATION_REQUIRED: "authorization_required",
|
|
3137
|
+
ELIGIBLE: "eligible"
|
|
3138
|
+
};
|
|
3139
|
+
const CHECKOUT_STATUS = {
|
|
3140
|
+
PROCESSING: "processing",
|
|
3141
|
+
SUCCESS: "success",
|
|
3142
|
+
FAILED: "failed"
|
|
3143
|
+
};
|
|
3144
|
+
const CHECKOUT_ERROR = { FAILED: "CHECKOUT_FAILED" };
|
|
3145
|
+
const ORDER_STATUS = { CONFIRMED: "confirmed" };
|
|
3146
|
+
const TENDER = {
|
|
3147
|
+
CARD: "card",
|
|
3148
|
+
MOBILE_MONEY: "mobile_money",
|
|
3149
|
+
AUTHORITY_TRANSIENT: "transient",
|
|
3150
|
+
MTN: "mtn"
|
|
3151
|
+
};
|
|
3152
|
+
const PAYMENT_PROVIDER = { PAYSTACK: "paystack" };
|
|
3153
|
+
const SOURCE_KIND = { CART: "cart" };
|
|
3154
|
+
const AUTHORIZATION = { OTP: "otp" };
|
|
3155
|
+
const EXACT_ZERO_MONEY = /^[+-]?0+(?:\\.0+)?(?:[eE][+-]?\\d+)?$/;
|
|
3156
|
+
const qs = new URLSearchParams(location.search);
|
|
3157
|
+
const AUTO = qs.get("auto") === "true";
|
|
3158
|
+
const DEMO_OTP = qs.get("otp") || "123456";
|
|
3159
|
+
const ORIGIN = qs.get("origin") || "*";
|
|
3160
|
+
const NONCE = qs.get("nonce");
|
|
3161
|
+
const state = {
|
|
3046
3162
|
businessId: DEFAULT_BUSINESS,
|
|
3047
3163
|
token: null,
|
|
3048
3164
|
cart: null,
|
|
@@ -3053,15 +3169,33 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3053
3169
|
contact: null,
|
|
3054
3170
|
pendingOtp: null
|
|
3055
3171
|
};
|
|
3056
|
-
|
|
3057
|
-
|
|
3172
|
+
const content = document.getElementById("content");
|
|
3173
|
+
const title = document.getElementById("title");
|
|
3058
3174
|
|
|
3059
3175
|
function send(msg) {
|
|
3060
3176
|
if (NONCE) msg.nonce = NONCE;
|
|
3061
3177
|
parent.postMessage(msg, ORIGIN);
|
|
3062
3178
|
}
|
|
3179
|
+
function isExactlyZeroMoney(value) {
|
|
3180
|
+
return typeof value === "number"
|
|
3181
|
+
? Object.is(value, 0) || Object.is(value, -0)
|
|
3182
|
+
: EXACT_ZERO_MONEY.test(String(value).trim());
|
|
3183
|
+
}
|
|
3063
3184
|
function reportHeight() { send({ type: MSG.HEIGHT_CHANGE, height: document.documentElement.scrollHeight }); }
|
|
3064
3185
|
function ready() { send({ type: MSG.READY, height: document.documentElement.scrollHeight }); }
|
|
3186
|
+
function responseWithBody(response) {
|
|
3187
|
+
return response.json().then(function (body) {
|
|
3188
|
+
return { status: response.status, body: body };
|
|
3189
|
+
});
|
|
3190
|
+
}
|
|
3191
|
+
function assertSuccessfulResponse(response, fallbackMessage) {
|
|
3192
|
+
if (response.status >= 400) {
|
|
3193
|
+
throw new Error(
|
|
3194
|
+
(response.body && response.body.error && response.body.error.message) || fallbackMessage
|
|
3195
|
+
);
|
|
3196
|
+
}
|
|
3197
|
+
return response.body;
|
|
3198
|
+
}
|
|
3065
3199
|
|
|
3066
3200
|
function defaultAddress() {
|
|
3067
3201
|
return {
|
|
@@ -3071,9 +3205,20 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3071
3205
|
};
|
|
3072
3206
|
}
|
|
3073
3207
|
function defaultPayment(type) {
|
|
3074
|
-
if (type ===
|
|
3075
|
-
|
|
3076
|
-
|
|
3208
|
+
if (type === TENDER.CARD) {
|
|
3209
|
+
return {
|
|
3210
|
+
type: TENDER.CARD,
|
|
3211
|
+
provider: PAYMENT_PROVIDER.PAYSTACK,
|
|
3212
|
+
last_four: "4242",
|
|
3213
|
+
label: "Visa \u2022\u2022\u2022\u2022 4242"
|
|
3214
|
+
};
|
|
3215
|
+
}
|
|
3216
|
+
return {
|
|
3217
|
+
type: TENDER.MOBILE_MONEY,
|
|
3218
|
+
provider: TENDER.MTN,
|
|
3219
|
+
phone_number: "+233244000000",
|
|
3220
|
+
label: "MTN Mobile Money"
|
|
3221
|
+
};
|
|
3077
3222
|
}
|
|
3078
3223
|
|
|
3079
3224
|
function renderAuth() {
|
|
@@ -3098,12 +3243,12 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3098
3243
|
' <div class="option" data-key="lagos">5 Allen Ave, Ikeja, Lagos</div>' +
|
|
3099
3244
|
'</div>' +
|
|
3100
3245
|
'<button id="confirm">Use this address</button>';
|
|
3101
|
-
|
|
3246
|
+
const options = {
|
|
3102
3247
|
"default": defaultAddress(),
|
|
3103
3248
|
"east-legon": { street_address: "8 Ring Road", city: "Accra", region: "Greater Accra", country: "GH", latitude: 5.65, longitude: -0.16 },
|
|
3104
3249
|
"lagos": { street_address: "5 Allen Avenue", city: "Lagos", region: "Lagos", country: "NG", latitude: 6.5244, longitude: 3.3792 }
|
|
3105
3250
|
};
|
|
3106
|
-
|
|
3251
|
+
let picked = "default";
|
|
3107
3252
|
Array.prototype.forEach.call(document.querySelectorAll(".option"), function (el) {
|
|
3108
3253
|
el.onclick = function () {
|
|
3109
3254
|
picked = el.getAttribute("data-key");
|
|
@@ -3126,10 +3271,9 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3126
3271
|
'<div class="options" id="pay-options">' +
|
|
3127
3272
|
' <div class="option selected" data-method="mobile_money">\u{1F4F1} MTN Mobile Money</div>' +
|
|
3128
3273
|
' <div class="option" data-method="card">\u{1F4B3} Card (Paystack)</div>' +
|
|
3129
|
-
' <div class="option" data-method="cash">\u{1F4B5} Cash on delivery</div>' +
|
|
3130
3274
|
'</div>' +
|
|
3131
3275
|
'<button id="confirm">Use this method</button>';
|
|
3132
|
-
|
|
3276
|
+
let picked = TENDER.MOBILE_MONEY;
|
|
3133
3277
|
Array.prototype.forEach.call(document.querySelectorAll(".option"), function (el) {
|
|
3134
3278
|
el.onclick = function () {
|
|
3135
3279
|
picked = el.getAttribute("data-method");
|
|
@@ -3173,7 +3317,6 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3173
3317
|
'</div>' +
|
|
3174
3318
|
'<label>Payment method</label>' +
|
|
3175
3319
|
'<select id="pay-method">' +
|
|
3176
|
-
' <option value="cash">Cash</option>' +
|
|
3177
3320
|
' <option value="mobile_money">Mobile Money (MTN)</option>' +
|
|
3178
3321
|
' <option value="card">Card (Paystack)</option>' +
|
|
3179
3322
|
'</select>' +
|
|
@@ -3190,65 +3333,139 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3190
3333
|
}
|
|
3191
3334
|
|
|
3192
3335
|
function runCheckout() {
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3336
|
+
const statusEl = document.getElementById("status");
|
|
3337
|
+
const errEl = document.getElementById("err");
|
|
3338
|
+
const resultEl = document.getElementById("result");
|
|
3196
3339
|
if (errEl) errEl.textContent = "";
|
|
3197
3340
|
if (!state.cart) { errEl.textContent = "No cart provided"; return; }
|
|
3198
|
-
|
|
3341
|
+
const customer = {
|
|
3199
3342
|
name: document.getElementById("cust-name").value.trim() || "Customer",
|
|
3200
3343
|
email: document.getElementById("cust-email").value.trim() || "noemail@example.com",
|
|
3201
3344
|
phone: document.getElementById("cust-phone").value.trim() || "+233000000000",
|
|
3202
3345
|
save_details: false
|
|
3203
3346
|
};
|
|
3204
|
-
|
|
3205
|
-
|
|
3347
|
+
const paymentMethod = document.getElementById("pay-method").value;
|
|
3348
|
+
const orderType = document.getElementById("order-type").value;
|
|
3206
3349
|
statusEl.textContent = "Processing\u2026";
|
|
3207
|
-
send({ type: MSG.CHECKOUT_STATUS, status:
|
|
3350
|
+
send({ type: MSG.CHECKOUT_STATUS, status: CHECKOUT_STATUS.PROCESSING, context: {} });
|
|
3208
3351
|
|
|
3209
|
-
|
|
3352
|
+
const headers = { "content-type": "application/json" };
|
|
3210
3353
|
if (state.token) headers["x-session-token"] = state.token;
|
|
3211
3354
|
|
|
3212
|
-
|
|
3355
|
+
const preference = paymentMethod === TENDER.MOBILE_MONEY
|
|
3356
|
+
? {
|
|
3357
|
+
method_kind: TENDER.MOBILE_MONEY,
|
|
3358
|
+
authority: {
|
|
3359
|
+
authority_kind: TENDER.AUTHORITY_TRANSIENT,
|
|
3360
|
+
phone_number: customer.phone,
|
|
3361
|
+
network: TENDER.MTN
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
: { method_kind: TENDER.CARD };
|
|
3365
|
+
const intentKey = "mock-element:" + state.cart.id;
|
|
3366
|
+
fetch(PURCHASE_INTENT.PATH, {
|
|
3213
3367
|
method: "POST",
|
|
3214
3368
|
headers: headers,
|
|
3215
3369
|
body: JSON.stringify({
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3370
|
+
client_intent_key: intentKey,
|
|
3371
|
+
source: { kind: SOURCE_KIND.CART, cart_id: state.cart.id },
|
|
3372
|
+
checkout: {
|
|
3373
|
+
customer: customer,
|
|
3374
|
+
order_type: orderType,
|
|
3375
|
+
address_info: state.address || {},
|
|
3376
|
+
tender_preference: preference
|
|
3377
|
+
}
|
|
3221
3378
|
})
|
|
3222
3379
|
})
|
|
3223
|
-
.then(
|
|
3380
|
+
.then(responseWithBody)
|
|
3224
3381
|
.then(function (resp) {
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3382
|
+
const intent = assertSuccessfulResponse(resp, "Intent creation failed");
|
|
3383
|
+
const terms = intent.current_terms;
|
|
3384
|
+
const option = terms && terms.payment_options && terms.payment_options.filter(function (candidate) {
|
|
3385
|
+
return candidate.status === PURCHASE_INTENT.ELIGIBLE && candidate.method_kind === preference.method_kind;
|
|
3386
|
+
})[0];
|
|
3387
|
+
if (!terms || (!option && !isExactlyZeroMoney(terms.money.rail_amount))) {
|
|
3388
|
+
throw new Error("No eligible payment option");
|
|
3389
|
+
}
|
|
3390
|
+
const confirmationPath = PURCHASE_INTENT.PATH + "/" + encodeURIComponent(intent.id) + "/confirm";
|
|
3391
|
+
const confirmationBody = JSON.stringify({
|
|
3392
|
+
accepted_intent_revision: terms.intent_revision,
|
|
3393
|
+
accepted_terms_version: terms.terms_version,
|
|
3394
|
+
accepted_due_now: terms.money.due_now,
|
|
3395
|
+
accepted_customer_debit_amount: option
|
|
3396
|
+
? option.customer_debit_amount
|
|
3397
|
+
: terms.money.rail_amount,
|
|
3398
|
+
currency: terms.money.currency,
|
|
3399
|
+
payment_option_id: option ? option.id : null,
|
|
3400
|
+
idempotency_key: "mock-confirm:" + intent.id
|
|
3401
|
+
});
|
|
3402
|
+
function confirmIntent() {
|
|
3403
|
+
return fetch(confirmationPath, {
|
|
3404
|
+
method: "POST",
|
|
3405
|
+
headers: headers,
|
|
3406
|
+
body: confirmationBody
|
|
3407
|
+
})
|
|
3408
|
+
.then(responseWithBody)
|
|
3409
|
+
.then(function (response) {
|
|
3410
|
+
return assertSuccessfulResponse(response, "Intent confirmation failed");
|
|
3411
|
+
});
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3414
|
+
return confirmIntent().then(function (outcome) {
|
|
3415
|
+
// This mock has no external provider window. Replaying the exact
|
|
3416
|
+
// idempotent confirmation models the provider-approved callback.
|
|
3417
|
+
return outcome.status === PURCHASE_INTENT.CARD_POPUP_REQUIRED
|
|
3418
|
+
? confirmIntent()
|
|
3419
|
+
: outcome;
|
|
3420
|
+
});
|
|
3421
|
+
})
|
|
3422
|
+
.then(function (outcome) {
|
|
3423
|
+
if (outcome.status !== PURCHASE_INTENT.AUTHORIZATION_REQUIRED) return outcome;
|
|
3424
|
+
return fetch(
|
|
3425
|
+
PURCHASE_INTENT.PATH + "/" + encodeURIComponent(outcome.intent_id) +
|
|
3426
|
+
"/attempts/" + encodeURIComponent(outcome.attempt_id) + "/actions",
|
|
3427
|
+
{
|
|
3428
|
+
method: "POST",
|
|
3429
|
+
headers: headers,
|
|
3430
|
+
body: JSON.stringify({ authorization: { type: AUTHORIZATION.OTP, value: DEMO_OTP } })
|
|
3431
|
+
}
|
|
3432
|
+
)
|
|
3433
|
+
.then(responseWithBody)
|
|
3434
|
+
.then(function (response) {
|
|
3435
|
+
return assertSuccessfulResponse(response, "Authorization failed");
|
|
3436
|
+
});
|
|
3437
|
+
})
|
|
3438
|
+
.then(function (outcome) {
|
|
3439
|
+
if (outcome.status !== PURCHASE_INTENT.ORDER_CREATED) {
|
|
3440
|
+
throw new Error("Checkout requires " + outcome.status.replace(/_/g, " "));
|
|
3231
3441
|
}
|
|
3232
|
-
|
|
3233
|
-
|
|
3442
|
+
send({
|
|
3443
|
+
type: MSG.CHECKOUT_STATUS,
|
|
3444
|
+
status: CHECKOUT_STATUS.SUCCESS,
|
|
3445
|
+
context: { order_id: outcome.order_id }
|
|
3446
|
+
});
|
|
3234
3447
|
send({
|
|
3235
3448
|
type: MSG.CHECKOUT_COMPLETE,
|
|
3236
3449
|
success: true,
|
|
3237
3450
|
order: {
|
|
3238
|
-
id:
|
|
3239
|
-
order_number:
|
|
3240
|
-
status:
|
|
3451
|
+
id: outcome.order_id,
|
|
3452
|
+
order_number: outcome.order_number || outcome.order_id,
|
|
3453
|
+
status: ORDER_STATUS.CONFIRMED,
|
|
3241
3454
|
total: (state.cart && state.cart.total_price) || "0.00",
|
|
3242
3455
|
currency: (state.cart && state.cart.currency) || "GHS"
|
|
3243
3456
|
}
|
|
3244
3457
|
});
|
|
3245
|
-
statusEl.textContent = "Success \u2014 order " +
|
|
3458
|
+
statusEl.textContent = "Success \u2014 order " + outcome.order_id;
|
|
3246
3459
|
resultEl.style.display = "block";
|
|
3247
|
-
resultEl.textContent = JSON.stringify(
|
|
3460
|
+
resultEl.textContent = JSON.stringify(outcome, null, 2);
|
|
3248
3461
|
})
|
|
3249
3462
|
.catch(function (e) {
|
|
3250
|
-
send({
|
|
3251
|
-
|
|
3463
|
+
send({
|
|
3464
|
+
type: MSG.CHECKOUT_COMPLETE,
|
|
3465
|
+
success: false,
|
|
3466
|
+
error: { code: CHECKOUT_ERROR.FAILED, message: String(e), recoverable: true }
|
|
3467
|
+
});
|
|
3468
|
+
statusEl.textContent = "Failed";
|
|
3252
3469
|
errEl.textContent = String(e);
|
|
3253
3470
|
});
|
|
3254
3471
|
}
|
|
@@ -3265,7 +3482,7 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3265
3482
|
break;
|
|
3266
3483
|
case MSG.SET_CART:
|
|
3267
3484
|
state.cart = msg.cart;
|
|
3268
|
-
|
|
3485
|
+
const s = document.getElementById("status");
|
|
3269
3486
|
if (s) s.textContent = "Cart loaded \u2014 " + (msg.cart && msg.cart.items ? msg.cart.items.length : 0) + " item(s), " + ((msg.cart && msg.cart.currency) || "GHS") + " " + ((msg.cart && msg.cart.total_price) || "0.00");
|
|
3270
3487
|
reportHeight();
|
|
3271
3488
|
break;
|
|
@@ -3289,7 +3506,7 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3289
3506
|
}
|
|
3290
3507
|
break;
|
|
3291
3508
|
case MSG.ABORT_CHECKOUT:
|
|
3292
|
-
send({ type: MSG.CHECKOUT_STATUS, status:
|
|
3509
|
+
send({ type: MSG.CHECKOUT_STATUS, status: CHECKOUT_STATUS.FAILED, context: {} });
|
|
3293
3510
|
break;
|
|
3294
3511
|
}
|
|
3295
3512
|
}
|
|
@@ -3903,6 +4120,7 @@ function createAuthService(opts) {
|
|
|
3903
4120
|
token: id,
|
|
3904
4121
|
business_id: options.defaultBusinessId,
|
|
3905
4122
|
is_authenticated: authenticated,
|
|
4123
|
+
account_id: authenticated ? ids.raw("account") : void 0,
|
|
3906
4124
|
customer_id: authenticated ? ids.customer() : void 0,
|
|
3907
4125
|
customer_name: profile?.name,
|
|
3908
4126
|
customer_email: profile?.email,
|
|
@@ -3985,7 +4203,7 @@ function createAuthService(opts) {
|
|
|
3985
4203
|
if (!s) return { is_authenticated: false, user_type: "guest" };
|
|
3986
4204
|
return {
|
|
3987
4205
|
is_authenticated: s.is_authenticated,
|
|
3988
|
-
account_id: s.
|
|
4206
|
+
account_id: s.account_id,
|
|
3989
4207
|
user_type: s.is_authenticated ? "customer" : "guest",
|
|
3990
4208
|
session_expires_at: s.expires_at ? Math.floor(new Date(s.expires_at).getTime() / 1e3) : void 0,
|
|
3991
4209
|
session: s
|
|
@@ -5283,88 +5501,10 @@ function createCartService(opts) {
|
|
|
5283
5501
|
};
|
|
5284
5502
|
}
|
|
5285
5503
|
|
|
5286
|
-
// src/mock/domain/
|
|
5287
|
-
function
|
|
5288
|
-
const { registry, clock,
|
|
5504
|
+
// src/mock/domain/payment.ts
|
|
5505
|
+
function createPaymentService(options) {
|
|
5506
|
+
const { registry, clock, bus } = options;
|
|
5289
5507
|
return {
|
|
5290
|
-
process(session, body) {
|
|
5291
|
-
if (!body.cart_id) throw validation("cart_id required");
|
|
5292
|
-
const c = registry.carts.get(body.cart_id);
|
|
5293
|
-
if (!c) throw notFound(`Cart ${body.cart_id} not found`);
|
|
5294
|
-
if (c.items.length === 0) throw validation("Cart is empty", { code: "CART_EMPTY" });
|
|
5295
|
-
const orderId = ids.order();
|
|
5296
|
-
const orderNumber = ids.orderNumber();
|
|
5297
|
-
const paymentId = ids.payment();
|
|
5298
|
-
const reference = ids.payment();
|
|
5299
|
-
const requiresAuth = body.payment_method === "mobile_money";
|
|
5300
|
-
const isCard = body.payment_method === "card" || body.payment_method === "stripe";
|
|
5301
|
-
const cardProvider = body.payment_method === "stripe" || body.pay_currency?.toUpperCase() === "USD" ? "stripe" : "paystack";
|
|
5302
|
-
const order = {
|
|
5303
|
-
id: orderId,
|
|
5304
|
-
business_id: c.business_id,
|
|
5305
|
-
user_friendly_id: orderNumber,
|
|
5306
|
-
channel: c.channel,
|
|
5307
|
-
status: requiresAuth ? "pending" : "confirmed",
|
|
5308
|
-
payment_state: requiresAuth ? "not_paid" : "paid",
|
|
5309
|
-
order_type: body.order_type,
|
|
5310
|
-
customer_id: session.customer_id,
|
|
5311
|
-
customer_name: body.customer.name,
|
|
5312
|
-
customer_email: body.customer.email,
|
|
5313
|
-
customer_phone: body.customer.phone,
|
|
5314
|
-
delivery_address: body.address_info?.street_address,
|
|
5315
|
-
delivery_fee: c.delivery_fee,
|
|
5316
|
-
subtotal: c.subtotal,
|
|
5317
|
-
tax_amount: c.tax_amount,
|
|
5318
|
-
service_charge: c.service_charge,
|
|
5319
|
-
total_discounts: c.total_discounts,
|
|
5320
|
-
total_price: c.total_price,
|
|
5321
|
-
currency: c.currency,
|
|
5322
|
-
items: c.items,
|
|
5323
|
-
applied_discount_ids: c.applied_discount_ids,
|
|
5324
|
-
applied_discount_codes: c.applied_discount_codes,
|
|
5325
|
-
payment_id: paymentId,
|
|
5326
|
-
payment_reference: reference,
|
|
5327
|
-
metadata: body.metadata,
|
|
5328
|
-
created_at: clock.iso(),
|
|
5329
|
-
updated_at: clock.iso()
|
|
5330
|
-
};
|
|
5331
|
-
registry.orders.put(orderId, order);
|
|
5332
|
-
registry.carts.put(c.id, { ...c, status: "converted", updated_at: clock.iso() });
|
|
5333
|
-
bus.emit("order.created", { order_id: orderId, order_number: orderNumber }, c.business_id);
|
|
5334
|
-
if (!requiresAuth) {
|
|
5335
|
-
bus.emit("order.payment.captured", { order_id: orderId, reference }, c.business_id);
|
|
5336
|
-
bus.emit("order.confirmed", { order_id: orderId }, c.business_id);
|
|
5337
|
-
}
|
|
5338
|
-
const billToken = `bt_${reference.slice(-12)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
5339
|
-
const result = {
|
|
5340
|
-
order_id: orderId,
|
|
5341
|
-
order_number: orderNumber,
|
|
5342
|
-
payment_id: paymentId,
|
|
5343
|
-
payment_status: requiresAuth || isCard ? "pending" : "succeeded",
|
|
5344
|
-
payment_reference: reference,
|
|
5345
|
-
requires_authorization: requiresAuth,
|
|
5346
|
-
authorization_type: requiresAuth ? "otp" : void 0,
|
|
5347
|
-
next_action: requiresAuth ? {
|
|
5348
|
-
type: "authorization",
|
|
5349
|
-
authorization_type: "otp",
|
|
5350
|
-
display_text: "Approve on your mobile money app"
|
|
5351
|
-
} : { type: "none" },
|
|
5352
|
-
provider: isCard ? cardProvider : body.payment_method,
|
|
5353
|
-
bill_token: billToken
|
|
5354
|
-
};
|
|
5355
|
-
if (isCard) {
|
|
5356
|
-
const proc = globalThis.process;
|
|
5357
|
-
result.client_secret = cardProvider === "stripe" ? `pi_${orderId.slice(-12)}_secret_${Math.random().toString(36).slice(2, 18)}` : `access_${reference}`;
|
|
5358
|
-
result.public_key = cardProvider === "stripe" ? proc?.env?.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ?? "pk_test_mock_stripe" : proc?.env?.NEXT_PUBLIC_PAYSTACK_PUBLIC_KEY ?? "pk_test_mock_paystack";
|
|
5359
|
-
result.next_action = {
|
|
5360
|
-
type: "card_popup",
|
|
5361
|
-
provider: cardProvider,
|
|
5362
|
-
client_secret: result.client_secret,
|
|
5363
|
-
public_key: result.public_key
|
|
5364
|
-
};
|
|
5365
|
-
}
|
|
5366
|
-
return result;
|
|
5367
|
-
},
|
|
5368
5508
|
authorize(body) {
|
|
5369
5509
|
if (!body.payment_id?.trim()) throw validation("payment_id required");
|
|
5370
5510
|
if (!body.authorization) throw validation("authorization required");
|
|
@@ -5375,7 +5515,7 @@ function createCheckoutService(opts) {
|
|
|
5375
5515
|
const updated = {
|
|
5376
5516
|
...order,
|
|
5377
5517
|
payment_state: "paid",
|
|
5378
|
-
status:
|
|
5518
|
+
status: CHECKOUT_ORDER_RESULT_STATUS.CONFIRMED,
|
|
5379
5519
|
updated_at: clock.iso()
|
|
5380
5520
|
};
|
|
5381
5521
|
registry.orders.put(order.id, updated);
|
|
@@ -5386,10 +5526,538 @@ function createCheckoutService(opts) {
|
|
|
5386
5526
|
order_number: order.user_friendly_id,
|
|
5387
5527
|
payment_id: body.payment_id,
|
|
5388
5528
|
payment_reference: order.payment_reference,
|
|
5389
|
-
payment_status:
|
|
5529
|
+
payment_status: LEGACY_CHECKOUT_PAYMENT_STATUS.SUCCEEDED,
|
|
5390
5530
|
requires_authorization: false,
|
|
5391
|
-
next_action: { type:
|
|
5531
|
+
next_action: { type: CHECKOUT_NEXT_ACTION.NONE }
|
|
5532
|
+
};
|
|
5533
|
+
}
|
|
5534
|
+
};
|
|
5535
|
+
}
|
|
5536
|
+
|
|
5537
|
+
// src/mock/domain/purchase-intent.ts
|
|
5538
|
+
var INTENT_LIFETIME_MS = 15 * 60 * 1e3;
|
|
5539
|
+
var ZERO_MONEY = "0.00";
|
|
5540
|
+
var PURCHASE_INTENT_MOBILE_MONEY_NETWORKS = new Set(
|
|
5541
|
+
Object.values(PURCHASE_INTENT_MOBILE_MONEY_NETWORK)
|
|
5542
|
+
);
|
|
5543
|
+
var MOCK_PURCHASE_INTENT = {
|
|
5544
|
+
OWNER_KIND: { ACCOUNT: "account", STOREFRONT_SESSION: "storefront_session" },
|
|
5545
|
+
CART_STATUS: { ACTIVE: "active", CONVERTED: "converted" },
|
|
5546
|
+
ORDER_STATUS: { PENDING: "pending", CONFIRMED: "confirmed" },
|
|
5547
|
+
PAYMENT_STATE: { NOT_PAID: "not_paid", PAID: "paid" },
|
|
5548
|
+
EVENT: {
|
|
5549
|
+
ORDER_CREATED: "order.created",
|
|
5550
|
+
PAYMENT_CAPTURED: "order.payment.captured",
|
|
5551
|
+
ORDER_CONFIRMED: "order.confirmed"
|
|
5552
|
+
},
|
|
5553
|
+
ID_PREFIX: { INTENT: "pi", ATTEMPT: "attempt" },
|
|
5554
|
+
DEFAULT_LOCATION_ID: "mock-location",
|
|
5555
|
+
MOCK_PAYSTACK_PUBLIC_KEY: "pk_test_mock_paystack",
|
|
5556
|
+
COMPLIANCE: {
|
|
5557
|
+
POLICY_NAME: "mock-storefront-commerce"
|
|
5558
|
+
}
|
|
5559
|
+
};
|
|
5560
|
+
var DECIMAL_WIRE_VALUE = /^([+-]?)(\d+)(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
|
|
5561
|
+
function isExactlyZero(value) {
|
|
5562
|
+
if (typeof value === "number") return Object.is(value, 0) || Object.is(value, -0);
|
|
5563
|
+
const match2 = DECIMAL_WIRE_VALUE.exec(value.trim());
|
|
5564
|
+
return Boolean(match2 && [...match2[2], ...match2[3] ?? ""].every((digit) => digit === "0"));
|
|
5565
|
+
}
|
|
5566
|
+
function sameDecimal(left, right) {
|
|
5567
|
+
const canonical = (value) => {
|
|
5568
|
+
const wire = typeof value === "number" ? String(value) : value.trim();
|
|
5569
|
+
const match2 = DECIMAL_WIRE_VALUE.exec(wire);
|
|
5570
|
+
if (!match2) return null;
|
|
5571
|
+
let digits = `${match2[2]}${match2[3] ?? ""}`.replace(/^0+/, "");
|
|
5572
|
+
if (!digits) return "0";
|
|
5573
|
+
let scale = BigInt((match2[3] ?? "").length) - BigInt(match2[4] ?? "0");
|
|
5574
|
+
while (digits.endsWith("0")) {
|
|
5575
|
+
digits = digits.slice(0, -1);
|
|
5576
|
+
scale -= 1n;
|
|
5577
|
+
}
|
|
5578
|
+
const sign = match2[1] === "-" ? "-" : "";
|
|
5579
|
+
return `${sign}${digits}:${scale}`;
|
|
5580
|
+
};
|
|
5581
|
+
const normalizedLeft = canonical(left);
|
|
5582
|
+
return normalizedLeft !== null && normalizedLeft === canonical(right);
|
|
5583
|
+
}
|
|
5584
|
+
function wireMoney(value) {
|
|
5585
|
+
return typeof value === "string" ? value.trim() : String(value);
|
|
5586
|
+
}
|
|
5587
|
+
function decimal(value) {
|
|
5588
|
+
return wireMoney(value.toFixed(2));
|
|
5589
|
+
}
|
|
5590
|
+
function paymentOptions(intentId, currency, amount, expiresAt) {
|
|
5591
|
+
const normalizedCurrency = currencyCode(currency);
|
|
5592
|
+
const normalizedAmount = wireMoney(amount);
|
|
5593
|
+
return [
|
|
5594
|
+
{
|
|
5595
|
+
id: `${intentId}:${PURCHASE_INTENT_PAYMENT_METHOD.CARD}`,
|
|
5596
|
+
rank: 0,
|
|
5597
|
+
method_kind: PURCHASE_INTENT_PAYMENT_METHOD.CARD,
|
|
5598
|
+
collection_mode: PAYMENT_COLLECTION_MODE.CREDENTIAL_CHARGE,
|
|
5599
|
+
provider: PURCHASE_INTENT_PAYMENT_PROVIDER.PAYSTACK,
|
|
5600
|
+
principal_amount: normalizedAmount,
|
|
5601
|
+
fee_amount: wireMoney(ZERO_MONEY),
|
|
5602
|
+
customer_debit_amount: normalizedAmount,
|
|
5603
|
+
currency: normalizedCurrency,
|
|
5604
|
+
status: PAYMENT_OPTION_STATUS.ELIGIBLE,
|
|
5605
|
+
expected_next_action: PAYMENT_OPTION_NEXT_ACTION.PROVIDER_APPROVAL,
|
|
5606
|
+
expires_at: expiresAt
|
|
5607
|
+
},
|
|
5608
|
+
{
|
|
5609
|
+
id: `${intentId}:${PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY}`,
|
|
5610
|
+
rank: 1,
|
|
5611
|
+
method_kind: PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY,
|
|
5612
|
+
collection_mode: PAYMENT_COLLECTION_MODE.REQUEST_TO_PAY,
|
|
5613
|
+
provider: PURCHASE_INTENT_PAYMENT_PROVIDER.PAYSTACK,
|
|
5614
|
+
principal_amount: normalizedAmount,
|
|
5615
|
+
fee_amount: wireMoney(ZERO_MONEY),
|
|
5616
|
+
customer_debit_amount: normalizedAmount,
|
|
5617
|
+
currency: normalizedCurrency,
|
|
5618
|
+
status: PAYMENT_OPTION_STATUS.ELIGIBLE,
|
|
5619
|
+
expected_next_action: PAYMENT_OPTION_NEXT_ACTION.PROVIDER_APPROVAL,
|
|
5620
|
+
expires_at: expiresAt
|
|
5621
|
+
}
|
|
5622
|
+
];
|
|
5623
|
+
}
|
|
5624
|
+
function termsForCart(input) {
|
|
5625
|
+
const total = wireMoney(input.total);
|
|
5626
|
+
return {
|
|
5627
|
+
id: `${input.intentId}:terms:${input.version}`,
|
|
5628
|
+
intent_revision: input.revision,
|
|
5629
|
+
terms_version: input.version,
|
|
5630
|
+
terms_digest: `mock:${input.intentId}:${input.revision}:${input.version}`,
|
|
5631
|
+
money: {
|
|
5632
|
+
currency: currencyCode(input.currency),
|
|
5633
|
+
subtotal: wireMoney(input.subtotal),
|
|
5634
|
+
discount_total: wireMoney(input.discount),
|
|
5635
|
+
tax_total: wireMoney(input.tax),
|
|
5636
|
+
delivery_total: wireMoney(input.delivery),
|
|
5637
|
+
statutory_total: wireMoney(ZERO_MONEY),
|
|
5638
|
+
total_obligation: total,
|
|
5639
|
+
due_now: total,
|
|
5640
|
+
rail_amount: total,
|
|
5641
|
+
store_credit_consumed: wireMoney(ZERO_MONEY),
|
|
5642
|
+
voucher_credit_consumed: wireMoney(ZERO_MONEY)
|
|
5643
|
+
},
|
|
5644
|
+
material: {
|
|
5645
|
+
line_digest: `mock-lines:${input.intentId}`,
|
|
5646
|
+
destination_digest: `mock-destination:${input.intentId}`,
|
|
5647
|
+
delivery_promise_digest: `mock-delivery:${input.intentId}`,
|
|
5648
|
+
entitlement_digest: `mock-entitlement:${input.intentId}`,
|
|
5649
|
+
cancellation_terms_digest: `mock-cancellation:${input.intentId}`
|
|
5650
|
+
},
|
|
5651
|
+
compliance: {
|
|
5652
|
+
policy_name: MOCK_PURCHASE_INTENT.COMPLIANCE.POLICY_NAME,
|
|
5653
|
+
policy_version: 1,
|
|
5654
|
+
lane: CHECKOUT_COMPLIANCE_LANE.NATIVE,
|
|
5655
|
+
reason_code: CHECKOUT_COMPLIANCE_REASON.PHYSICAL_GOODS_NATIVE,
|
|
5656
|
+
evidence_digest: `mock-compliance:${input.intentId}`
|
|
5657
|
+
},
|
|
5658
|
+
payment_options: isExactlyZero(input.total) ? [] : paymentOptions(input.intentId, input.currency, input.total, input.validUntil),
|
|
5659
|
+
valid_until: input.validUntil,
|
|
5660
|
+
created_at: input.now
|
|
5661
|
+
};
|
|
5662
|
+
}
|
|
5663
|
+
function intentView(intent) {
|
|
5664
|
+
const {
|
|
5665
|
+
intent_owner: _owner,
|
|
5666
|
+
mint_request: _request,
|
|
5667
|
+
last_confirmation: _confirmation,
|
|
5668
|
+
...view
|
|
5669
|
+
} = intent;
|
|
5670
|
+
return view;
|
|
5671
|
+
}
|
|
5672
|
+
function purchasingPrincipal(session) {
|
|
5673
|
+
if (!session.is_authenticated) {
|
|
5674
|
+
return { kind: PURCHASING_PRINCIPAL_KIND.GUEST };
|
|
5675
|
+
}
|
|
5676
|
+
if (!session.account_id) throw validation("Authenticated mock session has no account authority");
|
|
5677
|
+
return {
|
|
5678
|
+
kind: PURCHASING_PRINCIPAL_KIND.ACCOUNT,
|
|
5679
|
+
account_id: session.account_id
|
|
5680
|
+
};
|
|
5681
|
+
}
|
|
5682
|
+
function assertSupportedTenderPreference(request) {
|
|
5683
|
+
if (request.source.kind !== PURCHASE_INTENT_SOURCE_KIND.CART) return;
|
|
5684
|
+
const checkout = request.checkout;
|
|
5685
|
+
if (!checkout) throw validation("Cart checkout input is required");
|
|
5686
|
+
const preference = checkout.tender_preference;
|
|
5687
|
+
if (preference?.method_kind !== PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY || preference.authority.authority_kind !== MOBILE_MONEY_TENDER_AUTHORITY_KIND.TRANSIENT) {
|
|
5688
|
+
return;
|
|
5689
|
+
}
|
|
5690
|
+
if (!PURCHASE_INTENT_MOBILE_MONEY_NETWORKS.has(preference.authority.network)) {
|
|
5691
|
+
throw validation("Mobile Money network is not available for PurchaseIntent checkout");
|
|
5692
|
+
}
|
|
5693
|
+
}
|
|
5694
|
+
function intentOwner(session) {
|
|
5695
|
+
if (!session.is_authenticated) {
|
|
5696
|
+
return { kind: MOCK_PURCHASE_INTENT.OWNER_KIND.STOREFRONT_SESSION, id: session.id };
|
|
5697
|
+
}
|
|
5698
|
+
if (!session.account_id) throw validation("Authenticated mock session has no account authority");
|
|
5699
|
+
return { kind: MOCK_PURCHASE_INTENT.OWNER_KIND.ACCOUNT, id: session.account_id };
|
|
5700
|
+
}
|
|
5701
|
+
function createPurchaseIntentMockService(options) {
|
|
5702
|
+
const { registry, clock, ids, bus } = options;
|
|
5703
|
+
function stored(session, intentId) {
|
|
5704
|
+
const intent = registry.purchaseIntents.get(intentId);
|
|
5705
|
+
if (!intent) throw notFound(`Purchase intent ${intentId} not found`);
|
|
5706
|
+
const owner = intentOwner(session);
|
|
5707
|
+
if (intent.intent_owner.kind !== owner.kind || intent.intent_owner.id !== owner.id) {
|
|
5708
|
+
throw notFound(`Purchase intent ${intentId} not found`);
|
|
5709
|
+
}
|
|
5710
|
+
return intent;
|
|
5711
|
+
}
|
|
5712
|
+
function completeProviderOrder(intent, order, attemptId) {
|
|
5713
|
+
const updated = {
|
|
5714
|
+
...order,
|
|
5715
|
+
payment_state: MOCK_PURCHASE_INTENT.PAYMENT_STATE.PAID,
|
|
5716
|
+
status: MOCK_PURCHASE_INTENT.ORDER_STATUS.CONFIRMED,
|
|
5717
|
+
updated_at: clock.iso()
|
|
5718
|
+
};
|
|
5719
|
+
registry.orders.put(order.id, updated);
|
|
5720
|
+
bus.emit(
|
|
5721
|
+
MOCK_PURCHASE_INTENT.EVENT.PAYMENT_CAPTURED,
|
|
5722
|
+
{ order_id: order.id, reference: order.payment_reference },
|
|
5723
|
+
order.business_id
|
|
5724
|
+
);
|
|
5725
|
+
bus.emit(MOCK_PURCHASE_INTENT.EVENT.ORDER_CONFIRMED, { order_id: order.id }, order.business_id);
|
|
5726
|
+
const completed = {
|
|
5727
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED,
|
|
5728
|
+
intent_id: intent.id,
|
|
5729
|
+
attempt_id: attemptId,
|
|
5730
|
+
order_id: order.id,
|
|
5731
|
+
order_number: order.user_friendly_id,
|
|
5732
|
+
payment_id: order.payment_id
|
|
5733
|
+
};
|
|
5734
|
+
registry.purchaseIntents.put(intent.id, {
|
|
5735
|
+
...intent,
|
|
5736
|
+
updated_at: clock.iso(),
|
|
5737
|
+
last_confirmation: completed
|
|
5738
|
+
});
|
|
5739
|
+
return completed;
|
|
5740
|
+
}
|
|
5741
|
+
return {
|
|
5742
|
+
mint(session, request) {
|
|
5743
|
+
if (!request.client_intent_key.trim()) throw validation("client_intent_key required");
|
|
5744
|
+
if (request.source.kind !== PURCHASE_INTENT_SOURCE_KIND.CART) {
|
|
5745
|
+
throw validation("The mock currently prepares cart purchase intents only");
|
|
5746
|
+
}
|
|
5747
|
+
const checkoutInput = request.checkout;
|
|
5748
|
+
if (!checkoutInput) throw validation("Cart checkout input is required");
|
|
5749
|
+
assertSupportedTenderPreference(request);
|
|
5750
|
+
const cart = registry.carts.get(request.source.cart_id);
|
|
5751
|
+
if (!cart) throw notFound(`Cart ${request.source.cart_id} not found`);
|
|
5752
|
+
if (cart.items.length === 0) {
|
|
5753
|
+
throw validation("Cart is empty", { code: ErrorCode.CART_EMPTY });
|
|
5754
|
+
}
|
|
5755
|
+
const principal = purchasingPrincipal(session);
|
|
5756
|
+
const owner = intentOwner(session);
|
|
5757
|
+
const existing = registry.purchaseIntents.list(
|
|
5758
|
+
(candidate) => candidate.mint_request.client_intent_key === request.client_intent_key && candidate.intent_owner.kind === owner.kind && candidate.intent_owner.id === owner.id
|
|
5759
|
+
)[0];
|
|
5760
|
+
if (existing) return intentView(existing);
|
|
5761
|
+
const now = clock.iso();
|
|
5762
|
+
const expiresAt = new Date(clock.nowMs() + INTENT_LIFETIME_MS).toISOString();
|
|
5763
|
+
const intentId = ids.raw(MOCK_PURCHASE_INTENT.ID_PREFIX.INTENT);
|
|
5764
|
+
const terms = termsForCart({
|
|
5765
|
+
intentId,
|
|
5766
|
+
revision: 1,
|
|
5767
|
+
version: 1,
|
|
5768
|
+
currency: cart.currency,
|
|
5769
|
+
subtotal: cart.subtotal,
|
|
5770
|
+
discount: cart.total_discounts,
|
|
5771
|
+
tax: cart.tax_amount,
|
|
5772
|
+
delivery: cart.delivery_fee,
|
|
5773
|
+
total: cart.total_price,
|
|
5774
|
+
now,
|
|
5775
|
+
validUntil: expiresAt
|
|
5776
|
+
});
|
|
5777
|
+
const intent = {
|
|
5778
|
+
id: intentId,
|
|
5779
|
+
seller_business_id: cart.business_id,
|
|
5780
|
+
principal,
|
|
5781
|
+
revision: 1,
|
|
5782
|
+
status: PURCHASE_INTENT_STATUS.OPEN,
|
|
5783
|
+
source: {
|
|
5784
|
+
kind: PURCHASE_INTENT_SOURCE_KIND.CART,
|
|
5785
|
+
source_id: cart.id,
|
|
5786
|
+
source_version: cart.updated_at,
|
|
5787
|
+
seller_business_id: cart.business_id,
|
|
5788
|
+
subject: {
|
|
5789
|
+
kind: PURCHASING_PRINCIPAL_KIND.BUSINESS,
|
|
5790
|
+
business_id: cart.business_id
|
|
5791
|
+
},
|
|
5792
|
+
binding_digest: `mock-cart:${cart.id}:${cart.updated_at}`
|
|
5793
|
+
},
|
|
5794
|
+
lines: cart.items.map((line, ordinal) => ({
|
|
5795
|
+
id: line.id,
|
|
5796
|
+
ordinal,
|
|
5797
|
+
sellable: {
|
|
5798
|
+
kind: line.variant_id ? PURCHASE_INTENT_SELLABLE_KIND.VARIANT : PURCHASE_INTENT_SELLABLE_KIND.PRODUCT,
|
|
5799
|
+
product_id: line.item_id,
|
|
5800
|
+
variant_id: line.variant_id,
|
|
5801
|
+
location_id: checkoutInput.location_id || MOCK_PURCHASE_INTENT.DEFAULT_LOCATION_ID
|
|
5802
|
+
},
|
|
5803
|
+
quantity: line.quantity,
|
|
5804
|
+
configuration: {
|
|
5805
|
+
kind: PURCHASE_INTENT_LINE_CONFIGURATION_KIND.SIMPLE,
|
|
5806
|
+
variant_id: line.variant_id,
|
|
5807
|
+
customer_inputs: line.customer_inputs
|
|
5808
|
+
}
|
|
5809
|
+
})),
|
|
5810
|
+
line_pricing: cart.items.map((line) => {
|
|
5811
|
+
const unitPrice = Number(line.price) + Number(line.add_ons_price);
|
|
5812
|
+
const lineSubtotal = unitPrice * line.quantity - Number(line.item_discount_amount);
|
|
5813
|
+
return {
|
|
5814
|
+
intent_line_id: line.id,
|
|
5815
|
+
quantity: line.quantity,
|
|
5816
|
+
unit_price: decimal(unitPrice),
|
|
5817
|
+
line_subtotal: decimal(lineSubtotal),
|
|
5818
|
+
currency: currencyCode(cart.currency)
|
|
5819
|
+
};
|
|
5820
|
+
}),
|
|
5821
|
+
current_terms: terms,
|
|
5822
|
+
expires_at: expiresAt,
|
|
5823
|
+
created_at: now,
|
|
5824
|
+
updated_at: now,
|
|
5825
|
+
intent_owner: owner,
|
|
5826
|
+
mint_request: request
|
|
5827
|
+
};
|
|
5828
|
+
registry.purchaseIntents.put(intentId, intent);
|
|
5829
|
+
return intentView(intent);
|
|
5830
|
+
},
|
|
5831
|
+
get(session, intentId) {
|
|
5832
|
+
return intentView(stored(session, intentId));
|
|
5833
|
+
},
|
|
5834
|
+
refresh(session, intentId, expectedRevision) {
|
|
5835
|
+
const intent = stored(session, intentId);
|
|
5836
|
+
if (intent.revision !== expectedRevision) {
|
|
5837
|
+
throw validation("expected_intent_revision does not match current intent revision");
|
|
5838
|
+
}
|
|
5839
|
+
if (!intent.current_terms) throw validation("Purchase intent has no current terms");
|
|
5840
|
+
const previous = intent.current_terms;
|
|
5841
|
+
const nextDelivery = Number(previous.money.delivery_total) + 1;
|
|
5842
|
+
const nextTotal = Number(previous.money.total_obligation) + 1;
|
|
5843
|
+
const now = clock.iso();
|
|
5844
|
+
const replacement = termsForCart({
|
|
5845
|
+
intentId,
|
|
5846
|
+
revision: intent.revision,
|
|
5847
|
+
version: previous.terms_version + 1,
|
|
5848
|
+
currency: previous.money.currency,
|
|
5849
|
+
subtotal: String(previous.money.subtotal),
|
|
5850
|
+
discount: String(previous.money.discount_total),
|
|
5851
|
+
tax: String(previous.money.tax_total),
|
|
5852
|
+
delivery: nextDelivery.toFixed(2),
|
|
5853
|
+
total: nextTotal.toFixed(2),
|
|
5854
|
+
now,
|
|
5855
|
+
validUntil: intent.expires_at
|
|
5856
|
+
});
|
|
5857
|
+
const updated = { ...intent, current_terms: replacement, updated_at: now };
|
|
5858
|
+
registry.purchaseIntents.put(intentId, updated);
|
|
5859
|
+
return intentView(updated);
|
|
5860
|
+
},
|
|
5861
|
+
confirm(session, intentId, request) {
|
|
5862
|
+
const intent = stored(session, intentId);
|
|
5863
|
+
if (intent.status === PURCHASE_INTENT_STATUS.CONVERTED && intent.last_confirmation) {
|
|
5864
|
+
const orderId2 = "order_id" in intent.last_confirmation ? intent.last_confirmation.order_id : void 0;
|
|
5865
|
+
const order2 = orderId2 ? registry.orders.get(orderId2) : void 0;
|
|
5866
|
+
if (order2?.payment_state === MOCK_PURCHASE_INTENT.PAYMENT_STATE.PAID) {
|
|
5867
|
+
return {
|
|
5868
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED,
|
|
5869
|
+
intent_id: intent.id,
|
|
5870
|
+
attempt_id: "attempt_id" in intent.last_confirmation ? intent.last_confirmation.attempt_id : ids.raw(MOCK_PURCHASE_INTENT.ID_PREFIX.ATTEMPT),
|
|
5871
|
+
order_id: order2.id
|
|
5872
|
+
};
|
|
5873
|
+
}
|
|
5874
|
+
if (order2?.payment_id && intent.last_confirmation.status === PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED) {
|
|
5875
|
+
return completeProviderOrder(intent, order2, intent.last_confirmation.attempt_id);
|
|
5876
|
+
}
|
|
5877
|
+
return intent.last_confirmation;
|
|
5878
|
+
}
|
|
5879
|
+
const terms = intent.current_terms;
|
|
5880
|
+
if (!terms) throw validation("Purchase intent has no current terms");
|
|
5881
|
+
const zeroRail = isExactlyZero(terms.money.rail_amount);
|
|
5882
|
+
const option = request.payment_option_id ? terms.payment_options.find(
|
|
5883
|
+
(candidate) => candidate.id === request.payment_option_id && candidate.status === PAYMENT_OPTION_STATUS.ELIGIBLE
|
|
5884
|
+
) : void 0;
|
|
5885
|
+
const acceptedBaseTermsChanged = !sameDecimal(request.accepted_due_now, terms.money.due_now) || request.currency !== terms.money.currency;
|
|
5886
|
+
if (request.accepted_intent_revision !== intent.revision || request.accepted_terms_version !== terms.terms_version || acceptedBaseTermsChanged) {
|
|
5887
|
+
const deltas = acceptedBaseTermsChanged ? [
|
|
5888
|
+
{
|
|
5889
|
+
kind: CHECKOUT_TERMS_DELTA_KIND.MONEY,
|
|
5890
|
+
component: CHECKOUT_TERMS_COMPONENT.DUE_NOW,
|
|
5891
|
+
accepted: request.accepted_due_now,
|
|
5892
|
+
replacement: terms.money.due_now
|
|
5893
|
+
}
|
|
5894
|
+
] : [
|
|
5895
|
+
{
|
|
5896
|
+
kind: CHECKOUT_TERMS_DELTA_KIND.PAYMENT_OPTION,
|
|
5897
|
+
accepted_option_id: request.payment_option_id ?? null,
|
|
5898
|
+
accepted_customer_debit_amount: request.accepted_customer_debit_amount,
|
|
5899
|
+
replacement_option_id: option?.id ?? null,
|
|
5900
|
+
replacement_customer_debit_amount: option?.customer_debit_amount ?? null
|
|
5901
|
+
}
|
|
5902
|
+
];
|
|
5903
|
+
return {
|
|
5904
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED,
|
|
5905
|
+
intent_id: intent.id,
|
|
5906
|
+
replacement: terms,
|
|
5907
|
+
deltas
|
|
5908
|
+
};
|
|
5909
|
+
}
|
|
5910
|
+
if (!zeroRail && !option || zeroRail && request.payment_option_id != null) {
|
|
5911
|
+
return {
|
|
5912
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.SELECTION_UNAVAILABLE,
|
|
5913
|
+
intent_id: intent.id,
|
|
5914
|
+
lines: intent.lines.map((line) => ({
|
|
5915
|
+
line_id: line.id,
|
|
5916
|
+
reason: CHECKOUT_INVALIDATION_REASON.PAYMENT_OPTION_CHANGED
|
|
5917
|
+
}))
|
|
5918
|
+
};
|
|
5919
|
+
}
|
|
5920
|
+
const acceptedCustomerDebitMatches = zeroRail ? isExactlyZero(request.accepted_customer_debit_amount) : Boolean(
|
|
5921
|
+
option && sameDecimal(request.accepted_customer_debit_amount, option.customer_debit_amount)
|
|
5922
|
+
);
|
|
5923
|
+
if (!acceptedCustomerDebitMatches) {
|
|
5924
|
+
return {
|
|
5925
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED,
|
|
5926
|
+
intent_id: intent.id,
|
|
5927
|
+
replacement: terms,
|
|
5928
|
+
deltas: [
|
|
5929
|
+
{
|
|
5930
|
+
kind: CHECKOUT_TERMS_DELTA_KIND.PAYMENT_OPTION,
|
|
5931
|
+
accepted_option_id: request.payment_option_id ?? null,
|
|
5932
|
+
accepted_customer_debit_amount: request.accepted_customer_debit_amount,
|
|
5933
|
+
replacement_option_id: option?.id ?? null,
|
|
5934
|
+
replacement_customer_debit_amount: option?.customer_debit_amount ?? null
|
|
5935
|
+
}
|
|
5936
|
+
]
|
|
5937
|
+
};
|
|
5938
|
+
}
|
|
5939
|
+
if (intent.mint_request.source.kind !== PURCHASE_INTENT_SOURCE_KIND.CART) {
|
|
5940
|
+
throw validation("The mock currently confirms cart purchase intents only");
|
|
5941
|
+
}
|
|
5942
|
+
const checkoutInput = intent.mint_request.checkout;
|
|
5943
|
+
if (!checkoutInput) throw validation("Cart checkout input is required");
|
|
5944
|
+
const cart = registry.carts.get(intent.mint_request.source.cart_id);
|
|
5945
|
+
if (!cart || cart.status !== MOCK_PURCHASE_INTENT.CART_STATUS.ACTIVE) {
|
|
5946
|
+
return { status: PURCHASE_INTENT_CONFIRM_STATUS.SOURCE_UNAVAILABLE, intent_id: intent.id };
|
|
5947
|
+
}
|
|
5948
|
+
const attemptId = ids.raw(MOCK_PURCHASE_INTENT.ID_PREFIX.ATTEMPT);
|
|
5949
|
+
const orderId = ids.order();
|
|
5950
|
+
const orderNumber = ids.orderNumber();
|
|
5951
|
+
const paymentId = zeroRail ? void 0 : ids.payment();
|
|
5952
|
+
const paymentReference = zeroRail ? void 0 : ids.payment();
|
|
5953
|
+
const needsProvider = option?.method_kind === PURCHASE_INTENT_PAYMENT_METHOD.CARD || option?.method_kind === PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY;
|
|
5954
|
+
const paid = zeroRail;
|
|
5955
|
+
const order = {
|
|
5956
|
+
id: orderId,
|
|
5957
|
+
business_id: cart.business_id,
|
|
5958
|
+
user_friendly_id: orderNumber,
|
|
5959
|
+
channel: cart.channel,
|
|
5960
|
+
status: paid ? MOCK_PURCHASE_INTENT.ORDER_STATUS.CONFIRMED : MOCK_PURCHASE_INTENT.ORDER_STATUS.PENDING,
|
|
5961
|
+
payment_state: paid ? MOCK_PURCHASE_INTENT.PAYMENT_STATE.PAID : MOCK_PURCHASE_INTENT.PAYMENT_STATE.NOT_PAID,
|
|
5962
|
+
order_type: checkoutInput.order_type,
|
|
5963
|
+
customer_id: session.customer_id,
|
|
5964
|
+
customer_name: checkoutInput.customer.name,
|
|
5965
|
+
customer_email: checkoutInput.customer.email,
|
|
5966
|
+
customer_phone: checkoutInput.customer.phone,
|
|
5967
|
+
delivery_address: checkoutInput.address_info.street_address,
|
|
5968
|
+
delivery_fee: cart.delivery_fee,
|
|
5969
|
+
subtotal: cart.subtotal,
|
|
5970
|
+
tax_amount: cart.tax_amount,
|
|
5971
|
+
service_charge: cart.service_charge,
|
|
5972
|
+
total_discounts: cart.total_discounts,
|
|
5973
|
+
total_price: cart.total_price,
|
|
5974
|
+
currency: cart.currency,
|
|
5975
|
+
items: cart.items,
|
|
5976
|
+
applied_discount_ids: cart.applied_discount_ids,
|
|
5977
|
+
applied_discount_codes: cart.applied_discount_codes,
|
|
5978
|
+
payment_id: paymentId,
|
|
5979
|
+
payment_reference: paymentReference,
|
|
5980
|
+
metadata: checkoutInput.metadata,
|
|
5981
|
+
created_at: clock.iso(),
|
|
5982
|
+
updated_at: clock.iso()
|
|
5392
5983
|
};
|
|
5984
|
+
registry.orders.put(orderId, order);
|
|
5985
|
+
registry.carts.put(cart.id, {
|
|
5986
|
+
...cart,
|
|
5987
|
+
status: MOCK_PURCHASE_INTENT.CART_STATUS.CONVERTED,
|
|
5988
|
+
updated_at: clock.iso()
|
|
5989
|
+
});
|
|
5990
|
+
bus.emit(
|
|
5991
|
+
MOCK_PURCHASE_INTENT.EVENT.ORDER_CREATED,
|
|
5992
|
+
{ order_id: orderId, order_number: orderNumber },
|
|
5993
|
+
cart.business_id
|
|
5994
|
+
);
|
|
5995
|
+
if (paid) {
|
|
5996
|
+
if (paymentReference) {
|
|
5997
|
+
bus.emit(
|
|
5998
|
+
MOCK_PURCHASE_INTENT.EVENT.PAYMENT_CAPTURED,
|
|
5999
|
+
{ order_id: orderId, reference: paymentReference },
|
|
6000
|
+
cart.business_id
|
|
6001
|
+
);
|
|
6002
|
+
}
|
|
6003
|
+
bus.emit(
|
|
6004
|
+
MOCK_PURCHASE_INTENT.EVENT.ORDER_CONFIRMED,
|
|
6005
|
+
{ order_id: orderId },
|
|
6006
|
+
cart.business_id
|
|
6007
|
+
);
|
|
6008
|
+
}
|
|
6009
|
+
let confirmation;
|
|
6010
|
+
if (option?.method_kind === PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY) {
|
|
6011
|
+
confirmation = {
|
|
6012
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED,
|
|
6013
|
+
intent_id: intent.id,
|
|
6014
|
+
attempt_id: attemptId,
|
|
6015
|
+
order_id: orderId,
|
|
6016
|
+
authorization_type: AUTHORIZATION_TYPE.OTP,
|
|
6017
|
+
display_text: "Approve on your mobile money app"
|
|
6018
|
+
};
|
|
6019
|
+
} else if (option?.method_kind === PURCHASE_INTENT_PAYMENT_METHOD.CARD) {
|
|
6020
|
+
confirmation = {
|
|
6021
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED,
|
|
6022
|
+
intent_id: intent.id,
|
|
6023
|
+
attempt_id: attemptId,
|
|
6024
|
+
order_id: orderId,
|
|
6025
|
+
provider: PURCHASE_INTENT_PAYMENT_PROVIDER.PAYSTACK,
|
|
6026
|
+
client_secret: `access_${paymentReference}`,
|
|
6027
|
+
public_key: MOCK_PURCHASE_INTENT.MOCK_PAYSTACK_PUBLIC_KEY
|
|
6028
|
+
};
|
|
6029
|
+
} else {
|
|
6030
|
+
confirmation = {
|
|
6031
|
+
status: PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED,
|
|
6032
|
+
intent_id: intent.id,
|
|
6033
|
+
attempt_id: attemptId,
|
|
6034
|
+
order_id: orderId
|
|
6035
|
+
};
|
|
6036
|
+
}
|
|
6037
|
+
if (needsProvider && !paymentId) {
|
|
6038
|
+
throw validation("Provider-backed purchase intent has no payment authority");
|
|
6039
|
+
}
|
|
6040
|
+
registry.purchaseIntents.put(intent.id, {
|
|
6041
|
+
...intent,
|
|
6042
|
+
status: PURCHASE_INTENT_STATUS.CONVERTED,
|
|
6043
|
+
converted_order_id: orderId,
|
|
6044
|
+
updated_at: clock.iso(),
|
|
6045
|
+
last_confirmation: confirmation
|
|
6046
|
+
});
|
|
6047
|
+
return confirmation;
|
|
6048
|
+
},
|
|
6049
|
+
submitAction(session, intentId, attemptId, request) {
|
|
6050
|
+
const intent = stored(session, intentId);
|
|
6051
|
+
const previous = intent.last_confirmation;
|
|
6052
|
+
if (!previous || previous.status !== PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED || previous.attempt_id !== attemptId) {
|
|
6053
|
+
throw validation("Purchase-intent attempt is not awaiting authorization");
|
|
6054
|
+
}
|
|
6055
|
+
if (!request.authorization) throw validation("authorization required");
|
|
6056
|
+
const order = registry.orders.get(previous.order_id);
|
|
6057
|
+
if (!order || !order.payment_id) {
|
|
6058
|
+
throw notFound(`Purchase-intent attempt ${attemptId} not found`);
|
|
6059
|
+
}
|
|
6060
|
+
return completeProviderOrder(intent, order, attemptId);
|
|
5393
6061
|
}
|
|
5394
6062
|
};
|
|
5395
6063
|
}
|
|
@@ -10683,7 +11351,7 @@ var ID_PREFIX = {
|
|
|
10683
11351
|
product: "prod_",
|
|
10684
11352
|
service: "svc_"
|
|
10685
11353
|
};
|
|
10686
|
-
var
|
|
11354
|
+
var DEFAULT_CURRENCY2 = "GHS";
|
|
10687
11355
|
function slugify(value) {
|
|
10688
11356
|
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
10689
11357
|
}
|
|
@@ -10718,7 +11386,7 @@ function makeSeedContext(registry) {
|
|
|
10718
11386
|
const business = {
|
|
10719
11387
|
business_type: "other",
|
|
10720
11388
|
email: `hello@${handle}.test`,
|
|
10721
|
-
default_currency:
|
|
11389
|
+
default_currency: DEFAULT_CURRENCY2,
|
|
10722
11390
|
default_offers_table_service: false,
|
|
10723
11391
|
default_accepts_online_orders: true,
|
|
10724
11392
|
status: "active",
|
|
@@ -10897,7 +11565,8 @@ function createDeps(options = {}) {
|
|
|
10897
11565
|
const inventory = createInventoryService({ registry });
|
|
10898
11566
|
const cart = createCartService({ registry, clock, ids, bus, inventory });
|
|
10899
11567
|
const orders = createOrderService({ registry, clock, bus });
|
|
10900
|
-
const
|
|
11568
|
+
const payments = createPaymentService({ registry, clock, bus });
|
|
11569
|
+
const purchaseIntents = createPurchaseIntentMockService({ registry, clock, ids, bus });
|
|
10901
11570
|
const subscriptions = createSubscriptionService({ registry, clock, bus });
|
|
10902
11571
|
const scheduling = createSchedulingService({ registry, clock, bus });
|
|
10903
11572
|
const fx = createFxService({ registry, clock, ids });
|
|
@@ -10918,7 +11587,8 @@ function createDeps(options = {}) {
|
|
|
10918
11587
|
business,
|
|
10919
11588
|
catalogue,
|
|
10920
11589
|
cart,
|
|
10921
|
-
|
|
11590
|
+
payments,
|
|
11591
|
+
purchaseIntents,
|
|
10922
11592
|
orders,
|
|
10923
11593
|
subscriptions,
|
|
10924
11594
|
scheduling,
|