@cimplify/sdk 0.103.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-DHBwvh7U.d.ts → catalogue-BlQ85Uma.d.mts} +492 -748
- package/dist/{client-BfpNjJ_a.d.mts → catalogue-C8TqOj9K.d.ts} +492 -748
- package/dist/{payment-H5LoIvXU.d.mts → checkout-BqK9XUz5.d.mts} +4338 -1495
- package/dist/{payment-H5LoIvXU.d.ts → checkout-BqK9XUz5.d.ts} +4338 -1495
- package/dist/{chunk-GOHSXBKW.mjs → chunk-33VCYWVL.mjs} +25 -1
- package/dist/{chunk-C2JSNJUC.mjs → chunk-6G3ANKQA.mjs} +1080 -369
- package/dist/{chunk-QOWPGS7Z.js → chunk-BWEIMKLF.js} +572 -17
- package/dist/{chunk-JSWJ4XDE.js → chunk-DQEXY542.js} +1630 -824
- package/dist/{chunk-CNN7Z2IP.js → chunk-EV2EVOYS.js} +27 -0
- package/dist/{chunk-VIL6IQCG.js → chunk-HYFA67A7.js} +1084 -373
- package/dist/{chunk-H7ACMHM3.mjs → chunk-L5SNEU2O.mjs} +553 -16
- package/dist/{chunk-JG5CQNCB.js → chunk-RBNBSQI7.mjs} +221 -19
- package/dist/{chunk-VNPEYLB2.mjs → chunk-SFUJMS5E.js} +265 -2
- package/dist/{chunk-M4URVKHE.mjs → chunk-U54CWUUT.mjs} +11 -2
- package/dist/{chunk-GERXZQSX.mjs → chunk-UFOWPN3D.mjs} +967 -582
- package/dist/{chunk-J6PNHDHL.mjs → chunk-V4457OKB.mjs} +1580 -785
- package/dist/{chunk-R6OLQ33I.js → chunk-WXREIBFW.js} +1041 -654
- package/dist/{chunk-NNG6IFFX.js → chunk-XAUSDMMZ.js} +13 -3
- package/dist/{client-DpqRobY9.d.mts → client-DhXeiUrf.d.ts} +2 -2
- package/dist/{client-Dqg2mc-7.d.ts → client-mXiUrV4X.d.mts} +2 -2
- package/dist/{index-C8uDqLwJ.d.ts → index-B0AdZvrM.d.mts} +9 -4
- package/dist/{index-e2y6AK70.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 +34 -15
- package/dist/index.d.ts +34 -15
- package/dist/index.js +306 -133
- package/dist/index.mjs +7 -6
- package/dist/mock/cli.mjs +1494 -395
- package/dist/mock/library.js +1220 -361
- package/dist/mock/library.mjs +1220 -361
- package/dist/mock/msw.js +1220 -361
- package/dist/mock/msw.mjs +1220 -361
- package/dist/{price-C2RqscMY.d.ts → price-6hQIIac9.d.ts} +1 -1
- package/dist/{price-BvePgDXe.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 +279 -225
- package/dist/react.mjs +140 -86
- package/dist/{server-DoXIpSd7.d.ts → server-DJ0mSs9i.d.mts} +33 -57
- package/dist/{server-C7FyLdrz.d.mts → server-DSTX76Ki.d.ts} +33 -57
- package/dist/server.d.mts +3 -4
- package/dist/server.d.ts +3 -4
- package/dist/server.js +12 -11
- package/dist/server.mjs +6 -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 +2217 -14
- package/dist/testing.d.ts +2217 -14
- package/dist/testing.js +173 -83
- package/dist/testing.mjs +28 -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/chat-widget.json +1 -1
- package/registry/order-history.json +1 -1
- package/registry/order-summary.json +1 -1
- package/dist/link-cuNVYc2s.d.mts +0 -297
- package/dist/link-cuNVYc2s.d.ts +0 -297
|
@@ -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(
|
|
1518
|
-
|
|
1519
|
-
}
|
|
1520
|
-
if (!pathErrorCheckOnly && name !== "") {
|
|
1521
|
-
paramMap.push([name, __privateGet(node, _varIndex)]);
|
|
1522
|
-
}
|
|
1523
|
-
} else {
|
|
1524
|
-
node = __privateGet(this, _children)[token];
|
|
1525
|
-
if (!node) {
|
|
1526
|
-
if (Object.keys(__privateGet(this, _children)).some(
|
|
1527
|
-
(k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
|
|
1528
|
-
)) {
|
|
1529
|
-
throw PATH_ERROR;
|
|
1552
|
+
__privateGet(nextNode, _varIndex) ?? __privateSet(nextNode, _varIndex, context.varIndex++);
|
|
1553
|
+
paramMap.push([name, __privateGet(nextNode, _varIndex)]);
|
|
1530
1554
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
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;
|
|
1567
|
+
}
|
|
1568
|
+
if (__privateGet(node, _index) !== void 0) {
|
|
1569
|
+
throw PATH_ERROR;
|
|
1536
1570
|
}
|
|
1537
|
-
node
|
|
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
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
const handlerMap = [];
|
|
1812
|
+
for (const i in indexReplacementMap) {
|
|
1813
|
+
handlerMap[i] = handlerData[indexReplacementMap[i]];
|
|
1796
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));
|
|
@@ -2435,6 +2473,36 @@ function buildV1(deps) {
|
|
|
2435
2473
|
"/catalogue/quotes/:quote_id/refresh",
|
|
2436
2474
|
(c) => tryRoute(c, () => deps.catalogue.refreshQuote(c.req.param("quote_id")))
|
|
2437
2475
|
);
|
|
2476
|
+
app.get("/reviews/summary", (c) => {
|
|
2477
|
+
const productId = c.req.query("product_id");
|
|
2478
|
+
if (productId !== void 0 && (productId.length === 0 || productId.trim() !== productId)) {
|
|
2479
|
+
return fail(c, validation("product_id must be a non-empty canonical identifier"));
|
|
2480
|
+
}
|
|
2481
|
+
const response = {
|
|
2482
|
+
data: {
|
|
2483
|
+
ratings: {
|
|
2484
|
+
product_id: productId ?? null,
|
|
2485
|
+
review_count: 0,
|
|
2486
|
+
rating_sum: 0,
|
|
2487
|
+
average_rating: null,
|
|
2488
|
+
distribution: { one: 0, two: 0, three: 0, four: 0, five: 0 }
|
|
2489
|
+
},
|
|
2490
|
+
trust_chips: {
|
|
2491
|
+
on_time_delivery_percent: null,
|
|
2492
|
+
delivery_sample_size: 0,
|
|
2493
|
+
average_first_response_seconds: null,
|
|
2494
|
+
support_sample_size: 0
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
};
|
|
2498
|
+
return c.json(response);
|
|
2499
|
+
});
|
|
2500
|
+
app.get("/reviews", (c) => {
|
|
2501
|
+
const response = {
|
|
2502
|
+
data: { items: [], next_cursor: null }
|
|
2503
|
+
};
|
|
2504
|
+
return c.json(response);
|
|
2505
|
+
});
|
|
2438
2506
|
app.get("/cart", (c) => tryRoute(c, () => deps.cart.toUICart(deps.cart.get(c.var.session))));
|
|
2439
2507
|
app.delete("/cart", (c) => tryRoute(c, () => deps.cart.clear(c.var.session)));
|
|
2440
2508
|
app.get("/cart/items", (c) => tryRoute(c, () => deps.cart.getItems(c.var.session)));
|
|
@@ -2516,28 +2584,81 @@ function buildV1(deps) {
|
|
|
2516
2584
|
"/subscriptions/:subscription_id/skip",
|
|
2517
2585
|
(c) => tryRoute(c, () => deps.subscriptions.skipNext(c.req.param("subscription_id")))
|
|
2518
2586
|
);
|
|
2519
|
-
app.get(
|
|
2587
|
+
app.get(PAYMENT_ROUTE.COLLECTION_OPTIONS, async (c) => {
|
|
2520
2588
|
const currency = c.req.query("currency")?.trim().toUpperCase();
|
|
2521
2589
|
if (!currency || !/^[A-Z]{3}$/.test(currency)) {
|
|
2522
2590
|
return fail(c, validation("currency must be a canonical three-letter code"));
|
|
2523
2591
|
}
|
|
2524
2592
|
return tryRoute(c, () => ({
|
|
2525
2593
|
presentment_currency: currency,
|
|
2526
|
-
options: currency ===
|
|
2594
|
+
options: currency === DEFAULT_CURRENCY ? [
|
|
2527
2595
|
{ method: PAYMENT_METHOD.CARD, network: null },
|
|
2528
|
-
{
|
|
2529
|
-
|
|
2530
|
-
|
|
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
|
+
}
|
|
2531
2608
|
] : currency === "USD" ? [{ method: PAYMENT_METHOD.CARD, network: null }] : []
|
|
2532
2609
|
}));
|
|
2533
2610
|
});
|
|
2534
|
-
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) => {
|
|
2535
2648
|
const body = await c.req.json().catch(() => ({}));
|
|
2536
|
-
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
|
+
);
|
|
2537
2658
|
});
|
|
2538
|
-
app.post(
|
|
2659
|
+
app.post(PAYMENT_ROUTE.AUTHORIZATION, async (c) => {
|
|
2539
2660
|
const body = await c.req.json().catch(() => ({}));
|
|
2540
|
-
return tryRoute(c, () => deps.
|
|
2661
|
+
return tryRoute(c, () => deps.payments.authorize(body));
|
|
2541
2662
|
});
|
|
2542
2663
|
app.get("/auth/status", (c) => tryRoute(c, () => deps.auth.status(c.var.session.token)));
|
|
2543
2664
|
app.post("/auth/request-otp", async (c) => {
|
|
@@ -2843,6 +2964,7 @@ function createStateRegistry() {
|
|
|
2843
2964
|
collections: createMemoryStore(),
|
|
2844
2965
|
carts: createMemoryStore(),
|
|
2845
2966
|
orders: createMemoryStore(),
|
|
2967
|
+
purchaseIntents: createMemoryStore(),
|
|
2846
2968
|
subscriptions: createMemoryStore(),
|
|
2847
2969
|
bookings: createMemoryStore(),
|
|
2848
2970
|
services: createMemoryStore(),
|
|
@@ -2992,9 +3114,9 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
2992
3114
|
// injected into the HTML page served by the mock. Edit this file directly \u2014
|
|
2993
3115
|
// type-check via tsgo + the IframeToParentMessage shape from the SDK.
|
|
2994
3116
|
(function () {
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3117
|
+
const TYPE = window.__CIMPLIFY_MOCK_ELEMENT__;
|
|
3118
|
+
const DEFAULT_BUSINESS = window.__CIMPLIFY_MOCK_BUSINESS__;
|
|
3119
|
+
const MSG = {
|
|
2998
3120
|
INIT: "init", SET_TOKEN: "set_token", SET_CART: "set_cart", GET_DATA: "get_data",
|
|
2999
3121
|
REFRESH_TOKEN: "refresh_token", LOGOUT: "logout",
|
|
3000
3122
|
PROCESS_CHECKOUT: "process_checkout", ABORT_CHECKOUT: "abort_checkout",
|
|
@@ -3007,12 +3129,36 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3007
3129
|
CHECKOUT_STATUS: "checkout_status", CHECKOUT_COMPLETE: "checkout_complete",
|
|
3008
3130
|
ORDER_TYPE_CHANGED: "order_type_changed", REQUEST_SUBMIT: "request_submit"
|
|
3009
3131
|
};
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
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 = {
|
|
3016
3162
|
businessId: DEFAULT_BUSINESS,
|
|
3017
3163
|
token: null,
|
|
3018
3164
|
cart: null,
|
|
@@ -3023,15 +3169,33 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3023
3169
|
contact: null,
|
|
3024
3170
|
pendingOtp: null
|
|
3025
3171
|
};
|
|
3026
|
-
|
|
3027
|
-
|
|
3172
|
+
const content = document.getElementById("content");
|
|
3173
|
+
const title = document.getElementById("title");
|
|
3028
3174
|
|
|
3029
3175
|
function send(msg) {
|
|
3030
3176
|
if (NONCE) msg.nonce = NONCE;
|
|
3031
3177
|
parent.postMessage(msg, ORIGIN);
|
|
3032
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
|
+
}
|
|
3033
3184
|
function reportHeight() { send({ type: MSG.HEIGHT_CHANGE, height: document.documentElement.scrollHeight }); }
|
|
3034
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
|
+
}
|
|
3035
3199
|
|
|
3036
3200
|
function defaultAddress() {
|
|
3037
3201
|
return {
|
|
@@ -3041,9 +3205,20 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3041
3205
|
};
|
|
3042
3206
|
}
|
|
3043
3207
|
function defaultPayment(type) {
|
|
3044
|
-
if (type ===
|
|
3045
|
-
|
|
3046
|
-
|
|
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
|
+
};
|
|
3047
3222
|
}
|
|
3048
3223
|
|
|
3049
3224
|
function renderAuth() {
|
|
@@ -3068,12 +3243,12 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3068
3243
|
' <div class="option" data-key="lagos">5 Allen Ave, Ikeja, Lagos</div>' +
|
|
3069
3244
|
'</div>' +
|
|
3070
3245
|
'<button id="confirm">Use this address</button>';
|
|
3071
|
-
|
|
3246
|
+
const options = {
|
|
3072
3247
|
"default": defaultAddress(),
|
|
3073
3248
|
"east-legon": { street_address: "8 Ring Road", city: "Accra", region: "Greater Accra", country: "GH", latitude: 5.65, longitude: -0.16 },
|
|
3074
3249
|
"lagos": { street_address: "5 Allen Avenue", city: "Lagos", region: "Lagos", country: "NG", latitude: 6.5244, longitude: 3.3792 }
|
|
3075
3250
|
};
|
|
3076
|
-
|
|
3251
|
+
let picked = "default";
|
|
3077
3252
|
Array.prototype.forEach.call(document.querySelectorAll(".option"), function (el) {
|
|
3078
3253
|
el.onclick = function () {
|
|
3079
3254
|
picked = el.getAttribute("data-key");
|
|
@@ -3096,10 +3271,9 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3096
3271
|
'<div class="options" id="pay-options">' +
|
|
3097
3272
|
' <div class="option selected" data-method="mobile_money">\u{1F4F1} MTN Mobile Money</div>' +
|
|
3098
3273
|
' <div class="option" data-method="card">\u{1F4B3} Card (Paystack)</div>' +
|
|
3099
|
-
' <div class="option" data-method="cash">\u{1F4B5} Cash on delivery</div>' +
|
|
3100
3274
|
'</div>' +
|
|
3101
3275
|
'<button id="confirm">Use this method</button>';
|
|
3102
|
-
|
|
3276
|
+
let picked = TENDER.MOBILE_MONEY;
|
|
3103
3277
|
Array.prototype.forEach.call(document.querySelectorAll(".option"), function (el) {
|
|
3104
3278
|
el.onclick = function () {
|
|
3105
3279
|
picked = el.getAttribute("data-method");
|
|
@@ -3143,7 +3317,6 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3143
3317
|
'</div>' +
|
|
3144
3318
|
'<label>Payment method</label>' +
|
|
3145
3319
|
'<select id="pay-method">' +
|
|
3146
|
-
' <option value="cash">Cash</option>' +
|
|
3147
3320
|
' <option value="mobile_money">Mobile Money (MTN)</option>' +
|
|
3148
3321
|
' <option value="card">Card (Paystack)</option>' +
|
|
3149
3322
|
'</select>' +
|
|
@@ -3160,65 +3333,139 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3160
3333
|
}
|
|
3161
3334
|
|
|
3162
3335
|
function runCheckout() {
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3336
|
+
const statusEl = document.getElementById("status");
|
|
3337
|
+
const errEl = document.getElementById("err");
|
|
3338
|
+
const resultEl = document.getElementById("result");
|
|
3166
3339
|
if (errEl) errEl.textContent = "";
|
|
3167
3340
|
if (!state.cart) { errEl.textContent = "No cart provided"; return; }
|
|
3168
|
-
|
|
3341
|
+
const customer = {
|
|
3169
3342
|
name: document.getElementById("cust-name").value.trim() || "Customer",
|
|
3170
3343
|
email: document.getElementById("cust-email").value.trim() || "noemail@example.com",
|
|
3171
3344
|
phone: document.getElementById("cust-phone").value.trim() || "+233000000000",
|
|
3172
3345
|
save_details: false
|
|
3173
3346
|
};
|
|
3174
|
-
|
|
3175
|
-
|
|
3347
|
+
const paymentMethod = document.getElementById("pay-method").value;
|
|
3348
|
+
const orderType = document.getElementById("order-type").value;
|
|
3176
3349
|
statusEl.textContent = "Processing\u2026";
|
|
3177
|
-
send({ type: MSG.CHECKOUT_STATUS, status:
|
|
3350
|
+
send({ type: MSG.CHECKOUT_STATUS, status: CHECKOUT_STATUS.PROCESSING, context: {} });
|
|
3178
3351
|
|
|
3179
|
-
|
|
3352
|
+
const headers = { "content-type": "application/json" };
|
|
3180
3353
|
if (state.token) headers["x-session-token"] = state.token;
|
|
3181
3354
|
|
|
3182
|
-
|
|
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, {
|
|
3183
3367
|
method: "POST",
|
|
3184
3368
|
headers: headers,
|
|
3185
3369
|
body: JSON.stringify({
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
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
|
+
}
|
|
3191
3378
|
})
|
|
3192
3379
|
})
|
|
3193
|
-
.then(
|
|
3380
|
+
.then(responseWithBody)
|
|
3194
3381
|
.then(function (resp) {
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
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, " "));
|
|
3201
3441
|
}
|
|
3202
|
-
|
|
3203
|
-
|
|
3442
|
+
send({
|
|
3443
|
+
type: MSG.CHECKOUT_STATUS,
|
|
3444
|
+
status: CHECKOUT_STATUS.SUCCESS,
|
|
3445
|
+
context: { order_id: outcome.order_id }
|
|
3446
|
+
});
|
|
3204
3447
|
send({
|
|
3205
3448
|
type: MSG.CHECKOUT_COMPLETE,
|
|
3206
3449
|
success: true,
|
|
3207
3450
|
order: {
|
|
3208
|
-
id:
|
|
3209
|
-
order_number:
|
|
3210
|
-
status:
|
|
3451
|
+
id: outcome.order_id,
|
|
3452
|
+
order_number: outcome.order_number || outcome.order_id,
|
|
3453
|
+
status: ORDER_STATUS.CONFIRMED,
|
|
3211
3454
|
total: (state.cart && state.cart.total_price) || "0.00",
|
|
3212
3455
|
currency: (state.cart && state.cart.currency) || "GHS"
|
|
3213
3456
|
}
|
|
3214
3457
|
});
|
|
3215
|
-
statusEl.textContent = "Success \u2014 order " +
|
|
3458
|
+
statusEl.textContent = "Success \u2014 order " + outcome.order_id;
|
|
3216
3459
|
resultEl.style.display = "block";
|
|
3217
|
-
resultEl.textContent = JSON.stringify(
|
|
3460
|
+
resultEl.textContent = JSON.stringify(outcome, null, 2);
|
|
3218
3461
|
})
|
|
3219
3462
|
.catch(function (e) {
|
|
3220
|
-
send({
|
|
3221
|
-
|
|
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";
|
|
3222
3469
|
errEl.textContent = String(e);
|
|
3223
3470
|
});
|
|
3224
3471
|
}
|
|
@@ -3235,7 +3482,7 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3235
3482
|
break;
|
|
3236
3483
|
case MSG.SET_CART:
|
|
3237
3484
|
state.cart = msg.cart;
|
|
3238
|
-
|
|
3485
|
+
const s = document.getElementById("status");
|
|
3239
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");
|
|
3240
3487
|
reportHeight();
|
|
3241
3488
|
break;
|
|
@@ -3259,7 +3506,7 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
|
|
|
3259
3506
|
}
|
|
3260
3507
|
break;
|
|
3261
3508
|
case MSG.ABORT_CHECKOUT:
|
|
3262
|
-
send({ type: MSG.CHECKOUT_STATUS, status:
|
|
3509
|
+
send({ type: MSG.CHECKOUT_STATUS, status: CHECKOUT_STATUS.FAILED, context: {} });
|
|
3263
3510
|
break;
|
|
3264
3511
|
}
|
|
3265
3512
|
}
|
|
@@ -3330,9 +3577,10 @@ function buildLink(deps) {
|
|
|
3330
3577
|
app.post("/auth/request-otp", async (c) => {
|
|
3331
3578
|
const body = await c.req.json().catch(() => ({}));
|
|
3332
3579
|
return tryRoute(c, () => {
|
|
3333
|
-
deps.auth.requestOtp(body.contact ?? "");
|
|
3580
|
+
const challenge = deps.auth.requestOtp(body.contact ?? "");
|
|
3334
3581
|
return {
|
|
3335
3582
|
success: true,
|
|
3583
|
+
challenge_id: challenge.otp_id,
|
|
3336
3584
|
message: `OTP sent to ${body.contact ?? "contact"}`,
|
|
3337
3585
|
expires_in: 300,
|
|
3338
3586
|
is_new_account: false
|
|
@@ -3342,7 +3590,11 @@ function buildLink(deps) {
|
|
|
3342
3590
|
app.post("/auth/verify-otp", async (c) => {
|
|
3343
3591
|
const body = await c.req.json().catch(() => ({}));
|
|
3344
3592
|
return tryRoute(c, () => {
|
|
3345
|
-
const session = deps.auth.verifyOtp(
|
|
3593
|
+
const session = deps.auth.verifyOtp(
|
|
3594
|
+
body.contact ?? "",
|
|
3595
|
+
body.otp_code ?? "",
|
|
3596
|
+
body.challenge_id
|
|
3597
|
+
);
|
|
3346
3598
|
c.header("x-session-token", session.token);
|
|
3347
3599
|
const customer = deps.link.ensureCustomer(session.customer_id ?? session.id, {
|
|
3348
3600
|
email: body.contact?.includes("@") ? body.contact : void 0,
|
|
@@ -3436,10 +3688,7 @@ function buildLink(deps) {
|
|
|
3436
3688
|
};
|
|
3437
3689
|
});
|
|
3438
3690
|
});
|
|
3439
|
-
app.get(
|
|
3440
|
-
"/preferences",
|
|
3441
|
-
(c) => tryRoute(c, () => deps.link.getPreferences(customerId(c)))
|
|
3442
|
-
);
|
|
3691
|
+
app.get("/preferences", (c) => tryRoute(c, () => deps.link.getPreferences(customerId(c))));
|
|
3443
3692
|
app.post("/preferences", async (c) => {
|
|
3444
3693
|
const body = await c.req.json().catch(() => ({}));
|
|
3445
3694
|
return tryRoute(c, () => {
|
|
@@ -3871,6 +4120,7 @@ function createAuthService(opts) {
|
|
|
3871
4120
|
token: id,
|
|
3872
4121
|
business_id: options.defaultBusinessId,
|
|
3873
4122
|
is_authenticated: authenticated,
|
|
4123
|
+
account_id: authenticated ? ids.raw("account") : void 0,
|
|
3874
4124
|
customer_id: authenticated ? ids.customer() : void 0,
|
|
3875
4125
|
customer_name: profile?.name,
|
|
3876
4126
|
customer_email: profile?.email,
|
|
@@ -3916,9 +4166,16 @@ function createAuthService(opts) {
|
|
|
3916
4166
|
code_hint: options.mode === "permissive" ? code : void 0
|
|
3917
4167
|
};
|
|
3918
4168
|
},
|
|
3919
|
-
verifyOtp(contact, code) {
|
|
3920
|
-
|
|
3921
|
-
|
|
4169
|
+
verifyOtp(contact, code, challengeId) {
|
|
4170
|
+
let otp = challengeId ? registry.otps.get(challengeId) : void 0;
|
|
4171
|
+
if (!challengeId) {
|
|
4172
|
+
const matching = registry.otps.list((o) => o.contact === contact);
|
|
4173
|
+
otp = matching[matching.length - 1];
|
|
4174
|
+
}
|
|
4175
|
+
if (challengeId) {
|
|
4176
|
+
if (!otp) throw new Error("No OTP challenge found");
|
|
4177
|
+
if (otp.contact !== contact) throw new Error("OTP challenge does not match contact");
|
|
4178
|
+
}
|
|
3922
4179
|
if (options.mode === "strict") {
|
|
3923
4180
|
if (!otp) throw new Error("No OTP requested");
|
|
3924
4181
|
if (otp.code !== code && code !== options.defaultOtp) throw new Error("Invalid OTP");
|
|
@@ -3946,7 +4203,7 @@ function createAuthService(opts) {
|
|
|
3946
4203
|
if (!s) return { is_authenticated: false, user_type: "guest" };
|
|
3947
4204
|
return {
|
|
3948
4205
|
is_authenticated: s.is_authenticated,
|
|
3949
|
-
account_id: s.
|
|
4206
|
+
account_id: s.account_id,
|
|
3950
4207
|
user_type: s.is_authenticated ? "customer" : "guest",
|
|
3951
4208
|
session_expires_at: s.expires_at ? Math.floor(new Date(s.expires_at).getTime() / 1e3) : void 0,
|
|
3952
4209
|
session: s
|
|
@@ -5244,88 +5501,10 @@ function createCartService(opts) {
|
|
|
5244
5501
|
};
|
|
5245
5502
|
}
|
|
5246
5503
|
|
|
5247
|
-
// src/mock/domain/
|
|
5248
|
-
function
|
|
5249
|
-
const { registry, clock,
|
|
5504
|
+
// src/mock/domain/payment.ts
|
|
5505
|
+
function createPaymentService(options) {
|
|
5506
|
+
const { registry, clock, bus } = options;
|
|
5250
5507
|
return {
|
|
5251
|
-
process(session, body) {
|
|
5252
|
-
if (!body.cart_id) throw validation("cart_id required");
|
|
5253
|
-
const c = registry.carts.get(body.cart_id);
|
|
5254
|
-
if (!c) throw notFound(`Cart ${body.cart_id} not found`);
|
|
5255
|
-
if (c.items.length === 0) throw validation("Cart is empty", { code: "CART_EMPTY" });
|
|
5256
|
-
const orderId = ids.order();
|
|
5257
|
-
const orderNumber = ids.orderNumber();
|
|
5258
|
-
const paymentId = ids.payment();
|
|
5259
|
-
const reference = ids.payment();
|
|
5260
|
-
const requiresAuth = body.payment_method === "mobile_money";
|
|
5261
|
-
const isCard = body.payment_method === "card" || body.payment_method === "stripe";
|
|
5262
|
-
const cardProvider = body.payment_method === "stripe" || body.pay_currency?.toUpperCase() === "USD" ? "stripe" : "paystack";
|
|
5263
|
-
const order = {
|
|
5264
|
-
id: orderId,
|
|
5265
|
-
business_id: c.business_id,
|
|
5266
|
-
user_friendly_id: orderNumber,
|
|
5267
|
-
channel: c.channel,
|
|
5268
|
-
status: requiresAuth ? "pending" : "confirmed",
|
|
5269
|
-
payment_state: requiresAuth ? "not_paid" : "paid",
|
|
5270
|
-
order_type: body.order_type,
|
|
5271
|
-
customer_id: session.customer_id,
|
|
5272
|
-
customer_name: body.customer.name,
|
|
5273
|
-
customer_email: body.customer.email,
|
|
5274
|
-
customer_phone: body.customer.phone,
|
|
5275
|
-
delivery_address: body.address_info?.street_address,
|
|
5276
|
-
delivery_fee: c.delivery_fee,
|
|
5277
|
-
subtotal: c.subtotal,
|
|
5278
|
-
tax_amount: c.tax_amount,
|
|
5279
|
-
service_charge: c.service_charge,
|
|
5280
|
-
total_discounts: c.total_discounts,
|
|
5281
|
-
total_price: c.total_price,
|
|
5282
|
-
currency: c.currency,
|
|
5283
|
-
items: c.items,
|
|
5284
|
-
applied_discount_ids: c.applied_discount_ids,
|
|
5285
|
-
applied_discount_codes: c.applied_discount_codes,
|
|
5286
|
-
payment_id: paymentId,
|
|
5287
|
-
payment_reference: reference,
|
|
5288
|
-
metadata: body.metadata,
|
|
5289
|
-
created_at: clock.iso(),
|
|
5290
|
-
updated_at: clock.iso()
|
|
5291
|
-
};
|
|
5292
|
-
registry.orders.put(orderId, order);
|
|
5293
|
-
registry.carts.put(c.id, { ...c, status: "converted", updated_at: clock.iso() });
|
|
5294
|
-
bus.emit("order.created", { order_id: orderId, order_number: orderNumber }, c.business_id);
|
|
5295
|
-
if (!requiresAuth) {
|
|
5296
|
-
bus.emit("order.payment.captured", { order_id: orderId, reference }, c.business_id);
|
|
5297
|
-
bus.emit("order.confirmed", { order_id: orderId }, c.business_id);
|
|
5298
|
-
}
|
|
5299
|
-
const billToken = `bt_${reference.slice(-12)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
5300
|
-
const result = {
|
|
5301
|
-
order_id: orderId,
|
|
5302
|
-
order_number: orderNumber,
|
|
5303
|
-
payment_id: paymentId,
|
|
5304
|
-
payment_status: requiresAuth || isCard ? "pending" : "succeeded",
|
|
5305
|
-
payment_reference: reference,
|
|
5306
|
-
requires_authorization: requiresAuth,
|
|
5307
|
-
authorization_type: requiresAuth ? "otp" : void 0,
|
|
5308
|
-
next_action: requiresAuth ? {
|
|
5309
|
-
type: "authorization",
|
|
5310
|
-
authorization_type: "otp",
|
|
5311
|
-
display_text: "Approve on your mobile money app"
|
|
5312
|
-
} : { type: "none" },
|
|
5313
|
-
provider: isCard ? cardProvider : body.payment_method,
|
|
5314
|
-
bill_token: billToken
|
|
5315
|
-
};
|
|
5316
|
-
if (isCard) {
|
|
5317
|
-
const proc = globalThis.process;
|
|
5318
|
-
result.client_secret = cardProvider === "stripe" ? `pi_${orderId.slice(-12)}_secret_${Math.random().toString(36).slice(2, 18)}` : `access_${reference}`;
|
|
5319
|
-
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";
|
|
5320
|
-
result.next_action = {
|
|
5321
|
-
type: "card_popup",
|
|
5322
|
-
provider: cardProvider,
|
|
5323
|
-
client_secret: result.client_secret,
|
|
5324
|
-
public_key: result.public_key
|
|
5325
|
-
};
|
|
5326
|
-
}
|
|
5327
|
-
return result;
|
|
5328
|
-
},
|
|
5329
5508
|
authorize(body) {
|
|
5330
5509
|
if (!body.payment_id?.trim()) throw validation("payment_id required");
|
|
5331
5510
|
if (!body.authorization) throw validation("authorization required");
|
|
@@ -5336,7 +5515,7 @@ function createCheckoutService(opts) {
|
|
|
5336
5515
|
const updated = {
|
|
5337
5516
|
...order,
|
|
5338
5517
|
payment_state: "paid",
|
|
5339
|
-
status:
|
|
5518
|
+
status: CHECKOUT_ORDER_RESULT_STATUS.CONFIRMED,
|
|
5340
5519
|
updated_at: clock.iso()
|
|
5341
5520
|
};
|
|
5342
5521
|
registry.orders.put(order.id, updated);
|
|
@@ -5347,14 +5526,542 @@ function createCheckoutService(opts) {
|
|
|
5347
5526
|
order_number: order.user_friendly_id,
|
|
5348
5527
|
payment_id: body.payment_id,
|
|
5349
5528
|
payment_reference: order.payment_reference,
|
|
5350
|
-
payment_status:
|
|
5529
|
+
payment_status: LEGACY_CHECKOUT_PAYMENT_STATUS.SUCCEEDED,
|
|
5351
5530
|
requires_authorization: false,
|
|
5352
|
-
next_action: { type:
|
|
5531
|
+
next_action: { type: CHECKOUT_NEXT_ACTION.NONE }
|
|
5353
5532
|
};
|
|
5354
5533
|
}
|
|
5355
5534
|
};
|
|
5356
5535
|
}
|
|
5357
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()
|
|
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);
|
|
6061
|
+
}
|
|
6062
|
+
};
|
|
6063
|
+
}
|
|
6064
|
+
|
|
5358
6065
|
// src/mock/domain/orders.ts
|
|
5359
6066
|
function createOrderService(opts) {
|
|
5360
6067
|
const { registry, clock, bus } = opts;
|
|
@@ -5733,6 +6440,7 @@ function createDeliveryService() {
|
|
|
5733
6440
|
rate_id: "dlvrt_mock_standard",
|
|
5734
6441
|
name: "Standard",
|
|
5735
6442
|
fee: standardFree ? money(0) : money(15),
|
|
6443
|
+
fee_status: "priced",
|
|
5736
6444
|
currency: "GHS",
|
|
5737
6445
|
free_delivery_applied: standardFree,
|
|
5738
6446
|
free_over_amount: money(200),
|
|
@@ -5746,6 +6454,7 @@ function createDeliveryService() {
|
|
|
5746
6454
|
name: "Express",
|
|
5747
6455
|
description: "Delivered within the hour",
|
|
5748
6456
|
fee: money(25),
|
|
6457
|
+
fee_status: "priced",
|
|
5749
6458
|
currency: "GHS",
|
|
5750
6459
|
free_delivery_applied: false,
|
|
5751
6460
|
eta_min_minutes: 30,
|
|
@@ -10642,7 +11351,7 @@ var ID_PREFIX = {
|
|
|
10642
11351
|
product: "prod_",
|
|
10643
11352
|
service: "svc_"
|
|
10644
11353
|
};
|
|
10645
|
-
var
|
|
11354
|
+
var DEFAULT_CURRENCY2 = "GHS";
|
|
10646
11355
|
function slugify(value) {
|
|
10647
11356
|
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
10648
11357
|
}
|
|
@@ -10677,7 +11386,7 @@ function makeSeedContext(registry) {
|
|
|
10677
11386
|
const business = {
|
|
10678
11387
|
business_type: "other",
|
|
10679
11388
|
email: `hello@${handle}.test`,
|
|
10680
|
-
default_currency:
|
|
11389
|
+
default_currency: DEFAULT_CURRENCY2,
|
|
10681
11390
|
default_offers_table_service: false,
|
|
10682
11391
|
default_accepts_online_orders: true,
|
|
10683
11392
|
status: "active",
|
|
@@ -10856,7 +11565,8 @@ function createDeps(options = {}) {
|
|
|
10856
11565
|
const inventory = createInventoryService({ registry });
|
|
10857
11566
|
const cart = createCartService({ registry, clock, ids, bus, inventory });
|
|
10858
11567
|
const orders = createOrderService({ registry, clock, bus });
|
|
10859
|
-
const
|
|
11568
|
+
const payments = createPaymentService({ registry, clock, bus });
|
|
11569
|
+
const purchaseIntents = createPurchaseIntentMockService({ registry, clock, ids, bus });
|
|
10860
11570
|
const subscriptions = createSubscriptionService({ registry, clock, bus });
|
|
10861
11571
|
const scheduling = createSchedulingService({ registry, clock, bus });
|
|
10862
11572
|
const fx = createFxService({ registry, clock, ids });
|
|
@@ -10877,7 +11587,8 @@ function createDeps(options = {}) {
|
|
|
10877
11587
|
business,
|
|
10878
11588
|
catalogue,
|
|
10879
11589
|
cart,
|
|
10880
|
-
|
|
11590
|
+
payments,
|
|
11591
|
+
purchaseIntents,
|
|
10881
11592
|
orders,
|
|
10882
11593
|
subscriptions,
|
|
10883
11594
|
scheduling,
|