@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.
Files changed (72) hide show
  1. package/dist/advanced.d.mts +3 -7
  2. package/dist/advanced.d.ts +3 -7
  3. package/dist/advanced.js +23 -23
  4. package/dist/advanced.mjs +4 -4
  5. package/dist/{client-DHBwvh7U.d.ts → catalogue-BlQ85Uma.d.mts} +492 -748
  6. package/dist/{client-BfpNjJ_a.d.mts → catalogue-C8TqOj9K.d.ts} +492 -748
  7. package/dist/{payment-H5LoIvXU.d.mts → checkout-BqK9XUz5.d.mts} +4338 -1495
  8. package/dist/{payment-H5LoIvXU.d.ts → checkout-BqK9XUz5.d.ts} +4338 -1495
  9. package/dist/{chunk-GOHSXBKW.mjs → chunk-33VCYWVL.mjs} +25 -1
  10. package/dist/{chunk-C2JSNJUC.mjs → chunk-6G3ANKQA.mjs} +1080 -369
  11. package/dist/{chunk-QOWPGS7Z.js → chunk-BWEIMKLF.js} +572 -17
  12. package/dist/{chunk-JSWJ4XDE.js → chunk-DQEXY542.js} +1630 -824
  13. package/dist/{chunk-CNN7Z2IP.js → chunk-EV2EVOYS.js} +27 -0
  14. package/dist/{chunk-VIL6IQCG.js → chunk-HYFA67A7.js} +1084 -373
  15. package/dist/{chunk-H7ACMHM3.mjs → chunk-L5SNEU2O.mjs} +553 -16
  16. package/dist/{chunk-JG5CQNCB.js → chunk-RBNBSQI7.mjs} +221 -19
  17. package/dist/{chunk-VNPEYLB2.mjs → chunk-SFUJMS5E.js} +265 -2
  18. package/dist/{chunk-M4URVKHE.mjs → chunk-U54CWUUT.mjs} +11 -2
  19. package/dist/{chunk-GERXZQSX.mjs → chunk-UFOWPN3D.mjs} +967 -582
  20. package/dist/{chunk-J6PNHDHL.mjs → chunk-V4457OKB.mjs} +1580 -785
  21. package/dist/{chunk-R6OLQ33I.js → chunk-WXREIBFW.js} +1041 -654
  22. package/dist/{chunk-NNG6IFFX.js → chunk-XAUSDMMZ.js} +13 -3
  23. package/dist/{client-DpqRobY9.d.mts → client-DhXeiUrf.d.ts} +2 -2
  24. package/dist/{client-Dqg2mc-7.d.ts → client-mXiUrV4X.d.mts} +2 -2
  25. package/dist/{index-C8uDqLwJ.d.ts → index-B0AdZvrM.d.mts} +9 -4
  26. package/dist/{index-e2y6AK70.d.mts → index-CK8Nk5uQ.d.ts} +9 -4
  27. package/dist/index-DPWI5XcU.d.ts +8 -0
  28. package/dist/index-DVfUh-ci.d.mts +8 -0
  29. package/dist/index.d.mts +34 -15
  30. package/dist/index.d.ts +34 -15
  31. package/dist/index.js +306 -133
  32. package/dist/index.mjs +7 -6
  33. package/dist/mock/cli.mjs +1494 -395
  34. package/dist/mock/library.js +1220 -361
  35. package/dist/mock/library.mjs +1220 -361
  36. package/dist/mock/msw.js +1220 -361
  37. package/dist/mock/msw.mjs +1220 -361
  38. package/dist/{price-C2RqscMY.d.ts → price-6hQIIac9.d.ts} +1 -1
  39. package/dist/{price-BvePgDXe.d.mts → price-BUDv1rI7.d.mts} +1 -1
  40. package/dist/react.d.mts +10 -5
  41. package/dist/react.d.ts +10 -5
  42. package/dist/react.js +279 -225
  43. package/dist/react.mjs +140 -86
  44. package/dist/{server-DoXIpSd7.d.ts → server-DJ0mSs9i.d.mts} +33 -57
  45. package/dist/{server-C7FyLdrz.d.mts → server-DSTX76Ki.d.ts} +33 -57
  46. package/dist/server.d.mts +3 -4
  47. package/dist/server.d.ts +3 -4
  48. package/dist/server.js +12 -11
  49. package/dist/server.mjs +6 -5
  50. package/dist/styles.css +2 -2
  51. package/dist/testing/msw.d.mts +2 -2
  52. package/dist/testing/msw.d.ts +2 -2
  53. package/dist/testing/msw.js +4 -4
  54. package/dist/testing/msw.mjs +3 -3
  55. package/dist/testing/suite.d.mts +5 -6
  56. package/dist/testing/suite.d.ts +5 -6
  57. package/dist/testing/suite.js +29 -28
  58. package/dist/testing/suite.mjs +10 -9
  59. package/dist/testing.d.mts +2217 -14
  60. package/dist/testing.d.ts +2217 -14
  61. package/dist/testing.js +173 -83
  62. package/dist/testing.mjs +28 -10
  63. package/dist/utils.d.mts +3 -4
  64. package/dist/utils.d.ts +3 -4
  65. package/dist/utils.js +35 -31
  66. package/dist/utils.mjs +2 -2
  67. package/package.json +9 -9
  68. package/registry/chat-widget.json +1 -1
  69. package/registry/order-history.json +1 -1
  70. package/registry/order-summary.json +1 -1
  71. package/dist/link-cuNVYc2s.d.mts +0 -297
  72. 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-GOHSXBKW.mjs';
3
- import { ErrorCode } from './chunk-VNPEYLB2.mjs';
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.12.25/node_modules/hono/dist/compose.js
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.12.25/node_modules/hono/dist/request/constants.js
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.12.25/node_modules/hono/dist/utils/body.js
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 instanceof HonoRequest ? request.raw.headers : request.headers;
68
+ const headers = isRawRequest(request) ? request.headers : request.raw.headers;
57
69
  const contentType = headers.get("Content-Type");
58
- if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
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
- const formData = await request.formData();
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.12.25/node_modules/hono/dist/utils/url.js
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 (/\?/.test(segment)) {
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.replace("?", "");
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 value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
276
+ return tryDecodeURIComponent(value);
254
277
  };
255
278
  var _getQueryParam = (url, key, multiple) => {
256
279
  let encoded;
257
- if (!multiple && key && !/[%+]/.test(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.12.25/node_modules/hono/dist/request.js
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 = Object.keys(bodyCache)[0];
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 && /\%/.test(param) ? tryDecodeURIComponent(param) : 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] = /\%/.test(value) ? tryDecodeURIComponent(value) : value;
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.12.25/node_modules/hono/dist/utils/html.js
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.12.25/node_modules/hono/dist/context.js
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
- const responseHeaders = __privateGet(this, _res) ? new Headers(__privateGet(this, _res).headers) : __privateGet(this, _preparedHeaders) ?? new Headers();
1014
- if (typeof arg === "object" && "headers" in arg) {
1015
- const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
1016
- for (const [key, value] of argHeaders) {
1017
- if (key.toLowerCase() === "set-cookie") {
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
- for (const [k, v] of Object.entries(headers)) {
1026
- if (typeof v === "string") {
1027
- responseHeaders.set(k, v);
1028
- } else {
1029
- responseHeaders.delete(k);
1030
- for (const v2 of v) {
1031
- responseHeaders.append(k, v2);
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, { status, headers: responseHeaders });
1069
+ return createResponseInstance(data, {
1070
+ status,
1071
+ headers: responseHeaders ?? headers
1072
+ });
1038
1073
  }, _a2);
1039
1074
 
1040
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router.js
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.12.25/node_modules/hono/dist/utils/constants.js
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.12.25/node_modules/hono/dist/hono-base.js
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} Env - env Object
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.12.25/node_modules/hono/dist/router/reg-exp-router/matcher.js
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.12.25/node_modules/hono/dist/router/reg-exp-router/node.js
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, pathErrorCheckOnly) {
1480
- if (tokens.length === 0) {
1481
- if (__privateGet(this, _index) !== void 0) {
1482
- throw PATH_ERROR;
1483
- }
1484
- if (pathErrorCheckOnly) {
1485
- return;
1486
- }
1487
- __privateSet(this, _index, index);
1488
- return;
1489
- }
1490
- const [token, ...restTokens] = tokens;
1491
- const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
1492
- let node;
1493
- if (pattern) {
1494
- const name = pattern[1];
1495
- let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
1496
- if (name && pattern[2]) {
1497
- if (regexpStr === ".*") {
1498
- throw PATH_ERROR;
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
- if (pathErrorCheckOnly) {
1513
- return;
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(node, _varIndex, context.varIndex++);
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
- if (pathErrorCheckOnly) {
1532
- return;
1555
+ } else {
1556
+ nextNode = __privateGet(node, _children)[token];
1557
+ if (!nextNode) {
1558
+ for (const k in __privateGet(node, _children)) {
1559
+ if (k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR) {
1560
+ throw PATH_ERROR;
1561
+ }
1562
+ }
1563
+ nextNode = __privateGet(node, _children)[token] = new _a4();
1533
1564
  }
1534
- node = __privateGet(this, _children)[token] = new _a4();
1535
1565
  }
1566
+ node = nextNode;
1567
+ }
1568
+ if (__privateGet(node, _index) !== void 0) {
1569
+ throw PATH_ERROR;
1536
1570
  }
1537
- node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly);
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
- return (typeof __privateGet(c, _varIndex) === "number" ? `(${k})@${__privateGet(c, _varIndex)}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
1544
- });
1545
- if (typeof __privateGet(this, _index) === "number") {
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.12.25/node_modules/hono/dist/router/reg-exp-router/trie.js
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, index, pathErrorCheckOnly) {
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
- path = path.replace(/\{[^}]+\}/g, (m) => {
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 = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
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, index, paramAssoc, __privateGet(this, _context), pathErrorCheckOnly);
1592
- return paramAssoc;
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.12.25/node_modules/hono/dist/router/reg-exp-router/router.js
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
- if (method === METHOD_NAME_ALL) {
1732
- Object.keys(middleware).forEach((m) => {
1733
- var _a11;
1734
- (_a11 = middleware[m])[path] || (_a11[path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || []);
1735
- });
1736
- } else {
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
- (_a11 = routes[m])[path2] || (_a11[path2] = [
1762
- ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
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(), buildMatcher_fn = function(method) {
1779
- const routes = [];
1780
- let hasOwnRoute = method === METHOD_NAME_ALL;
1781
- [__privateGet(this, _middleware), __privateGet(this, _routes)].forEach((r) => {
1782
- const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
1783
- if (ownRoute.length !== 0) {
1784
- hasOwnRoute || (hasOwnRoute = true);
1785
- routes.push(...ownRoute);
1786
- } else if (method !== METHOD_NAME_ALL) {
1787
- routes.push(
1788
- ...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]])
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
- if (!hasOwnRoute) {
1793
- return null;
1794
- } else {
1795
- return buildMatcherFromPreprocessedRoutes(routes);
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.12.25/node_modules/hono/dist/router/smart-router/router.js
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.12.25/node_modules/hono/dist/router/trie-router/node.js
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.12.25/node_modules/hono/dist/router/trie-router/router.js
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.12.25/node_modules/hono/dist/hono.js
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 recordId = `${session.id}:${key}`;
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("/payments/collection-options", (c) => {
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 === "GHS" ? [
2594
+ options: currency === DEFAULT_CURRENCY ? [
2527
2595
  { method: PAYMENT_METHOD.CARD, network: null },
2528
- { method: PAYMENT_METHOD.MOBILE_MONEY, network: "mtn" },
2529
- { method: PAYMENT_METHOD.MOBILE_MONEY, network: "telecel" },
2530
- { method: PAYMENT_METHOD.MOBILE_MONEY, network: "airteltigo" }
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("/checkout", async (c) => {
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(c, () => deps.checkout.process(c.var.session, body));
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("/payments/authorization", async (c) => {
2659
+ app.post(PAYMENT_ROUTE.AUTHORIZATION, async (c) => {
2539
2660
  const body = await c.req.json().catch(() => ({}));
2540
- return tryRoute(c, () => deps.checkout.authorize(body));
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
- var TYPE = window.__CIMPLIFY_MOCK_ELEMENT__;
2996
- var DEFAULT_BUSINESS = window.__CIMPLIFY_MOCK_BUSINESS__;
2997
- var MSG = {
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
- var qs = new URLSearchParams(location.search);
3011
- var AUTO = qs.get("auto") === "true";
3012
- var DEMO_OTP = qs.get("otp") || "123456";
3013
- var ORIGIN = qs.get("origin") || "*";
3014
- var NONCE = qs.get("nonce");
3015
- var state = {
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
- var content = document.getElementById("content");
3027
- var title = document.getElementById("title");
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 === "card") return { type: "card", provider: "paystack", last_four: "4242", label: "Visa \u2022\u2022\u2022\u2022 4242" };
3045
- if (type === "cash") return { type: "cash", label: "Cash on delivery" };
3046
- return { type: "mobile_money", provider: "mtn", phone_number: "+233244000000", label: "MTN Mobile Money" };
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
- var options = {
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
- var picked = "default";
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
- var picked = "mobile_money";
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
- var statusEl = document.getElementById("status");
3164
- var errEl = document.getElementById("err");
3165
- var resultEl = document.getElementById("result");
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
- var customer = {
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
- var paymentMethod = document.getElementById("pay-method").value;
3175
- var orderType = document.getElementById("order-type").value;
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: "processing", context: {} });
3350
+ send({ type: MSG.CHECKOUT_STATUS, status: CHECKOUT_STATUS.PROCESSING, context: {} });
3178
3351
 
3179
- var headers = { "content-type": "application/json" };
3352
+ const headers = { "content-type": "application/json" };
3180
3353
  if (state.token) headers["x-session-token"] = state.token;
3181
3354
 
3182
- fetch("/api/v1/checkout", {
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
- cart_id: state.cart.id,
3187
- customer: customer,
3188
- order_type: orderType,
3189
- payment_method: paymentMethod,
3190
- address_info: state.address || undefined
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(function (r) { return r.json().then(function (b) { return { status: r.status, body: b }; }); })
3380
+ .then(responseWithBody)
3194
3381
  .then(function (resp) {
3195
- if (resp.status >= 400) {
3196
- var msg = (resp.body && resp.body.error && resp.body.error.message) || "Checkout failed";
3197
- send({ type: MSG.CHECKOUT_COMPLETE, success: false, error: { code: (resp.body.error && resp.body.error.code) || "CHECKOUT_FAILED", message: msg, recoverable: true } });
3198
- statusEl.textContent = "Failed";
3199
- errEl.textContent = msg;
3200
- return;
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
- var b = resp.body;
3203
- send({ type: MSG.CHECKOUT_STATUS, status: "success", context: { order_id: b.order_id, order_number: b.order_number, provider: b.provider } });
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: b.order_id,
3209
- order_number: b.order_number,
3210
- status: b.requires_authorization ? "pending" : "confirmed",
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 " + b.order_number;
3458
+ statusEl.textContent = "Success \u2014 order " + outcome.order_id;
3216
3459
  resultEl.style.display = "block";
3217
- resultEl.textContent = JSON.stringify(b, null, 2);
3460
+ resultEl.textContent = JSON.stringify(outcome, null, 2);
3218
3461
  })
3219
3462
  .catch(function (e) {
3220
- send({ type: MSG.CHECKOUT_COMPLETE, success: false, error: { code: "NETWORK", message: String(e), recoverable: true } });
3221
- statusEl.textContent = "Network error";
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
- var s = document.getElementById("status");
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: "failed", context: {} });
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(body.contact ?? "", body.otp_code ?? "");
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
- const matching = registry.otps.list((o) => o.contact === contact);
3921
- const otp = matching[matching.length - 1];
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.customer_id,
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/checkout.ts
5248
- function createCheckoutService(opts) {
5249
- const { registry, clock, ids, bus} = opts;
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: "confirmed",
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: "succeeded",
5529
+ payment_status: LEGACY_CHECKOUT_PAYMENT_STATUS.SUCCEEDED,
5351
5530
  requires_authorization: false,
5352
- next_action: { type: "none" }
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 DEFAULT_CURRENCY = "GHS";
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: 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 checkout = createCheckoutService({ registry, clock, ids, bus});
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
- checkout,
11590
+ payments,
11591
+ purchaseIntents,
10881
11592
  orders,
10882
11593
  subscriptions,
10883
11594
  scheduling,