@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,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkXREIZ56K_js = require('./chunk-XREIZ56K.js');
4
- var chunkCNN7Z2IP_js = require('./chunk-CNN7Z2IP.js');
5
- var chunkJG5CQNCB_js = require('./chunk-JG5CQNCB.js');
4
+ var chunkEV2EVOYS_js = require('./chunk-EV2EVOYS.js');
5
+ var chunkSFUJMS5E_js = require('./chunk-SFUJMS5E.js');
6
6
  var chunkOWW5GUSB_js = require('./chunk-OWW5GUSB.js');
7
7
 
8
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/compose.js
8
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/compose.js
9
9
  var compose = (middleware, onError, onNotFound) => {
10
10
  return (context, next) => {
11
11
  let index = -1;
@@ -49,21 +49,46 @@ var compose = (middleware, onError, onNotFound) => {
49
49
  };
50
50
  };
51
51
 
52
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/request/constants.js
52
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/request/constants.js
53
53
  var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
54
54
 
55
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/body.js
55
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/buffer.js
56
+ var bufferToFormData = (arrayBuffer, contentType) => {
57
+ const response = new Response(arrayBuffer, {
58
+ headers: {
59
+ // Normalize the media type (case-insensitive) while keeping parameters like the boundary
60
+ "Content-Type": contentType.replace(/^[^;]+/, (mediaType) => mediaType.toLowerCase())
61
+ }
62
+ });
63
+ return response.formData();
64
+ };
65
+
66
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/body.js
67
+ var isRawRequest = (request) => "headers" in request;
56
68
  var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
57
69
  const { all = false, dot = false } = options;
58
- const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
70
+ const headers = isRawRequest(request) ? request.headers : request.raw.headers;
59
71
  const contentType = headers.get("Content-Type");
60
- if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
72
+ const mediaType = contentType?.split(";")[0].trim().toLowerCase();
73
+ if (mediaType === "multipart/form-data" || mediaType === "application/x-www-form-urlencoded") {
61
74
  return parseFormData(request, { all, dot });
62
75
  }
63
76
  return {};
64
77
  };
65
78
  async function parseFormData(request, options) {
66
- const formData = await request.formData();
79
+ if (!isRawRequest(request) && request.bodyCache.formData) {
80
+ return convertFormDataToBodyData(
81
+ await request.bodyCache.formData,
82
+ options
83
+ );
84
+ }
85
+ const headers = isRawRequest(request) ? request.headers : request.raw.headers;
86
+ const arrayBuffer = await request.arrayBuffer();
87
+ const formDataPromise = bufferToFormData(arrayBuffer, headers.get("Content-Type") || "");
88
+ if (!isRawRequest(request)) {
89
+ request.bodyCache.formData = formDataPromise;
90
+ }
91
+ const formData = await formDataPromise;
67
92
  if (formData) {
68
93
  return convertFormDataToBodyData(formData, options);
69
94
  }
@@ -123,7 +148,7 @@ var handleParsingNestedValues = (form, key, value) => {
123
148
  });
124
149
  };
125
150
 
126
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/url.js
151
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/url.js
127
152
  var splitPath = (path) => {
128
153
  const paths = path.split("/");
129
154
  if (paths[0] === "") {
@@ -229,13 +254,13 @@ var checkOptionalParameter = (path) => {
229
254
  if (segment !== "" && !/\:/.test(segment)) {
230
255
  basePath += "/" + segment;
231
256
  } else if (/\:/.test(segment)) {
232
- if (/\?/.test(segment)) {
257
+ if (segment.charCodeAt(segment.length - 1) === 63) {
233
258
  if (results.length === 0 && basePath === "") {
234
259
  results.push("/");
235
260
  } else {
236
261
  results.push(basePath);
237
262
  }
238
- const optionalSegment = segment.replace("?", "");
263
+ const optionalSegment = segment.slice(0, -1);
239
264
  basePath += "/" + optionalSegment;
240
265
  results.push(basePath);
241
266
  } else {
@@ -245,18 +270,16 @@ var checkOptionalParameter = (path) => {
245
270
  });
246
271
  return results.filter((v, i, a) => a.indexOf(v) === i);
247
272
  };
273
+ var tryDecodeURIComponent = (str) => str.indexOf("%") !== -1 ? tryDecode(str, decodeURIComponent_) : str;
248
274
  var _decodeURI = (value) => {
249
- if (!/[%+]/.test(value)) {
250
- return value;
251
- }
252
275
  if (value.indexOf("+") !== -1) {
253
276
  value = value.replace(/\+/g, " ");
254
277
  }
255
- return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
278
+ return tryDecodeURIComponent(value);
256
279
  };
257
280
  var _getQueryParam = (url, key, multiple) => {
258
281
  let encoded;
259
- if (!multiple && key && !/[%+]/.test(key)) {
282
+ if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
260
283
  let keyIndex2 = url.indexOf("?", 8);
261
284
  if (keyIndex2 === -1) {
262
285
  return void 0;
@@ -280,7 +303,7 @@ var _getQueryParam = (url, key, multiple) => {
280
303
  return void 0;
281
304
  }
282
305
  }
283
- const results = {};
306
+ const results = /* @__PURE__ */ Object.create(null);
284
307
  encoded ?? (encoded = /[%+]/.test(url));
285
308
  let keyIndex = url.indexOf("?", 8);
286
309
  while (keyIndex !== -1) {
@@ -326,8 +349,7 @@ var getQueryParams = (url, key) => {
326
349
  };
327
350
  var decodeURIComponent_ = decodeURIComponent;
328
351
 
329
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/request.js
330
- var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
352
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/request.js
331
353
  var _validatedData, _matchResult, _HonoRequest_instances, getDecodedParam_fn, getAllDecodedParams_fn, getParamValue_fn, _cachedBody, _a;
332
354
  var HonoRequest = (_a = class {
333
355
  constructor(request, path = "/", matchResult = [[]]) {
@@ -371,8 +393,7 @@ var HonoRequest = (_a = class {
371
393
  if (cachedBody) {
372
394
  return cachedBody;
373
395
  }
374
- const anyCachedKey = Object.keys(bodyCache)[0];
375
- if (anyCachedKey) {
396
+ for (const anyCachedKey in bodyCache) {
376
397
  return bodyCache[anyCachedKey].then((body) => {
377
398
  if (anyCachedKey === "json") {
378
399
  body = JSON.stringify(body);
@@ -385,7 +406,6 @@ var HonoRequest = (_a = class {
385
406
  this.raw = request;
386
407
  this.path = path;
387
408
  chunkOWW5GUSB_js.__privateSet(this, _matchResult, matchResult);
388
- chunkOWW5GUSB_js.__privateSet(this, _validatedData, {});
389
409
  }
390
410
  param(key) {
391
411
  return key ? chunkOWW5GUSB_js.__privateMethod(this, _HonoRequest_instances, getDecodedParam_fn).call(this, key) : chunkOWW5GUSB_js.__privateMethod(this, _HonoRequest_instances, getAllDecodedParams_fn).call(this);
@@ -400,7 +420,7 @@ var HonoRequest = (_a = class {
400
420
  if (name) {
401
421
  return this.raw.headers.get(name) ?? void 0;
402
422
  }
403
- const headerData = {};
423
+ const headerData = /* @__PURE__ */ Object.create(null);
404
424
  this.raw.headers.forEach((value, key) => {
405
425
  headerData[key] = value;
406
426
  });
@@ -502,10 +522,10 @@ var HonoRequest = (_a = class {
502
522
  * @param data - The validated data to add.
503
523
  */
504
524
  addValidatedData(target, data) {
505
- chunkOWW5GUSB_js.__privateGet(this, _validatedData)[target] = data;
525
+ (chunkOWW5GUSB_js.__privateGet(this, _validatedData) ?? chunkOWW5GUSB_js.__privateSet(this, _validatedData, {}))[target] = data;
506
526
  }
507
527
  valid(target) {
508
- return chunkOWW5GUSB_js.__privateGet(this, _validatedData)[target];
528
+ return chunkOWW5GUSB_js.__privateGet(this, _validatedData)?.[target];
509
529
  }
510
530
  /**
511
531
  * `.url()` can get the request url strings.
@@ -593,14 +613,14 @@ var HonoRequest = (_a = class {
593
613
  }, _validatedData = new WeakMap(), _matchResult = new WeakMap(), _HonoRequest_instances = new WeakSet(), getDecodedParam_fn = function(key) {
594
614
  const paramKey = chunkOWW5GUSB_js.__privateGet(this, _matchResult)[0][this.routeIndex][1][key];
595
615
  const param = chunkOWW5GUSB_js.__privateMethod(this, _HonoRequest_instances, getParamValue_fn).call(this, paramKey);
596
- return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param;
616
+ return param && tryDecodeURIComponent(param);
597
617
  }, getAllDecodedParams_fn = function() {
598
618
  const decoded = {};
599
619
  const keys = Object.keys(chunkOWW5GUSB_js.__privateGet(this, _matchResult)[0][this.routeIndex][1]);
600
620
  for (const key of keys) {
601
621
  const value = chunkOWW5GUSB_js.__privateMethod(this, _HonoRequest_instances, getParamValue_fn).call(this, chunkOWW5GUSB_js.__privateGet(this, _matchResult)[0][this.routeIndex][1][key]);
602
622
  if (value !== void 0) {
603
- decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value;
623
+ decoded[key] = tryDecodeURIComponent(value);
604
624
  }
605
625
  }
606
626
  return decoded;
@@ -608,7 +628,7 @@ var HonoRequest = (_a = class {
608
628
  return chunkOWW5GUSB_js.__privateGet(this, _matchResult)[1] ? chunkOWW5GUSB_js.__privateGet(this, _matchResult)[1][paramKey] : paramKey;
609
629
  }, _cachedBody = new WeakMap(), _a);
610
630
 
611
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/html.js
631
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/html.js
612
632
  var HtmlEscapedCallbackPhase = {
613
633
  Stringify: 1};
614
634
  var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
@@ -639,7 +659,7 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
639
659
  }
640
660
  };
641
661
 
642
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/context.js
662
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/context.js
643
663
  var TEXT_PLAIN = "text/plain; charset=UTF-8";
644
664
  var setDefaultContentType = (contentType, headers) => {
645
665
  return {
@@ -1012,11 +1032,11 @@ var Context = (_a2 = class {
1012
1032
  return Object.fromEntries(chunkOWW5GUSB_js.__privateGet(this, _var));
1013
1033
  }
1014
1034
  }, _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) {
1015
- const responseHeaders = chunkOWW5GUSB_js.__privateGet(this, _res) ? new Headers(chunkOWW5GUSB_js.__privateGet(this, _res).headers) : chunkOWW5GUSB_js.__privateGet(this, _preparedHeaders) ?? new Headers();
1016
- if (typeof arg === "object" && "headers" in arg) {
1017
- const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
1018
- for (const [key, value] of argHeaders) {
1019
- if (key.toLowerCase() === "set-cookie") {
1035
+ let responseHeaders = chunkOWW5GUSB_js.__privateGet(this, _res) ? new Headers(chunkOWW5GUSB_js.__privateGet(this, _res).headers) : chunkOWW5GUSB_js.__privateGet(this, _preparedHeaders);
1036
+ if (typeof arg === "object" && arg.headers) {
1037
+ responseHeaders ?? (responseHeaders = new Headers());
1038
+ for (const [key, value] of new Headers(arg.headers)) {
1039
+ if (key === "set-cookie") {
1020
1040
  responseHeaders.append(key, value);
1021
1041
  } else {
1022
1042
  responseHeaders.set(key, value);
@@ -1024,33 +1044,48 @@ var Context = (_a2 = class {
1024
1044
  }
1025
1045
  }
1026
1046
  if (headers) {
1027
- for (const [k, v] of Object.entries(headers)) {
1028
- if (typeof v === "string") {
1029
- responseHeaders.set(k, v);
1030
- } else {
1031
- responseHeaders.delete(k);
1032
- for (const v2 of v) {
1033
- responseHeaders.append(k, v2);
1047
+ if (!responseHeaders) {
1048
+ let count = 0;
1049
+ for (const k in headers) {
1050
+ if (++count > 1 || typeof headers[k] !== "string") {
1051
+ responseHeaders = new Headers();
1052
+ break;
1053
+ }
1054
+ }
1055
+ }
1056
+ if (responseHeaders) {
1057
+ for (const k in headers) {
1058
+ const v = headers[k];
1059
+ if (typeof v === "string") {
1060
+ responseHeaders.set(k, v);
1061
+ } else {
1062
+ responseHeaders.delete(k);
1063
+ for (const v2 of v) {
1064
+ responseHeaders.append(k, v2);
1065
+ }
1034
1066
  }
1035
1067
  }
1036
1068
  }
1037
1069
  }
1038
1070
  const status = typeof arg === "number" ? arg : arg?.status ?? chunkOWW5GUSB_js.__privateGet(this, _status);
1039
- return createResponseInstance(data, { status, headers: responseHeaders });
1071
+ return createResponseInstance(data, {
1072
+ status,
1073
+ headers: responseHeaders ?? headers
1074
+ });
1040
1075
  }, _a2);
1041
1076
 
1042
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router.js
1077
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router.js
1043
1078
  var METHOD_NAME_ALL = "ALL";
1044
1079
  var METHOD_NAME_ALL_LOWERCASE = "all";
1045
- var METHODS = ["get", "post", "put", "delete", "options", "patch"];
1080
+ var METHODS = ["get", "post", "put", "delete", "options", "patch", "query"];
1046
1081
  var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
1047
1082
  var UnsupportedPathError = class extends Error {
1048
1083
  };
1049
1084
 
1050
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/constants.js
1085
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/utils/constants.js
1051
1086
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
1052
1087
 
1053
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/hono-base.js
1088
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/hono-base.js
1054
1089
  var notFoundHandler = (c) => {
1055
1090
  return c.text("404 Not Found", 404);
1056
1091
  };
@@ -1072,6 +1107,7 @@ var Hono = (_a3 = class {
1072
1107
  chunkOWW5GUSB_js.__publicField(this, "delete");
1073
1108
  chunkOWW5GUSB_js.__publicField(this, "options");
1074
1109
  chunkOWW5GUSB_js.__publicField(this, "patch");
1110
+ chunkOWW5GUSB_js.__publicField(this, "query");
1075
1111
  chunkOWW5GUSB_js.__publicField(this, "all");
1076
1112
  chunkOWW5GUSB_js.__publicField(this, "on");
1077
1113
  chunkOWW5GUSB_js.__publicField(this, "use");
@@ -1133,8 +1169,8 @@ var Hono = (_a3 = class {
1133
1169
  * @see {@link https://hono.dev/docs/api/hono#fetch}
1134
1170
  *
1135
1171
  * @param {Request} request - request Object of request
1136
- * @param {Env} Env - env Object
1137
- * @param {ExecutionContext} - context of execution
1172
+ * @param {Env} env - env Object
1173
+ * @param {ExecutionContext} executionCtx - context of execution
1138
1174
  * @returns {Response | Promise<Response>} response of request
1139
1175
  *
1140
1176
  */
@@ -1425,7 +1461,7 @@ var Hono = (_a3 = class {
1425
1461
  })();
1426
1462
  }, _a3);
1427
1463
 
1428
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/matcher.js
1464
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/matcher.js
1429
1465
  var emptyParam = [];
1430
1466
  function match(method, path) {
1431
1467
  const matchers = this.buildAllMatchers();
@@ -1446,7 +1482,7 @@ function match(method, path) {
1446
1482
  return match2(method, path);
1447
1483
  }
1448
1484
 
1449
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/node.js
1485
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/node.js
1450
1486
  var LABEL_REG_EXP_STR = "[^/]+";
1451
1487
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
1452
1488
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
@@ -1460,7 +1496,7 @@ function compareKey(a, b) {
1460
1496
  return 1;
1461
1497
  }
1462
1498
  if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
1463
- return 1;
1499
+ return b === TAIL_WILDCARD_REG_EXP_STR ? -1 : 1;
1464
1500
  } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
1465
1501
  return -1;
1466
1502
  }
@@ -1474,77 +1510,76 @@ function compareKey(a, b) {
1474
1510
  var _index, _varIndex, _children, _a4;
1475
1511
  var Node = (_a4 = class {
1476
1512
  constructor() {
1513
+ // handler index of a dynamic path, or -1 for a static path terminal
1477
1514
  chunkOWW5GUSB_js.__privateAdd(this, _index);
1478
1515
  chunkOWW5GUSB_js.__privateAdd(this, _varIndex);
1479
1516
  chunkOWW5GUSB_js.__privateAdd(this, _children, /* @__PURE__ */ Object.create(null));
1480
1517
  }
1481
- insert(tokens, index, paramMap, context, pathErrorCheckOnly) {
1482
- if (tokens.length === 0) {
1483
- if (chunkOWW5GUSB_js.__privateGet(this, _index) !== void 0) {
1484
- throw PATH_ERROR;
1485
- }
1486
- if (pathErrorCheckOnly) {
1487
- return;
1488
- }
1489
- chunkOWW5GUSB_js.__privateSet(this, _index, index);
1490
- return;
1491
- }
1492
- const [token, ...restTokens] = tokens;
1493
- const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
1494
- let node;
1495
- if (pattern) {
1496
- const name = pattern[1];
1497
- let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
1498
- if (name && pattern[2]) {
1499
- if (regexpStr === ".*") {
1500
- throw PATH_ERROR;
1501
- }
1502
- regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
1503
- if (/\((?!\?:)/.test(regexpStr)) {
1504
- throw PATH_ERROR;
1505
- }
1506
- }
1507
- node = chunkOWW5GUSB_js.__privateGet(this, _children)[regexpStr];
1508
- if (!node) {
1509
- if (Object.keys(chunkOWW5GUSB_js.__privateGet(this, _children)).some(
1510
- (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
1511
- )) {
1512
- throw PATH_ERROR;
1518
+ insert(tokens, index, paramMap, context, isStatic) {
1519
+ let node = this;
1520
+ for (let i = 0, len = tokens.length; i < len; i++) {
1521
+ const token = tokens[i];
1522
+ 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(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
1523
+ let nextNode;
1524
+ if (pattern) {
1525
+ const name = pattern[1];
1526
+ let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
1527
+ if (name && pattern[2]) {
1528
+ if (regexpStr === ".*") {
1529
+ throw PATH_ERROR;
1530
+ }
1531
+ regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
1532
+ if (/\((?!\?:)/.test(regexpStr)) {
1533
+ throw PATH_ERROR;
1534
+ }
1535
+ if (regexpStr.length === 1 && regExpMetaChars.has(regexpStr)) {
1536
+ throw PATH_ERROR;
1537
+ }
1513
1538
  }
1514
- if (pathErrorCheckOnly) {
1515
- return;
1539
+ nextNode = chunkOWW5GUSB_js.__privateGet(node, _children)[regexpStr];
1540
+ if (!nextNode) {
1541
+ if (regexpStr !== ONLY_WILDCARD_REG_EXP_STR && regexpStr !== TAIL_WILDCARD_REG_EXP_STR) {
1542
+ for (const k in chunkOWW5GUSB_js.__privateGet(node, _children)) {
1543
+ if (
1544
+ // a single-char pattern coexists with single-char literals as a literal does
1545
+ (regexpStr.length > 1 || k.length > 1) && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
1546
+ ) {
1547
+ throw PATH_ERROR;
1548
+ }
1549
+ }
1550
+ }
1551
+ nextNode = chunkOWW5GUSB_js.__privateGet(node, _children)[regexpStr] = new _a4();
1516
1552
  }
1517
- node = chunkOWW5GUSB_js.__privateGet(this, _children)[regexpStr] = new _a4();
1518
1553
  if (name !== "") {
1519
- chunkOWW5GUSB_js.__privateSet(node, _varIndex, context.varIndex++);
1520
- }
1521
- }
1522
- if (!pathErrorCheckOnly && name !== "") {
1523
- paramMap.push([name, chunkOWW5GUSB_js.__privateGet(node, _varIndex)]);
1524
- }
1525
- } else {
1526
- node = chunkOWW5GUSB_js.__privateGet(this, _children)[token];
1527
- if (!node) {
1528
- if (Object.keys(chunkOWW5GUSB_js.__privateGet(this, _children)).some(
1529
- (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
1530
- )) {
1531
- throw PATH_ERROR;
1554
+ chunkOWW5GUSB_js.__privateGet(nextNode, _varIndex) ?? chunkOWW5GUSB_js.__privateSet(nextNode, _varIndex, context.varIndex++);
1555
+ paramMap.push([name, chunkOWW5GUSB_js.__privateGet(nextNode, _varIndex)]);
1532
1556
  }
1533
- if (pathErrorCheckOnly) {
1534
- return;
1557
+ } else {
1558
+ nextNode = chunkOWW5GUSB_js.__privateGet(node, _children)[token];
1559
+ if (!nextNode) {
1560
+ for (const k in chunkOWW5GUSB_js.__privateGet(node, _children)) {
1561
+ if (k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR) {
1562
+ throw PATH_ERROR;
1563
+ }
1564
+ }
1565
+ nextNode = chunkOWW5GUSB_js.__privateGet(node, _children)[token] = new _a4();
1535
1566
  }
1536
- node = chunkOWW5GUSB_js.__privateGet(this, _children)[token] = new _a4();
1537
1567
  }
1568
+ node = nextNode;
1569
+ }
1570
+ if (chunkOWW5GUSB_js.__privateGet(node, _index) !== void 0) {
1571
+ throw PATH_ERROR;
1538
1572
  }
1539
- node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly);
1573
+ chunkOWW5GUSB_js.__privateSet(node, _index, isStatic ? -1 : index);
1540
1574
  }
1541
1575
  buildRegExpStr() {
1542
1576
  const childKeys = Object.keys(chunkOWW5GUSB_js.__privateGet(this, _children)).sort(compareKey);
1543
1577
  const strList = childKeys.map((k) => {
1544
1578
  const c = chunkOWW5GUSB_js.__privateGet(this, _children)[k];
1545
- return (typeof chunkOWW5GUSB_js.__privateGet(c, _varIndex) === "number" ? `(${k})@${chunkOWW5GUSB_js.__privateGet(c, _varIndex)}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr();
1546
- });
1547
- if (typeof chunkOWW5GUSB_js.__privateGet(this, _index) === "number") {
1579
+ const childStr = c.buildRegExpStr();
1580
+ return childStr === "" ? "" : (typeof chunkOWW5GUSB_js.__privateGet(c, _varIndex) === "number" ? `(${k})@${chunkOWW5GUSB_js.__privateGet(c, _varIndex)}` : regExpMetaChars.has(k) ? `\\${k}` : k) + childStr;
1581
+ }).filter(Boolean);
1582
+ if (typeof chunkOWW5GUSB_js.__privateGet(this, _index) === "number" && chunkOWW5GUSB_js.__privateGet(this, _index) !== -1) {
1548
1583
  strList.unshift(`#${chunkOWW5GUSB_js.__privateGet(this, _index)}`);
1549
1584
  }
1550
1585
  if (strList.length === 0) {
@@ -1557,19 +1592,27 @@ var Node = (_a4 = class {
1557
1592
  }
1558
1593
  }, _index = new WeakMap(), _varIndex = new WeakMap(), _children = new WeakMap(), _a4);
1559
1594
 
1560
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/trie.js
1561
- var _context, _root, _a5;
1595
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/trie.js
1596
+ var _context, _root, _index2, _a5;
1562
1597
  var Trie = (_a5 = class {
1563
1598
  constructor() {
1564
1599
  chunkOWW5GUSB_js.__privateAdd(this, _context, { varIndex: 0 });
1565
1600
  chunkOWW5GUSB_js.__privateAdd(this, _root, new Node());
1601
+ chunkOWW5GUSB_js.__privateAdd(this, _index2, 0);
1602
+ // dynamic path -> [handler index, param assoc]; static paths are not registered
1603
+ chunkOWW5GUSB_js.__publicField(this, "paths", /* @__PURE__ */ Object.create(null));
1566
1604
  }
1567
- insert(path, index, pathErrorCheckOnly) {
1605
+ insert(path, isStatic) {
1606
+ if (isStatic) {
1607
+ chunkOWW5GUSB_js.__privateGet(this, _root).insert(path.split(""), 0, [], chunkOWW5GUSB_js.__privateGet(this, _context), true);
1608
+ return;
1609
+ }
1568
1610
  const paramAssoc = [];
1569
1611
  const groups = [];
1612
+ let markedPath = path;
1570
1613
  for (let i = 0; ; ) {
1571
1614
  let replaced = false;
1572
- path = path.replace(/\{[^}]+\}/g, (m) => {
1615
+ markedPath = markedPath.replace(/\{[^}]+\}/g, (m) => {
1573
1616
  const mark = `@\\${i}`;
1574
1617
  groups[i] = [mark, m];
1575
1618
  i++;
@@ -1580,7 +1623,7 @@ var Trie = (_a5 = class {
1580
1623
  break;
1581
1624
  }
1582
1625
  }
1583
- const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
1626
+ const tokens = markedPath.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
1584
1627
  for (let i = groups.length - 1; i >= 0; i--) {
1585
1628
  const [mark] = groups[i];
1586
1629
  for (let j = tokens.length - 1; j >= 0; j--) {
@@ -1590,8 +1633,8 @@ var Trie = (_a5 = class {
1590
1633
  }
1591
1634
  }
1592
1635
  }
1593
- chunkOWW5GUSB_js.__privateGet(this, _root).insert(tokens, index, paramAssoc, chunkOWW5GUSB_js.__privateGet(this, _context), pathErrorCheckOnly);
1594
- return paramAssoc;
1636
+ chunkOWW5GUSB_js.__privateGet(this, _root).insert(tokens, chunkOWW5GUSB_js.__privateGet(this, _index2), paramAssoc, chunkOWW5GUSB_js.__privateGet(this, _context), false);
1637
+ this.paths[path] = [chunkOWW5GUSB_js.__privateWrapper(this, _index2)._++, paramAssoc];
1595
1638
  }
1596
1639
  buildRegExp() {
1597
1640
  let regexp = chunkOWW5GUSB_js.__privateGet(this, _root).buildRegExpStr();
@@ -1614,10 +1657,9 @@ var Trie = (_a5 = class {
1614
1657
  });
1615
1658
  return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
1616
1659
  }
1617
- }, _context = new WeakMap(), _root = new WeakMap(), _a5);
1660
+ }, _context = new WeakMap(), _root = new WeakMap(), _index2 = new WeakMap(), _a5);
1618
1661
 
1619
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/router.js
1620
- var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
1662
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/reg-exp-router/router.js
1621
1663
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
1622
1664
  function buildWildcardRegExp(path) {
1623
1665
  return wildcardRegExpCache[path] ?? (wildcardRegExpCache[path] = new RegExp(
@@ -1630,63 +1672,6 @@ function buildWildcardRegExp(path) {
1630
1672
  function clearWildcardRegExpCache() {
1631
1673
  wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
1632
1674
  }
1633
- function buildMatcherFromPreprocessedRoutes(routes) {
1634
- const trie = new Trie();
1635
- const handlerData = [];
1636
- if (routes.length === 0) {
1637
- return nullMatcher;
1638
- }
1639
- const routesWithStaticPathFlag = routes.map(
1640
- (route) => [!/\*|\/:/.test(route[0]), ...route]
1641
- ).sort(
1642
- ([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
1643
- );
1644
- const staticMap = /* @__PURE__ */ Object.create(null);
1645
- for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
1646
- const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i];
1647
- if (pathErrorCheckOnly) {
1648
- staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
1649
- } else {
1650
- j++;
1651
- }
1652
- let paramAssoc;
1653
- try {
1654
- paramAssoc = trie.insert(path, j, pathErrorCheckOnly);
1655
- } catch (e) {
1656
- throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
1657
- }
1658
- if (pathErrorCheckOnly) {
1659
- continue;
1660
- }
1661
- handlerData[j] = handlers.map(([h, paramCount]) => {
1662
- const paramIndexMap = /* @__PURE__ */ Object.create(null);
1663
- paramCount -= 1;
1664
- for (; paramCount >= 0; paramCount--) {
1665
- const [key, value] = paramAssoc[paramCount];
1666
- paramIndexMap[key] = value;
1667
- }
1668
- return [h, paramIndexMap];
1669
- });
1670
- }
1671
- const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
1672
- for (let i = 0, len = handlerData.length; i < len; i++) {
1673
- for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
1674
- const map = handlerData[i][j]?.[1];
1675
- if (!map) {
1676
- continue;
1677
- }
1678
- const keys = Object.keys(map);
1679
- for (let k = 0, len3 = keys.length; k < len3; k++) {
1680
- map[keys[k]] = paramReplacementMap[map[keys[k]]];
1681
- }
1682
- }
1683
- }
1684
- const handlerMap = [];
1685
- for (const i in indexReplacementMap) {
1686
- handlerMap[i] = handlerData[indexReplacementMap[i]];
1687
- }
1688
- return [regexp, handlerMap, staticMap];
1689
- }
1690
1675
  function findMiddleware(middleware, path) {
1691
1676
  if (!middleware) {
1692
1677
  return void 0;
@@ -1698,29 +1683,32 @@ function findMiddleware(middleware, path) {
1698
1683
  }
1699
1684
  return void 0;
1700
1685
  }
1701
- var _middleware, _routes, _RegExpRouter_instances, buildMatcher_fn, _a6;
1686
+ var _middleware, _routes, _tries, _RegExpRouter_instances, insertPath_fn, buildMatcher_fn, _a6;
1702
1687
  var RegExpRouter = (_a6 = class {
1703
1688
  constructor() {
1704
1689
  chunkOWW5GUSB_js.__privateAdd(this, _RegExpRouter_instances);
1705
1690
  chunkOWW5GUSB_js.__publicField(this, "name", "RegExpRouter");
1706
1691
  chunkOWW5GUSB_js.__privateAdd(this, _middleware);
1707
1692
  chunkOWW5GUSB_js.__privateAdd(this, _routes);
1693
+ chunkOWW5GUSB_js.__privateAdd(this, _tries);
1708
1694
  chunkOWW5GUSB_js.__publicField(this, "match", match);
1709
1695
  chunkOWW5GUSB_js.__privateSet(this, _middleware, { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) });
1710
1696
  chunkOWW5GUSB_js.__privateSet(this, _routes, { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) });
1697
+ chunkOWW5GUSB_js.__privateSet(this, _tries, { [METHOD_NAME_ALL]: new Trie() });
1711
1698
  }
1712
1699
  add(method, path, handler) {
1713
- var _a10;
1714
1700
  const middleware = chunkOWW5GUSB_js.__privateGet(this, _middleware);
1715
1701
  const routes = chunkOWW5GUSB_js.__privateGet(this, _routes);
1716
1702
  if (!middleware || !routes) {
1717
1703
  throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
1718
1704
  }
1719
1705
  if (!middleware[method]) {
1706
+ chunkOWW5GUSB_js.__privateGet(this, _tries)[method] = new Trie();
1720
1707
  [middleware, routes].forEach((handlerMap) => {
1721
1708
  handlerMap[method] = /* @__PURE__ */ Object.create(null);
1722
1709
  Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
1723
1710
  handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
1711
+ chunkOWW5GUSB_js.__privateMethod(this, _RegExpRouter_instances, insertPath_fn).call(this, method, p);
1724
1712
  });
1725
1713
  });
1726
1714
  }
@@ -1730,14 +1718,12 @@ var RegExpRouter = (_a6 = class {
1730
1718
  const paramCount = (path.match(/\/:/g) || []).length;
1731
1719
  if (/\*$/.test(path)) {
1732
1720
  const re = buildWildcardRegExp(path);
1733
- if (method === METHOD_NAME_ALL) {
1734
- Object.keys(middleware).forEach((m) => {
1735
- var _a11;
1736
- (_a11 = middleware[m])[path] || (_a11[path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || []);
1737
- });
1738
- } else {
1739
- (_a10 = middleware[method])[path] || (_a10[path] = findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || []);
1740
- }
1721
+ Object.keys(middleware).forEach((m) => {
1722
+ if ((method === METHOD_NAME_ALL || method === m) && !middleware[m][path]) {
1723
+ chunkOWW5GUSB_js.__privateMethod(this, _RegExpRouter_instances, insertPath_fn).call(this, m, path);
1724
+ middleware[m][path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
1725
+ }
1726
+ });
1741
1727
  Object.keys(middleware).forEach((m) => {
1742
1728
  if (method === METHOD_NAME_ALL || method === m) {
1743
1729
  Object.keys(middleware[m]).forEach((p) => {
@@ -1758,11 +1744,13 @@ var RegExpRouter = (_a6 = class {
1758
1744
  for (let i = 0, len = paths.length; i < len; i++) {
1759
1745
  const path2 = paths[i];
1760
1746
  Object.keys(routes).forEach((m) => {
1761
- var _a11;
1762
1747
  if (method === METHOD_NAME_ALL || method === m) {
1763
- (_a11 = routes[m])[path2] || (_a11[path2] = [
1764
- ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
1765
- ]);
1748
+ if (!routes[m][path2]) {
1749
+ chunkOWW5GUSB_js.__privateMethod(this, _RegExpRouter_instances, insertPath_fn).call(this, m, path2);
1750
+ routes[m][path2] = [
1751
+ ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
1752
+ ];
1753
+ }
1766
1754
  routes[m][path2].push([handler, paramCount - len + i + 1]);
1767
1755
  }
1768
1756
  });
@@ -1773,32 +1761,63 @@ var RegExpRouter = (_a6 = class {
1773
1761
  Object.keys(chunkOWW5GUSB_js.__privateGet(this, _routes)).concat(Object.keys(chunkOWW5GUSB_js.__privateGet(this, _middleware))).forEach((method) => {
1774
1762
  matchers[method] || (matchers[method] = chunkOWW5GUSB_js.__privateMethod(this, _RegExpRouter_instances, buildMatcher_fn).call(this, method));
1775
1763
  });
1776
- chunkOWW5GUSB_js.__privateSet(this, _middleware, chunkOWW5GUSB_js.__privateSet(this, _routes, void 0));
1764
+ chunkOWW5GUSB_js.__privateSet(this, _middleware, chunkOWW5GUSB_js.__privateSet(this, _routes, chunkOWW5GUSB_js.__privateSet(this, _tries, void 0)));
1777
1765
  clearWildcardRegExpCache();
1778
1766
  return matchers;
1779
1767
  }
1780
- }, _middleware = new WeakMap(), _routes = new WeakMap(), _RegExpRouter_instances = new WeakSet(), buildMatcher_fn = function(method) {
1781
- const routes = [];
1782
- let hasOwnRoute = method === METHOD_NAME_ALL;
1783
- [chunkOWW5GUSB_js.__privateGet(this, _middleware), chunkOWW5GUSB_js.__privateGet(this, _routes)].forEach((r) => {
1784
- const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [];
1785
- if (ownRoute.length !== 0) {
1786
- hasOwnRoute || (hasOwnRoute = true);
1787
- routes.push(...ownRoute);
1788
- } else if (method !== METHOD_NAME_ALL) {
1789
- routes.push(
1790
- ...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]])
1791
- );
1768
+ }, _middleware = new WeakMap(), _routes = new WeakMap(), _tries = new WeakMap(), _RegExpRouter_instances = new WeakSet(), insertPath_fn = function(method, path) {
1769
+ try {
1770
+ chunkOWW5GUSB_js.__privateGet(this, _tries)[method].insert(path, !/\*|\/:/.test(path));
1771
+ } catch (e) {
1772
+ throw e === PATH_ERROR ? new UnsupportedPathError(path) : e;
1773
+ }
1774
+ }, buildMatcher_fn = function(method) {
1775
+ const middleware = chunkOWW5GUSB_js.__privateGet(this, _middleware)[method];
1776
+ const routes = chunkOWW5GUSB_js.__privateGet(this, _routes)[method];
1777
+ const trie = chunkOWW5GUSB_js.__privateGet(this, _tries)[method];
1778
+ const staticMap = /* @__PURE__ */ Object.create(null);
1779
+ const handlerData = [];
1780
+ [middleware, routes].forEach((r) => {
1781
+ for (const path in r) {
1782
+ const handlers = r[path];
1783
+ const pathData = trie.paths[path];
1784
+ if (!pathData) {
1785
+ staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
1786
+ continue;
1787
+ }
1788
+ const paramAssoc = pathData[1];
1789
+ handlerData[pathData[0]] = handlers.map(([h, paramCount]) => {
1790
+ const paramIndexMap = /* @__PURE__ */ Object.create(null);
1791
+ paramCount -= 1;
1792
+ for (; paramCount >= 0; paramCount--) {
1793
+ const [key, value] = paramAssoc[paramCount];
1794
+ paramIndexMap[key] = value;
1795
+ }
1796
+ return [h, paramIndexMap];
1797
+ });
1792
1798
  }
1793
1799
  });
1794
- if (!hasOwnRoute) {
1795
- return null;
1796
- } else {
1797
- return buildMatcherFromPreprocessedRoutes(routes);
1800
+ const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
1801
+ for (let i = 0, len = handlerData.length; i < len; i++) {
1802
+ for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
1803
+ const map = handlerData[i][j]?.[1];
1804
+ if (!map) {
1805
+ continue;
1806
+ }
1807
+ const keys = Object.keys(map);
1808
+ for (let k = 0, len3 = keys.length; k < len3; k++) {
1809
+ map[keys[k]] = paramReplacementMap[map[keys[k]]];
1810
+ }
1811
+ }
1812
+ }
1813
+ const handlerMap = [];
1814
+ for (const i in indexReplacementMap) {
1815
+ handlerMap[i] = handlerData[indexReplacementMap[i]];
1798
1816
  }
1817
+ return [regexp, handlerMap, staticMap];
1799
1818
  }, _a6);
1800
1819
 
1801
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/smart-router/router.js
1820
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/smart-router/router.js
1802
1821
  var _routers, _routes2, _a7;
1803
1822
  var SmartRouter = (_a7 = class {
1804
1823
  constructor(init) {
@@ -1854,7 +1873,7 @@ var SmartRouter = (_a7 = class {
1854
1873
  }
1855
1874
  }, _routers = new WeakMap(), _routes2 = new WeakMap(), _a7);
1856
1875
 
1857
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/trie-router/node.js
1876
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/trie-router/node.js
1858
1877
  var emptyParams = /* @__PURE__ */ Object.create(null);
1859
1878
  var hasChildren = (children) => {
1860
1879
  for (const _ in children) {
@@ -1971,9 +1990,12 @@ var Node2 = (_a8 = class {
1971
1990
  if (m) {
1972
1991
  params[name] = m[0];
1973
1992
  chunkOWW5GUSB_js.__privateMethod(this, __Node_instances, pushHandlerSets_fn).call(this, handlerSets, child, method, chunkOWW5GUSB_js.__privateGet(node, _params), params);
1993
+ if (m[0].length === restPathString.length && chunkOWW5GUSB_js.__privateGet(child, _children2)["*"]) {
1994
+ chunkOWW5GUSB_js.__privateMethod(this, __Node_instances, pushHandlerSets_fn).call(this, handlerSets, chunkOWW5GUSB_js.__privateGet(child, _children2)["*"], method, chunkOWW5GUSB_js.__privateGet(node, _params), params);
1995
+ }
1974
1996
  if (hasChildren(chunkOWW5GUSB_js.__privateGet(child, _children2))) {
1975
1997
  chunkOWW5GUSB_js.__privateSet(child, _params, params);
1976
- const componentCount = m[0].match(/\//)?.length ?? 0;
1998
+ const componentCount = m[0].match(/\//g)?.length ?? 0;
1977
1999
  const targetCurNodes = curNodesQueue[componentCount] || (curNodesQueue[componentCount] = []);
1978
2000
  targetCurNodes.push(child);
1979
2001
  }
@@ -2024,7 +2046,7 @@ var Node2 = (_a8 = class {
2024
2046
  }
2025
2047
  }, _a8);
2026
2048
 
2027
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/trie-router/router.js
2049
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/router/trie-router/router.js
2028
2050
  var _node, _a9;
2029
2051
  var TrieRouter = (_a9 = class {
2030
2052
  constructor() {
@@ -2047,7 +2069,7 @@ var TrieRouter = (_a9 = class {
2047
2069
  }
2048
2070
  }, _node = new WeakMap(), _a9);
2049
2071
 
2050
- // ../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/hono.js
2072
+ // ../node_modules/.bun/hono@4.13.2/node_modules/hono/dist/hono.js
2051
2073
  var Hono2 = class extends Hono {
2052
2074
  /**
2053
2075
  * Creates an instance of the Hono class.
@@ -2078,8 +2100,8 @@ var MockError = class extends Error {
2078
2100
  };
2079
2101
  }
2080
2102
  };
2081
- var notFound = (msg) => new MockError(chunkJG5CQNCB_js.ErrorCode.NOT_FOUND, msg, 404);
2082
- var validation = (msg, ctx) => new MockError(chunkJG5CQNCB_js.ErrorCode.VALIDATION_ERROR, msg, 400, ctx);
2103
+ var notFound = (msg) => new MockError(chunkSFUJMS5E_js.ErrorCode.NOT_FOUND, msg, 404);
2104
+ var validation = (msg, ctx) => new MockError(chunkSFUJMS5E_js.ErrorCode.VALIDATION_ERROR, msg, 400, ctx);
2083
2105
 
2084
2106
  // src/mock/routes/_helpers.ts
2085
2107
  function authMiddleware(deps) {
@@ -2092,7 +2114,7 @@ function authMiddleware(deps) {
2092
2114
  await next();
2093
2115
  };
2094
2116
  }
2095
- var IDEMPOTENT_PATH_RE = /\/(cart\/items|cart\/coupons|checkout|payments\/authorization|auth\/(request-otp|verify-otp|profile|logout))(\/|$)/;
2117
+ var IDEMPOTENT_PATH_RE = /\/(cart\/items|cart\/coupons|checkout|purchase-intents|payments\/authorization|auth\/(request-otp|verify-otp|profile|logout))(\/|$)/;
2096
2118
  var IDEMPOTENCY_TTL_MS = 24 * 60 * 60 * 1e3;
2097
2119
  function idempotencyMiddleware(deps) {
2098
2120
  return async (c, next) => {
@@ -2102,7 +2124,8 @@ function idempotencyMiddleware(deps) {
2102
2124
  const key = c.req.header("idempotency-key") ?? c.req.header("Idempotency-Key");
2103
2125
  if (!key || key.length > 200) return next();
2104
2126
  const session = c.var.session;
2105
- const recordId = `${session.id}:${key}`;
2127
+ const routeScope = c.req.path.includes("/purchase-intents") ? `:${c.req.path}` : "";
2128
+ const recordId = `${session.id}${routeScope}:${key}`;
2106
2129
  const existing = deps.registry.idempotency.get(recordId);
2107
2130
  if (existing) {
2108
2131
  const expiresAt = Date.parse(existing.expires_at);
@@ -2176,6 +2199,21 @@ function getQueryNum(c, key) {
2176
2199
  }
2177
2200
 
2178
2201
  // src/mock/routes/v1.ts
2202
+ var PURCHASE_INTENT_ROUTE = {
2203
+ COLLECTION: "/purchase-intents",
2204
+ MEMBER: "/purchase-intents/:intent_id",
2205
+ REFRESH: "/purchase-intents/:intent_id/refresh",
2206
+ CONFIRM: "/purchase-intents/:intent_id/confirm",
2207
+ ACTION: "/purchase-intents/:intent_id/attempts/:attempt_id/actions"
2208
+ };
2209
+ var PURCHASE_INTENT_ROUTE_PARAM = {
2210
+ INTENT_ID: "intent_id",
2211
+ ATTEMPT_ID: "attempt_id"
2212
+ };
2213
+ var PAYMENT_ROUTE = {
2214
+ COLLECTION_OPTIONS: "/payments/collection-options",
2215
+ AUTHORIZATION: "/payments/authorization"
2216
+ };
2179
2217
  function buildV1(deps) {
2180
2218
  const app = new Hono2();
2181
2219
  app.use("*", chaosMiddleware(deps));
@@ -2437,6 +2475,36 @@ function buildV1(deps) {
2437
2475
  "/catalogue/quotes/:quote_id/refresh",
2438
2476
  (c) => tryRoute(c, () => deps.catalogue.refreshQuote(c.req.param("quote_id")))
2439
2477
  );
2478
+ app.get("/reviews/summary", (c) => {
2479
+ const productId = c.req.query("product_id");
2480
+ if (productId !== void 0 && (productId.length === 0 || productId.trim() !== productId)) {
2481
+ return fail(c, validation("product_id must be a non-empty canonical identifier"));
2482
+ }
2483
+ const response = {
2484
+ data: {
2485
+ ratings: {
2486
+ product_id: productId ?? null,
2487
+ review_count: 0,
2488
+ rating_sum: 0,
2489
+ average_rating: null,
2490
+ distribution: { one: 0, two: 0, three: 0, four: 0, five: 0 }
2491
+ },
2492
+ trust_chips: {
2493
+ on_time_delivery_percent: null,
2494
+ delivery_sample_size: 0,
2495
+ average_first_response_seconds: null,
2496
+ support_sample_size: 0
2497
+ }
2498
+ }
2499
+ };
2500
+ return c.json(response);
2501
+ });
2502
+ app.get("/reviews", (c) => {
2503
+ const response = {
2504
+ data: { items: [], next_cursor: null }
2505
+ };
2506
+ return c.json(response);
2507
+ });
2440
2508
  app.get("/cart", (c) => tryRoute(c, () => deps.cart.toUICart(deps.cart.get(c.var.session))));
2441
2509
  app.delete("/cart", (c) => tryRoute(c, () => deps.cart.clear(c.var.session)));
2442
2510
  app.get("/cart/items", (c) => tryRoute(c, () => deps.cart.getItems(c.var.session)));
@@ -2518,28 +2586,81 @@ function buildV1(deps) {
2518
2586
  "/subscriptions/:subscription_id/skip",
2519
2587
  (c) => tryRoute(c, () => deps.subscriptions.skipNext(c.req.param("subscription_id")))
2520
2588
  );
2521
- app.get("/payments/collection-options", (c) => {
2589
+ app.get(PAYMENT_ROUTE.COLLECTION_OPTIONS, async (c) => {
2522
2590
  const currency = c.req.query("currency")?.trim().toUpperCase();
2523
2591
  if (!currency || !/^[A-Z]{3}$/.test(currency)) {
2524
2592
  return fail(c, validation("currency must be a canonical three-letter code"));
2525
2593
  }
2526
2594
  return tryRoute(c, () => ({
2527
2595
  presentment_currency: currency,
2528
- options: currency === "GHS" ? [
2529
- { method: chunkCNN7Z2IP_js.PAYMENT_METHOD.CARD, network: null },
2530
- { method: chunkCNN7Z2IP_js.PAYMENT_METHOD.MOBILE_MONEY, network: "mtn" },
2531
- { method: chunkCNN7Z2IP_js.PAYMENT_METHOD.MOBILE_MONEY, network: "telecel" },
2532
- { method: chunkCNN7Z2IP_js.PAYMENT_METHOD.MOBILE_MONEY, network: "airteltigo" }
2533
- ] : currency === "USD" ? [{ method: chunkCNN7Z2IP_js.PAYMENT_METHOD.CARD, network: null }] : []
2596
+ options: currency === chunkEV2EVOYS_js.DEFAULT_CURRENCY ? [
2597
+ { method: chunkEV2EVOYS_js.PAYMENT_METHOD.CARD, network: null },
2598
+ {
2599
+ method: chunkEV2EVOYS_js.PAYMENT_METHOD.MOBILE_MONEY,
2600
+ network: chunkSFUJMS5E_js.PURCHASE_INTENT_MOBILE_MONEY_NETWORK.MTN
2601
+ },
2602
+ {
2603
+ method: chunkEV2EVOYS_js.PAYMENT_METHOD.MOBILE_MONEY,
2604
+ network: chunkSFUJMS5E_js.PURCHASE_INTENT_MOBILE_MONEY_NETWORK.TELECEL
2605
+ },
2606
+ {
2607
+ method: chunkEV2EVOYS_js.PAYMENT_METHOD.MOBILE_MONEY,
2608
+ network: chunkSFUJMS5E_js.PURCHASE_INTENT_MOBILE_MONEY_NETWORK.AIRTEL
2609
+ }
2610
+ ] : currency === "USD" ? [{ method: chunkEV2EVOYS_js.PAYMENT_METHOD.CARD, network: null }] : []
2534
2611
  }));
2535
2612
  });
2536
- app.post("/checkout", async (c) => {
2613
+ app.post(PURCHASE_INTENT_ROUTE.COLLECTION, async (c) => {
2614
+ const body = await c.req.json().catch(() => ({}));
2615
+ return tryRoute(c, () => deps.purchaseIntents.mint(c.var.session, body));
2616
+ });
2617
+ app.get(
2618
+ PURCHASE_INTENT_ROUTE.MEMBER,
2619
+ (c) => tryRoute(
2620
+ c,
2621
+ () => deps.purchaseIntents.get(
2622
+ c.var.session,
2623
+ c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID)
2624
+ )
2625
+ )
2626
+ );
2627
+ app.post(PURCHASE_INTENT_ROUTE.REFRESH, async (c) => {
2628
+ const body = await c.req.json().catch(() => ({}));
2629
+ return tryRoute(
2630
+ c,
2631
+ () => deps.purchaseIntents.refresh(
2632
+ c.var.session,
2633
+ c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID),
2634
+ body.expected_intent_revision
2635
+ )
2636
+ );
2637
+ });
2638
+ app.post(PURCHASE_INTENT_ROUTE.CONFIRM, async (c) => {
2639
+ const body = await c.req.json().catch(() => ({}));
2640
+ return tryRoute(
2641
+ c,
2642
+ () => deps.purchaseIntents.confirm(
2643
+ c.var.session,
2644
+ c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID),
2645
+ body
2646
+ )
2647
+ );
2648
+ });
2649
+ app.post(PURCHASE_INTENT_ROUTE.ACTION, async (c) => {
2537
2650
  const body = await c.req.json().catch(() => ({}));
2538
- return tryRoute(c, () => deps.checkout.process(c.var.session, body));
2651
+ return tryRoute(
2652
+ c,
2653
+ () => deps.purchaseIntents.submitAction(
2654
+ c.var.session,
2655
+ c.req.param(PURCHASE_INTENT_ROUTE_PARAM.INTENT_ID),
2656
+ c.req.param(PURCHASE_INTENT_ROUTE_PARAM.ATTEMPT_ID),
2657
+ body
2658
+ )
2659
+ );
2539
2660
  });
2540
- app.post("/payments/authorization", async (c) => {
2661
+ app.post(PAYMENT_ROUTE.AUTHORIZATION, async (c) => {
2541
2662
  const body = await c.req.json().catch(() => ({}));
2542
- return tryRoute(c, () => deps.checkout.authorize(body));
2663
+ return tryRoute(c, () => deps.payments.authorize(body));
2543
2664
  });
2544
2665
  app.get("/auth/status", (c) => tryRoute(c, () => deps.auth.status(c.var.session.token)));
2545
2666
  app.post("/auth/request-otp", async (c) => {
@@ -2845,6 +2966,7 @@ function createStateRegistry() {
2845
2966
  collections: createMemoryStore(),
2846
2967
  carts: createMemoryStore(),
2847
2968
  orders: createMemoryStore(),
2969
+ purchaseIntents: createMemoryStore(),
2848
2970
  subscriptions: createMemoryStore(),
2849
2971
  bookings: createMemoryStore(),
2850
2972
  services: createMemoryStore(),
@@ -2994,9 +3116,9 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
2994
3116
  // injected into the HTML page served by the mock. Edit this file directly \u2014
2995
3117
  // type-check via tsgo + the IframeToParentMessage shape from the SDK.
2996
3118
  (function () {
2997
- var TYPE = window.__CIMPLIFY_MOCK_ELEMENT__;
2998
- var DEFAULT_BUSINESS = window.__CIMPLIFY_MOCK_BUSINESS__;
2999
- var MSG = {
3119
+ const TYPE = window.__CIMPLIFY_MOCK_ELEMENT__;
3120
+ const DEFAULT_BUSINESS = window.__CIMPLIFY_MOCK_BUSINESS__;
3121
+ const MSG = {
3000
3122
  INIT: "init", SET_TOKEN: "set_token", SET_CART: "set_cart", GET_DATA: "get_data",
3001
3123
  REFRESH_TOKEN: "refresh_token", LOGOUT: "logout",
3002
3124
  PROCESS_CHECKOUT: "process_checkout", ABORT_CHECKOUT: "abort_checkout",
@@ -3009,12 +3131,36 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3009
3131
  CHECKOUT_STATUS: "checkout_status", CHECKOUT_COMPLETE: "checkout_complete",
3010
3132
  ORDER_TYPE_CHANGED: "order_type_changed", REQUEST_SUBMIT: "request_submit"
3011
3133
  };
3012
- var qs = new URLSearchParams(location.search);
3013
- var AUTO = qs.get("auto") === "true";
3014
- var DEMO_OTP = qs.get("otp") || "123456";
3015
- var ORIGIN = qs.get("origin") || "*";
3016
- var NONCE = qs.get("nonce");
3017
- var state = {
3134
+ const PURCHASE_INTENT = {
3135
+ PATH: "/api/v1/purchase-intents",
3136
+ ORDER_CREATED: "order_created",
3137
+ CARD_POPUP_REQUIRED: "card_popup_required",
3138
+ AUTHORIZATION_REQUIRED: "authorization_required",
3139
+ ELIGIBLE: "eligible"
3140
+ };
3141
+ const CHECKOUT_STATUS = {
3142
+ PROCESSING: "processing",
3143
+ SUCCESS: "success",
3144
+ FAILED: "failed"
3145
+ };
3146
+ const CHECKOUT_ERROR = { FAILED: "CHECKOUT_FAILED" };
3147
+ const ORDER_STATUS = { CONFIRMED: "confirmed" };
3148
+ const TENDER = {
3149
+ CARD: "card",
3150
+ MOBILE_MONEY: "mobile_money",
3151
+ AUTHORITY_TRANSIENT: "transient",
3152
+ MTN: "mtn"
3153
+ };
3154
+ const PAYMENT_PROVIDER = { PAYSTACK: "paystack" };
3155
+ const SOURCE_KIND = { CART: "cart" };
3156
+ const AUTHORIZATION = { OTP: "otp" };
3157
+ const EXACT_ZERO_MONEY = /^[+-]?0+(?:\\.0+)?(?:[eE][+-]?\\d+)?$/;
3158
+ const qs = new URLSearchParams(location.search);
3159
+ const AUTO = qs.get("auto") === "true";
3160
+ const DEMO_OTP = qs.get("otp") || "123456";
3161
+ const ORIGIN = qs.get("origin") || "*";
3162
+ const NONCE = qs.get("nonce");
3163
+ const state = {
3018
3164
  businessId: DEFAULT_BUSINESS,
3019
3165
  token: null,
3020
3166
  cart: null,
@@ -3025,15 +3171,33 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3025
3171
  contact: null,
3026
3172
  pendingOtp: null
3027
3173
  };
3028
- var content = document.getElementById("content");
3029
- var title = document.getElementById("title");
3174
+ const content = document.getElementById("content");
3175
+ const title = document.getElementById("title");
3030
3176
 
3031
3177
  function send(msg) {
3032
3178
  if (NONCE) msg.nonce = NONCE;
3033
3179
  parent.postMessage(msg, ORIGIN);
3034
3180
  }
3181
+ function isExactlyZeroMoney(value) {
3182
+ return typeof value === "number"
3183
+ ? Object.is(value, 0) || Object.is(value, -0)
3184
+ : EXACT_ZERO_MONEY.test(String(value).trim());
3185
+ }
3035
3186
  function reportHeight() { send({ type: MSG.HEIGHT_CHANGE, height: document.documentElement.scrollHeight }); }
3036
3187
  function ready() { send({ type: MSG.READY, height: document.documentElement.scrollHeight }); }
3188
+ function responseWithBody(response) {
3189
+ return response.json().then(function (body) {
3190
+ return { status: response.status, body: body };
3191
+ });
3192
+ }
3193
+ function assertSuccessfulResponse(response, fallbackMessage) {
3194
+ if (response.status >= 400) {
3195
+ throw new Error(
3196
+ (response.body && response.body.error && response.body.error.message) || fallbackMessage
3197
+ );
3198
+ }
3199
+ return response.body;
3200
+ }
3037
3201
 
3038
3202
  function defaultAddress() {
3039
3203
  return {
@@ -3043,9 +3207,20 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3043
3207
  };
3044
3208
  }
3045
3209
  function defaultPayment(type) {
3046
- if (type === "card") return { type: "card", provider: "paystack", last_four: "4242", label: "Visa \u2022\u2022\u2022\u2022 4242" };
3047
- if (type === "cash") return { type: "cash", label: "Cash on delivery" };
3048
- return { type: "mobile_money", provider: "mtn", phone_number: "+233244000000", label: "MTN Mobile Money" };
3210
+ if (type === TENDER.CARD) {
3211
+ return {
3212
+ type: TENDER.CARD,
3213
+ provider: PAYMENT_PROVIDER.PAYSTACK,
3214
+ last_four: "4242",
3215
+ label: "Visa \u2022\u2022\u2022\u2022 4242"
3216
+ };
3217
+ }
3218
+ return {
3219
+ type: TENDER.MOBILE_MONEY,
3220
+ provider: TENDER.MTN,
3221
+ phone_number: "+233244000000",
3222
+ label: "MTN Mobile Money"
3223
+ };
3049
3224
  }
3050
3225
 
3051
3226
  function renderAuth() {
@@ -3070,12 +3245,12 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3070
3245
  ' <div class="option" data-key="lagos">5 Allen Ave, Ikeja, Lagos</div>' +
3071
3246
  '</div>' +
3072
3247
  '<button id="confirm">Use this address</button>';
3073
- var options = {
3248
+ const options = {
3074
3249
  "default": defaultAddress(),
3075
3250
  "east-legon": { street_address: "8 Ring Road", city: "Accra", region: "Greater Accra", country: "GH", latitude: 5.65, longitude: -0.16 },
3076
3251
  "lagos": { street_address: "5 Allen Avenue", city: "Lagos", region: "Lagos", country: "NG", latitude: 6.5244, longitude: 3.3792 }
3077
3252
  };
3078
- var picked = "default";
3253
+ let picked = "default";
3079
3254
  Array.prototype.forEach.call(document.querySelectorAll(".option"), function (el) {
3080
3255
  el.onclick = function () {
3081
3256
  picked = el.getAttribute("data-key");
@@ -3098,10 +3273,9 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3098
3273
  '<div class="options" id="pay-options">' +
3099
3274
  ' <div class="option selected" data-method="mobile_money">\u{1F4F1} MTN Mobile Money</div>' +
3100
3275
  ' <div class="option" data-method="card">\u{1F4B3} Card (Paystack)</div>' +
3101
- ' <div class="option" data-method="cash">\u{1F4B5} Cash on delivery</div>' +
3102
3276
  '</div>' +
3103
3277
  '<button id="confirm">Use this method</button>';
3104
- var picked = "mobile_money";
3278
+ let picked = TENDER.MOBILE_MONEY;
3105
3279
  Array.prototype.forEach.call(document.querySelectorAll(".option"), function (el) {
3106
3280
  el.onclick = function () {
3107
3281
  picked = el.getAttribute("data-method");
@@ -3145,7 +3319,6 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3145
3319
  '</div>' +
3146
3320
  '<label>Payment method</label>' +
3147
3321
  '<select id="pay-method">' +
3148
- ' <option value="cash">Cash</option>' +
3149
3322
  ' <option value="mobile_money">Mobile Money (MTN)</option>' +
3150
3323
  ' <option value="card">Card (Paystack)</option>' +
3151
3324
  '</select>' +
@@ -3162,65 +3335,139 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3162
3335
  }
3163
3336
 
3164
3337
  function runCheckout() {
3165
- var statusEl = document.getElementById("status");
3166
- var errEl = document.getElementById("err");
3167
- var resultEl = document.getElementById("result");
3338
+ const statusEl = document.getElementById("status");
3339
+ const errEl = document.getElementById("err");
3340
+ const resultEl = document.getElementById("result");
3168
3341
  if (errEl) errEl.textContent = "";
3169
3342
  if (!state.cart) { errEl.textContent = "No cart provided"; return; }
3170
- var customer = {
3343
+ const customer = {
3171
3344
  name: document.getElementById("cust-name").value.trim() || "Customer",
3172
3345
  email: document.getElementById("cust-email").value.trim() || "noemail@example.com",
3173
3346
  phone: document.getElementById("cust-phone").value.trim() || "+233000000000",
3174
3347
  save_details: false
3175
3348
  };
3176
- var paymentMethod = document.getElementById("pay-method").value;
3177
- var orderType = document.getElementById("order-type").value;
3349
+ const paymentMethod = document.getElementById("pay-method").value;
3350
+ const orderType = document.getElementById("order-type").value;
3178
3351
  statusEl.textContent = "Processing\u2026";
3179
- send({ type: MSG.CHECKOUT_STATUS, status: "processing", context: {} });
3352
+ send({ type: MSG.CHECKOUT_STATUS, status: CHECKOUT_STATUS.PROCESSING, context: {} });
3180
3353
 
3181
- var headers = { "content-type": "application/json" };
3354
+ const headers = { "content-type": "application/json" };
3182
3355
  if (state.token) headers["x-session-token"] = state.token;
3183
3356
 
3184
- fetch("/api/v1/checkout", {
3357
+ const preference = paymentMethod === TENDER.MOBILE_MONEY
3358
+ ? {
3359
+ method_kind: TENDER.MOBILE_MONEY,
3360
+ authority: {
3361
+ authority_kind: TENDER.AUTHORITY_TRANSIENT,
3362
+ phone_number: customer.phone,
3363
+ network: TENDER.MTN
3364
+ }
3365
+ }
3366
+ : { method_kind: TENDER.CARD };
3367
+ const intentKey = "mock-element:" + state.cart.id;
3368
+ fetch(PURCHASE_INTENT.PATH, {
3185
3369
  method: "POST",
3186
3370
  headers: headers,
3187
3371
  body: JSON.stringify({
3188
- cart_id: state.cart.id,
3189
- customer: customer,
3190
- order_type: orderType,
3191
- payment_method: paymentMethod,
3192
- address_info: state.address || undefined
3372
+ client_intent_key: intentKey,
3373
+ source: { kind: SOURCE_KIND.CART, cart_id: state.cart.id },
3374
+ checkout: {
3375
+ customer: customer,
3376
+ order_type: orderType,
3377
+ address_info: state.address || {},
3378
+ tender_preference: preference
3379
+ }
3193
3380
  })
3194
3381
  })
3195
- .then(function (r) { return r.json().then(function (b) { return { status: r.status, body: b }; }); })
3382
+ .then(responseWithBody)
3196
3383
  .then(function (resp) {
3197
- if (resp.status >= 400) {
3198
- var msg = (resp.body && resp.body.error && resp.body.error.message) || "Checkout failed";
3199
- send({ type: MSG.CHECKOUT_COMPLETE, success: false, error: { code: (resp.body.error && resp.body.error.code) || "CHECKOUT_FAILED", message: msg, recoverable: true } });
3200
- statusEl.textContent = "Failed";
3201
- errEl.textContent = msg;
3202
- return;
3384
+ const intent = assertSuccessfulResponse(resp, "Intent creation failed");
3385
+ const terms = intent.current_terms;
3386
+ const option = terms && terms.payment_options && terms.payment_options.filter(function (candidate) {
3387
+ return candidate.status === PURCHASE_INTENT.ELIGIBLE && candidate.method_kind === preference.method_kind;
3388
+ })[0];
3389
+ if (!terms || (!option && !isExactlyZeroMoney(terms.money.rail_amount))) {
3390
+ throw new Error("No eligible payment option");
3391
+ }
3392
+ const confirmationPath = PURCHASE_INTENT.PATH + "/" + encodeURIComponent(intent.id) + "/confirm";
3393
+ const confirmationBody = JSON.stringify({
3394
+ accepted_intent_revision: terms.intent_revision,
3395
+ accepted_terms_version: terms.terms_version,
3396
+ accepted_due_now: terms.money.due_now,
3397
+ accepted_customer_debit_amount: option
3398
+ ? option.customer_debit_amount
3399
+ : terms.money.rail_amount,
3400
+ currency: terms.money.currency,
3401
+ payment_option_id: option ? option.id : null,
3402
+ idempotency_key: "mock-confirm:" + intent.id
3403
+ });
3404
+ function confirmIntent() {
3405
+ return fetch(confirmationPath, {
3406
+ method: "POST",
3407
+ headers: headers,
3408
+ body: confirmationBody
3409
+ })
3410
+ .then(responseWithBody)
3411
+ .then(function (response) {
3412
+ return assertSuccessfulResponse(response, "Intent confirmation failed");
3413
+ });
3414
+ }
3415
+
3416
+ return confirmIntent().then(function (outcome) {
3417
+ // This mock has no external provider window. Replaying the exact
3418
+ // idempotent confirmation models the provider-approved callback.
3419
+ return outcome.status === PURCHASE_INTENT.CARD_POPUP_REQUIRED
3420
+ ? confirmIntent()
3421
+ : outcome;
3422
+ });
3423
+ })
3424
+ .then(function (outcome) {
3425
+ if (outcome.status !== PURCHASE_INTENT.AUTHORIZATION_REQUIRED) return outcome;
3426
+ return fetch(
3427
+ PURCHASE_INTENT.PATH + "/" + encodeURIComponent(outcome.intent_id) +
3428
+ "/attempts/" + encodeURIComponent(outcome.attempt_id) + "/actions",
3429
+ {
3430
+ method: "POST",
3431
+ headers: headers,
3432
+ body: JSON.stringify({ authorization: { type: AUTHORIZATION.OTP, value: DEMO_OTP } })
3433
+ }
3434
+ )
3435
+ .then(responseWithBody)
3436
+ .then(function (response) {
3437
+ return assertSuccessfulResponse(response, "Authorization failed");
3438
+ });
3439
+ })
3440
+ .then(function (outcome) {
3441
+ if (outcome.status !== PURCHASE_INTENT.ORDER_CREATED) {
3442
+ throw new Error("Checkout requires " + outcome.status.replace(/_/g, " "));
3203
3443
  }
3204
- var b = resp.body;
3205
- send({ type: MSG.CHECKOUT_STATUS, status: "success", context: { order_id: b.order_id, order_number: b.order_number, provider: b.provider } });
3444
+ send({
3445
+ type: MSG.CHECKOUT_STATUS,
3446
+ status: CHECKOUT_STATUS.SUCCESS,
3447
+ context: { order_id: outcome.order_id }
3448
+ });
3206
3449
  send({
3207
3450
  type: MSG.CHECKOUT_COMPLETE,
3208
3451
  success: true,
3209
3452
  order: {
3210
- id: b.order_id,
3211
- order_number: b.order_number,
3212
- status: b.requires_authorization ? "pending" : "confirmed",
3453
+ id: outcome.order_id,
3454
+ order_number: outcome.order_number || outcome.order_id,
3455
+ status: ORDER_STATUS.CONFIRMED,
3213
3456
  total: (state.cart && state.cart.total_price) || "0.00",
3214
3457
  currency: (state.cart && state.cart.currency) || "GHS"
3215
3458
  }
3216
3459
  });
3217
- statusEl.textContent = "Success \u2014 order " + b.order_number;
3460
+ statusEl.textContent = "Success \u2014 order " + outcome.order_id;
3218
3461
  resultEl.style.display = "block";
3219
- resultEl.textContent = JSON.stringify(b, null, 2);
3462
+ resultEl.textContent = JSON.stringify(outcome, null, 2);
3220
3463
  })
3221
3464
  .catch(function (e) {
3222
- send({ type: MSG.CHECKOUT_COMPLETE, success: false, error: { code: "NETWORK", message: String(e), recoverable: true } });
3223
- statusEl.textContent = "Network error";
3465
+ send({
3466
+ type: MSG.CHECKOUT_COMPLETE,
3467
+ success: false,
3468
+ error: { code: CHECKOUT_ERROR.FAILED, message: String(e), recoverable: true }
3469
+ });
3470
+ statusEl.textContent = "Failed";
3224
3471
  errEl.textContent = String(e);
3225
3472
  });
3226
3473
  }
@@ -3237,7 +3484,7 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3237
3484
  break;
3238
3485
  case MSG.SET_CART:
3239
3486
  state.cart = msg.cart;
3240
- var s = document.getElementById("status");
3487
+ const s = document.getElementById("status");
3241
3488
  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");
3242
3489
  reportHeight();
3243
3490
  break;
@@ -3261,7 +3508,7 @@ var ELEMENT_HANDLER_JS = `/* eslint-disable */
3261
3508
  }
3262
3509
  break;
3263
3510
  case MSG.ABORT_CHECKOUT:
3264
- send({ type: MSG.CHECKOUT_STATUS, status: "failed", context: {} });
3511
+ send({ type: MSG.CHECKOUT_STATUS, status: CHECKOUT_STATUS.FAILED, context: {} });
3265
3512
  break;
3266
3513
  }
3267
3514
  }
@@ -3332,9 +3579,10 @@ function buildLink(deps) {
3332
3579
  app.post("/auth/request-otp", async (c) => {
3333
3580
  const body = await c.req.json().catch(() => ({}));
3334
3581
  return tryRoute(c, () => {
3335
- deps.auth.requestOtp(body.contact ?? "");
3582
+ const challenge = deps.auth.requestOtp(body.contact ?? "");
3336
3583
  return {
3337
3584
  success: true,
3585
+ challenge_id: challenge.otp_id,
3338
3586
  message: `OTP sent to ${body.contact ?? "contact"}`,
3339
3587
  expires_in: 300,
3340
3588
  is_new_account: false
@@ -3344,7 +3592,11 @@ function buildLink(deps) {
3344
3592
  app.post("/auth/verify-otp", async (c) => {
3345
3593
  const body = await c.req.json().catch(() => ({}));
3346
3594
  return tryRoute(c, () => {
3347
- const session = deps.auth.verifyOtp(body.contact ?? "", body.otp_code ?? "");
3595
+ const session = deps.auth.verifyOtp(
3596
+ body.contact ?? "",
3597
+ body.otp_code ?? "",
3598
+ body.challenge_id
3599
+ );
3348
3600
  c.header("x-session-token", session.token);
3349
3601
  const customer = deps.link.ensureCustomer(session.customer_id ?? session.id, {
3350
3602
  email: body.contact?.includes("@") ? body.contact : void 0,
@@ -3438,10 +3690,7 @@ function buildLink(deps) {
3438
3690
  };
3439
3691
  });
3440
3692
  });
3441
- app.get(
3442
- "/preferences",
3443
- (c) => tryRoute(c, () => deps.link.getPreferences(customerId(c)))
3444
- );
3693
+ app.get("/preferences", (c) => tryRoute(c, () => deps.link.getPreferences(customerId(c))));
3445
3694
  app.post("/preferences", async (c) => {
3446
3695
  const body = await c.req.json().catch(() => ({}));
3447
3696
  return tryRoute(c, () => {
@@ -3873,6 +4122,7 @@ function createAuthService(opts) {
3873
4122
  token: id,
3874
4123
  business_id: options.defaultBusinessId,
3875
4124
  is_authenticated: authenticated,
4125
+ account_id: authenticated ? ids.raw("account") : void 0,
3876
4126
  customer_id: authenticated ? ids.customer() : void 0,
3877
4127
  customer_name: profile?.name,
3878
4128
  customer_email: profile?.email,
@@ -3918,9 +4168,16 @@ function createAuthService(opts) {
3918
4168
  code_hint: options.mode === "permissive" ? code : void 0
3919
4169
  };
3920
4170
  },
3921
- verifyOtp(contact, code) {
3922
- const matching = registry.otps.list((o) => o.contact === contact);
3923
- const otp = matching[matching.length - 1];
4171
+ verifyOtp(contact, code, challengeId) {
4172
+ let otp = challengeId ? registry.otps.get(challengeId) : void 0;
4173
+ if (!challengeId) {
4174
+ const matching = registry.otps.list((o) => o.contact === contact);
4175
+ otp = matching[matching.length - 1];
4176
+ }
4177
+ if (challengeId) {
4178
+ if (!otp) throw new Error("No OTP challenge found");
4179
+ if (otp.contact !== contact) throw new Error("OTP challenge does not match contact");
4180
+ }
3924
4181
  if (options.mode === "strict") {
3925
4182
  if (!otp) throw new Error("No OTP requested");
3926
4183
  if (otp.code !== code && code !== options.defaultOtp) throw new Error("Invalid OTP");
@@ -3948,7 +4205,7 @@ function createAuthService(opts) {
3948
4205
  if (!s) return { is_authenticated: false, user_type: "guest" };
3949
4206
  return {
3950
4207
  is_authenticated: s.is_authenticated,
3951
- account_id: s.customer_id,
4208
+ account_id: s.account_id,
3952
4209
  user_type: s.is_authenticated ? "customer" : "guest",
3953
4210
  session_expires_at: s.expires_at ? Math.floor(new Date(s.expires_at).getTime() / 1e3) : void 0,
3954
4211
  session: s
@@ -5246,88 +5503,10 @@ function createCartService(opts) {
5246
5503
  };
5247
5504
  }
5248
5505
 
5249
- // src/mock/domain/checkout.ts
5250
- function createCheckoutService(opts) {
5251
- const { registry, clock, ids, bus} = opts;
5506
+ // src/mock/domain/payment.ts
5507
+ function createPaymentService(options) {
5508
+ const { registry, clock, bus } = options;
5252
5509
  return {
5253
- process(session, body) {
5254
- if (!body.cart_id) throw validation("cart_id required");
5255
- const c = registry.carts.get(body.cart_id);
5256
- if (!c) throw notFound(`Cart ${body.cart_id} not found`);
5257
- if (c.items.length === 0) throw validation("Cart is empty", { code: "CART_EMPTY" });
5258
- const orderId = ids.order();
5259
- const orderNumber = ids.orderNumber();
5260
- const paymentId = ids.payment();
5261
- const reference = ids.payment();
5262
- const requiresAuth = body.payment_method === "mobile_money";
5263
- const isCard = body.payment_method === "card" || body.payment_method === "stripe";
5264
- const cardProvider = body.payment_method === "stripe" || body.pay_currency?.toUpperCase() === "USD" ? "stripe" : "paystack";
5265
- const order = {
5266
- id: orderId,
5267
- business_id: c.business_id,
5268
- user_friendly_id: orderNumber,
5269
- channel: c.channel,
5270
- status: requiresAuth ? "pending" : "confirmed",
5271
- payment_state: requiresAuth ? "not_paid" : "paid",
5272
- order_type: body.order_type,
5273
- customer_id: session.customer_id,
5274
- customer_name: body.customer.name,
5275
- customer_email: body.customer.email,
5276
- customer_phone: body.customer.phone,
5277
- delivery_address: body.address_info?.street_address,
5278
- delivery_fee: c.delivery_fee,
5279
- subtotal: c.subtotal,
5280
- tax_amount: c.tax_amount,
5281
- service_charge: c.service_charge,
5282
- total_discounts: c.total_discounts,
5283
- total_price: c.total_price,
5284
- currency: c.currency,
5285
- items: c.items,
5286
- applied_discount_ids: c.applied_discount_ids,
5287
- applied_discount_codes: c.applied_discount_codes,
5288
- payment_id: paymentId,
5289
- payment_reference: reference,
5290
- metadata: body.metadata,
5291
- created_at: clock.iso(),
5292
- updated_at: clock.iso()
5293
- };
5294
- registry.orders.put(orderId, order);
5295
- registry.carts.put(c.id, { ...c, status: "converted", updated_at: clock.iso() });
5296
- bus.emit("order.created", { order_id: orderId, order_number: orderNumber }, c.business_id);
5297
- if (!requiresAuth) {
5298
- bus.emit("order.payment.captured", { order_id: orderId, reference }, c.business_id);
5299
- bus.emit("order.confirmed", { order_id: orderId }, c.business_id);
5300
- }
5301
- const billToken = `bt_${reference.slice(-12)}_${Math.random().toString(36).slice(2, 10)}`;
5302
- const result = {
5303
- order_id: orderId,
5304
- order_number: orderNumber,
5305
- payment_id: paymentId,
5306
- payment_status: requiresAuth || isCard ? "pending" : "succeeded",
5307
- payment_reference: reference,
5308
- requires_authorization: requiresAuth,
5309
- authorization_type: requiresAuth ? "otp" : void 0,
5310
- next_action: requiresAuth ? {
5311
- type: "authorization",
5312
- authorization_type: "otp",
5313
- display_text: "Approve on your mobile money app"
5314
- } : { type: "none" },
5315
- provider: isCard ? cardProvider : body.payment_method,
5316
- bill_token: billToken
5317
- };
5318
- if (isCard) {
5319
- const proc = globalThis.process;
5320
- result.client_secret = cardProvider === "stripe" ? `pi_${orderId.slice(-12)}_secret_${Math.random().toString(36).slice(2, 18)}` : `access_${reference}`;
5321
- 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";
5322
- result.next_action = {
5323
- type: "card_popup",
5324
- provider: cardProvider,
5325
- client_secret: result.client_secret,
5326
- public_key: result.public_key
5327
- };
5328
- }
5329
- return result;
5330
- },
5331
5510
  authorize(body) {
5332
5511
  if (!body.payment_id?.trim()) throw validation("payment_id required");
5333
5512
  if (!body.authorization) throw validation("authorization required");
@@ -5338,7 +5517,7 @@ function createCheckoutService(opts) {
5338
5517
  const updated = {
5339
5518
  ...order,
5340
5519
  payment_state: "paid",
5341
- status: "confirmed",
5520
+ status: chunkEV2EVOYS_js.CHECKOUT_ORDER_RESULT_STATUS.CONFIRMED,
5342
5521
  updated_at: clock.iso()
5343
5522
  };
5344
5523
  registry.orders.put(order.id, updated);
@@ -5349,14 +5528,542 @@ function createCheckoutService(opts) {
5349
5528
  order_number: order.user_friendly_id,
5350
5529
  payment_id: body.payment_id,
5351
5530
  payment_reference: order.payment_reference,
5352
- payment_status: "succeeded",
5531
+ payment_status: chunkSFUJMS5E_js.LEGACY_CHECKOUT_PAYMENT_STATUS.SUCCEEDED,
5353
5532
  requires_authorization: false,
5354
- next_action: { type: "none" }
5533
+ next_action: { type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.NONE }
5355
5534
  };
5356
5535
  }
5357
5536
  };
5358
5537
  }
5359
5538
 
5539
+ // src/mock/domain/purchase-intent.ts
5540
+ var INTENT_LIFETIME_MS = 15 * 60 * 1e3;
5541
+ var ZERO_MONEY = "0.00";
5542
+ var PURCHASE_INTENT_MOBILE_MONEY_NETWORKS = new Set(
5543
+ Object.values(chunkSFUJMS5E_js.PURCHASE_INTENT_MOBILE_MONEY_NETWORK)
5544
+ );
5545
+ var MOCK_PURCHASE_INTENT = {
5546
+ OWNER_KIND: { ACCOUNT: "account", STOREFRONT_SESSION: "storefront_session" },
5547
+ CART_STATUS: { ACTIVE: "active", CONVERTED: "converted" },
5548
+ ORDER_STATUS: { PENDING: "pending", CONFIRMED: "confirmed" },
5549
+ PAYMENT_STATE: { NOT_PAID: "not_paid", PAID: "paid" },
5550
+ EVENT: {
5551
+ ORDER_CREATED: "order.created",
5552
+ PAYMENT_CAPTURED: "order.payment.captured",
5553
+ ORDER_CONFIRMED: "order.confirmed"
5554
+ },
5555
+ ID_PREFIX: { INTENT: "pi", ATTEMPT: "attempt" },
5556
+ DEFAULT_LOCATION_ID: "mock-location",
5557
+ MOCK_PAYSTACK_PUBLIC_KEY: "pk_test_mock_paystack",
5558
+ COMPLIANCE: {
5559
+ POLICY_NAME: "mock-storefront-commerce"
5560
+ }
5561
+ };
5562
+ var DECIMAL_WIRE_VALUE = /^([+-]?)(\d+)(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
5563
+ function isExactlyZero(value) {
5564
+ if (typeof value === "number") return Object.is(value, 0) || Object.is(value, -0);
5565
+ const match2 = DECIMAL_WIRE_VALUE.exec(value.trim());
5566
+ return Boolean(match2 && [...match2[2], ...match2[3] ?? ""].every((digit) => digit === "0"));
5567
+ }
5568
+ function sameDecimal(left, right) {
5569
+ const canonical = (value) => {
5570
+ const wire = typeof value === "number" ? String(value) : value.trim();
5571
+ const match2 = DECIMAL_WIRE_VALUE.exec(wire);
5572
+ if (!match2) return null;
5573
+ let digits = `${match2[2]}${match2[3] ?? ""}`.replace(/^0+/, "");
5574
+ if (!digits) return "0";
5575
+ let scale = BigInt((match2[3] ?? "").length) - BigInt(match2[4] ?? "0");
5576
+ while (digits.endsWith("0")) {
5577
+ digits = digits.slice(0, -1);
5578
+ scale -= 1n;
5579
+ }
5580
+ const sign = match2[1] === "-" ? "-" : "";
5581
+ return `${sign}${digits}:${scale}`;
5582
+ };
5583
+ const normalizedLeft = canonical(left);
5584
+ return normalizedLeft !== null && normalizedLeft === canonical(right);
5585
+ }
5586
+ function wireMoney(value) {
5587
+ return typeof value === "string" ? value.trim() : String(value);
5588
+ }
5589
+ function decimal(value) {
5590
+ return wireMoney(value.toFixed(2));
5591
+ }
5592
+ function paymentOptions(intentId, currency, amount, expiresAt) {
5593
+ const normalizedCurrency = chunkSFUJMS5E_js.currencyCode(currency);
5594
+ const normalizedAmount = wireMoney(amount);
5595
+ return [
5596
+ {
5597
+ id: `${intentId}:${chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD}`,
5598
+ rank: 0,
5599
+ method_kind: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD,
5600
+ collection_mode: chunkSFUJMS5E_js.PAYMENT_COLLECTION_MODE.CREDENTIAL_CHARGE,
5601
+ provider: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_PROVIDER.PAYSTACK,
5602
+ principal_amount: normalizedAmount,
5603
+ fee_amount: wireMoney(ZERO_MONEY),
5604
+ customer_debit_amount: normalizedAmount,
5605
+ currency: normalizedCurrency,
5606
+ status: chunkSFUJMS5E_js.PAYMENT_OPTION_STATUS.ELIGIBLE,
5607
+ expected_next_action: chunkSFUJMS5E_js.PAYMENT_OPTION_NEXT_ACTION.PROVIDER_APPROVAL,
5608
+ expires_at: expiresAt
5609
+ },
5610
+ {
5611
+ id: `${intentId}:${chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY}`,
5612
+ rank: 1,
5613
+ method_kind: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY,
5614
+ collection_mode: chunkSFUJMS5E_js.PAYMENT_COLLECTION_MODE.REQUEST_TO_PAY,
5615
+ provider: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_PROVIDER.PAYSTACK,
5616
+ principal_amount: normalizedAmount,
5617
+ fee_amount: wireMoney(ZERO_MONEY),
5618
+ customer_debit_amount: normalizedAmount,
5619
+ currency: normalizedCurrency,
5620
+ status: chunkSFUJMS5E_js.PAYMENT_OPTION_STATUS.ELIGIBLE,
5621
+ expected_next_action: chunkSFUJMS5E_js.PAYMENT_OPTION_NEXT_ACTION.PROVIDER_APPROVAL,
5622
+ expires_at: expiresAt
5623
+ }
5624
+ ];
5625
+ }
5626
+ function termsForCart(input) {
5627
+ const total = wireMoney(input.total);
5628
+ return {
5629
+ id: `${input.intentId}:terms:${input.version}`,
5630
+ intent_revision: input.revision,
5631
+ terms_version: input.version,
5632
+ terms_digest: `mock:${input.intentId}:${input.revision}:${input.version}`,
5633
+ money: {
5634
+ currency: chunkSFUJMS5E_js.currencyCode(input.currency),
5635
+ subtotal: wireMoney(input.subtotal),
5636
+ discount_total: wireMoney(input.discount),
5637
+ tax_total: wireMoney(input.tax),
5638
+ delivery_total: wireMoney(input.delivery),
5639
+ statutory_total: wireMoney(ZERO_MONEY),
5640
+ total_obligation: total,
5641
+ due_now: total,
5642
+ rail_amount: total,
5643
+ store_credit_consumed: wireMoney(ZERO_MONEY),
5644
+ voucher_credit_consumed: wireMoney(ZERO_MONEY)
5645
+ },
5646
+ material: {
5647
+ line_digest: `mock-lines:${input.intentId}`,
5648
+ destination_digest: `mock-destination:${input.intentId}`,
5649
+ delivery_promise_digest: `mock-delivery:${input.intentId}`,
5650
+ entitlement_digest: `mock-entitlement:${input.intentId}`,
5651
+ cancellation_terms_digest: `mock-cancellation:${input.intentId}`
5652
+ },
5653
+ compliance: {
5654
+ policy_name: MOCK_PURCHASE_INTENT.COMPLIANCE.POLICY_NAME,
5655
+ policy_version: 1,
5656
+ lane: chunkSFUJMS5E_js.CHECKOUT_COMPLIANCE_LANE.NATIVE,
5657
+ reason_code: chunkSFUJMS5E_js.CHECKOUT_COMPLIANCE_REASON.PHYSICAL_GOODS_NATIVE,
5658
+ evidence_digest: `mock-compliance:${input.intentId}`
5659
+ },
5660
+ payment_options: isExactlyZero(input.total) ? [] : paymentOptions(input.intentId, input.currency, input.total, input.validUntil),
5661
+ valid_until: input.validUntil,
5662
+ created_at: input.now
5663
+ };
5664
+ }
5665
+ function intentView(intent) {
5666
+ const {
5667
+ intent_owner: _owner,
5668
+ mint_request: _request,
5669
+ last_confirmation: _confirmation,
5670
+ ...view
5671
+ } = intent;
5672
+ return view;
5673
+ }
5674
+ function purchasingPrincipal(session) {
5675
+ if (!session.is_authenticated) {
5676
+ return { kind: chunkSFUJMS5E_js.PURCHASING_PRINCIPAL_KIND.GUEST };
5677
+ }
5678
+ if (!session.account_id) throw validation("Authenticated mock session has no account authority");
5679
+ return {
5680
+ kind: chunkSFUJMS5E_js.PURCHASING_PRINCIPAL_KIND.ACCOUNT,
5681
+ account_id: session.account_id
5682
+ };
5683
+ }
5684
+ function assertSupportedTenderPreference(request) {
5685
+ if (request.source.kind !== chunkSFUJMS5E_js.PURCHASE_INTENT_SOURCE_KIND.CART) return;
5686
+ const checkout = request.checkout;
5687
+ if (!checkout) throw validation("Cart checkout input is required");
5688
+ const preference = checkout.tender_preference;
5689
+ if (preference?.method_kind !== chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY || preference.authority.authority_kind !== chunkSFUJMS5E_js.MOBILE_MONEY_TENDER_AUTHORITY_KIND.TRANSIENT) {
5690
+ return;
5691
+ }
5692
+ if (!PURCHASE_INTENT_MOBILE_MONEY_NETWORKS.has(preference.authority.network)) {
5693
+ throw validation("Mobile Money network is not available for PurchaseIntent checkout");
5694
+ }
5695
+ }
5696
+ function intentOwner(session) {
5697
+ if (!session.is_authenticated) {
5698
+ return { kind: MOCK_PURCHASE_INTENT.OWNER_KIND.STOREFRONT_SESSION, id: session.id };
5699
+ }
5700
+ if (!session.account_id) throw validation("Authenticated mock session has no account authority");
5701
+ return { kind: MOCK_PURCHASE_INTENT.OWNER_KIND.ACCOUNT, id: session.account_id };
5702
+ }
5703
+ function createPurchaseIntentMockService(options) {
5704
+ const { registry, clock, ids, bus } = options;
5705
+ function stored(session, intentId) {
5706
+ const intent = registry.purchaseIntents.get(intentId);
5707
+ if (!intent) throw notFound(`Purchase intent ${intentId} not found`);
5708
+ const owner = intentOwner(session);
5709
+ if (intent.intent_owner.kind !== owner.kind || intent.intent_owner.id !== owner.id) {
5710
+ throw notFound(`Purchase intent ${intentId} not found`);
5711
+ }
5712
+ return intent;
5713
+ }
5714
+ function completeProviderOrder(intent, order, attemptId) {
5715
+ const updated = {
5716
+ ...order,
5717
+ payment_state: MOCK_PURCHASE_INTENT.PAYMENT_STATE.PAID,
5718
+ status: MOCK_PURCHASE_INTENT.ORDER_STATUS.CONFIRMED,
5719
+ updated_at: clock.iso()
5720
+ };
5721
+ registry.orders.put(order.id, updated);
5722
+ bus.emit(
5723
+ MOCK_PURCHASE_INTENT.EVENT.PAYMENT_CAPTURED,
5724
+ { order_id: order.id, reference: order.payment_reference },
5725
+ order.business_id
5726
+ );
5727
+ bus.emit(MOCK_PURCHASE_INTENT.EVENT.ORDER_CONFIRMED, { order_id: order.id }, order.business_id);
5728
+ const completed = {
5729
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED,
5730
+ intent_id: intent.id,
5731
+ attempt_id: attemptId,
5732
+ order_id: order.id,
5733
+ order_number: order.user_friendly_id,
5734
+ payment_id: order.payment_id
5735
+ };
5736
+ registry.purchaseIntents.put(intent.id, {
5737
+ ...intent,
5738
+ updated_at: clock.iso(),
5739
+ last_confirmation: completed
5740
+ });
5741
+ return completed;
5742
+ }
5743
+ return {
5744
+ mint(session, request) {
5745
+ if (!request.client_intent_key.trim()) throw validation("client_intent_key required");
5746
+ if (request.source.kind !== chunkSFUJMS5E_js.PURCHASE_INTENT_SOURCE_KIND.CART) {
5747
+ throw validation("The mock currently prepares cart purchase intents only");
5748
+ }
5749
+ const checkoutInput = request.checkout;
5750
+ if (!checkoutInput) throw validation("Cart checkout input is required");
5751
+ assertSupportedTenderPreference(request);
5752
+ const cart = registry.carts.get(request.source.cart_id);
5753
+ if (!cart) throw notFound(`Cart ${request.source.cart_id} not found`);
5754
+ if (cart.items.length === 0) {
5755
+ throw validation("Cart is empty", { code: chunkSFUJMS5E_js.ErrorCode.CART_EMPTY });
5756
+ }
5757
+ const principal = purchasingPrincipal(session);
5758
+ const owner = intentOwner(session);
5759
+ const existing = registry.purchaseIntents.list(
5760
+ (candidate) => candidate.mint_request.client_intent_key === request.client_intent_key && candidate.intent_owner.kind === owner.kind && candidate.intent_owner.id === owner.id
5761
+ )[0];
5762
+ if (existing) return intentView(existing);
5763
+ const now = clock.iso();
5764
+ const expiresAt = new Date(clock.nowMs() + INTENT_LIFETIME_MS).toISOString();
5765
+ const intentId = ids.raw(MOCK_PURCHASE_INTENT.ID_PREFIX.INTENT);
5766
+ const terms = termsForCart({
5767
+ intentId,
5768
+ revision: 1,
5769
+ version: 1,
5770
+ currency: cart.currency,
5771
+ subtotal: cart.subtotal,
5772
+ discount: cart.total_discounts,
5773
+ tax: cart.tax_amount,
5774
+ delivery: cart.delivery_fee,
5775
+ total: cart.total_price,
5776
+ now,
5777
+ validUntil: expiresAt
5778
+ });
5779
+ const intent = {
5780
+ id: intentId,
5781
+ seller_business_id: cart.business_id,
5782
+ principal,
5783
+ revision: 1,
5784
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_STATUS.OPEN,
5785
+ source: {
5786
+ kind: chunkSFUJMS5E_js.PURCHASE_INTENT_SOURCE_KIND.CART,
5787
+ source_id: cart.id,
5788
+ source_version: cart.updated_at,
5789
+ seller_business_id: cart.business_id,
5790
+ subject: {
5791
+ kind: chunkSFUJMS5E_js.PURCHASING_PRINCIPAL_KIND.BUSINESS,
5792
+ business_id: cart.business_id
5793
+ },
5794
+ binding_digest: `mock-cart:${cart.id}:${cart.updated_at}`
5795
+ },
5796
+ lines: cart.items.map((line, ordinal) => ({
5797
+ id: line.id,
5798
+ ordinal,
5799
+ sellable: {
5800
+ kind: line.variant_id ? chunkSFUJMS5E_js.PURCHASE_INTENT_SELLABLE_KIND.VARIANT : chunkSFUJMS5E_js.PURCHASE_INTENT_SELLABLE_KIND.PRODUCT,
5801
+ product_id: line.item_id,
5802
+ variant_id: line.variant_id,
5803
+ location_id: checkoutInput.location_id || MOCK_PURCHASE_INTENT.DEFAULT_LOCATION_ID
5804
+ },
5805
+ quantity: line.quantity,
5806
+ configuration: {
5807
+ kind: chunkSFUJMS5E_js.PURCHASE_INTENT_LINE_CONFIGURATION_KIND.SIMPLE,
5808
+ variant_id: line.variant_id,
5809
+ customer_inputs: line.customer_inputs
5810
+ }
5811
+ })),
5812
+ line_pricing: cart.items.map((line) => {
5813
+ const unitPrice = Number(line.price) + Number(line.add_ons_price);
5814
+ const lineSubtotal = unitPrice * line.quantity - Number(line.item_discount_amount);
5815
+ return {
5816
+ intent_line_id: line.id,
5817
+ quantity: line.quantity,
5818
+ unit_price: decimal(unitPrice),
5819
+ line_subtotal: decimal(lineSubtotal),
5820
+ currency: chunkSFUJMS5E_js.currencyCode(cart.currency)
5821
+ };
5822
+ }),
5823
+ current_terms: terms,
5824
+ expires_at: expiresAt,
5825
+ created_at: now,
5826
+ updated_at: now,
5827
+ intent_owner: owner,
5828
+ mint_request: request
5829
+ };
5830
+ registry.purchaseIntents.put(intentId, intent);
5831
+ return intentView(intent);
5832
+ },
5833
+ get(session, intentId) {
5834
+ return intentView(stored(session, intentId));
5835
+ },
5836
+ refresh(session, intentId, expectedRevision) {
5837
+ const intent = stored(session, intentId);
5838
+ if (intent.revision !== expectedRevision) {
5839
+ throw validation("expected_intent_revision does not match current intent revision");
5840
+ }
5841
+ if (!intent.current_terms) throw validation("Purchase intent has no current terms");
5842
+ const previous = intent.current_terms;
5843
+ const nextDelivery = Number(previous.money.delivery_total) + 1;
5844
+ const nextTotal = Number(previous.money.total_obligation) + 1;
5845
+ const now = clock.iso();
5846
+ const replacement = termsForCart({
5847
+ intentId,
5848
+ revision: intent.revision,
5849
+ version: previous.terms_version + 1,
5850
+ currency: previous.money.currency,
5851
+ subtotal: String(previous.money.subtotal),
5852
+ discount: String(previous.money.discount_total),
5853
+ tax: String(previous.money.tax_total),
5854
+ delivery: nextDelivery.toFixed(2),
5855
+ total: nextTotal.toFixed(2),
5856
+ now,
5857
+ validUntil: intent.expires_at
5858
+ });
5859
+ const updated = { ...intent, current_terms: replacement, updated_at: now };
5860
+ registry.purchaseIntents.put(intentId, updated);
5861
+ return intentView(updated);
5862
+ },
5863
+ confirm(session, intentId, request) {
5864
+ const intent = stored(session, intentId);
5865
+ if (intent.status === chunkSFUJMS5E_js.PURCHASE_INTENT_STATUS.CONVERTED && intent.last_confirmation) {
5866
+ const orderId2 = "order_id" in intent.last_confirmation ? intent.last_confirmation.order_id : void 0;
5867
+ const order2 = orderId2 ? registry.orders.get(orderId2) : void 0;
5868
+ if (order2?.payment_state === MOCK_PURCHASE_INTENT.PAYMENT_STATE.PAID) {
5869
+ return {
5870
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED,
5871
+ intent_id: intent.id,
5872
+ attempt_id: "attempt_id" in intent.last_confirmation ? intent.last_confirmation.attempt_id : ids.raw(MOCK_PURCHASE_INTENT.ID_PREFIX.ATTEMPT),
5873
+ order_id: order2.id
5874
+ };
5875
+ }
5876
+ if (order2?.payment_id && intent.last_confirmation.status === chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED) {
5877
+ return completeProviderOrder(intent, order2, intent.last_confirmation.attempt_id);
5878
+ }
5879
+ return intent.last_confirmation;
5880
+ }
5881
+ const terms = intent.current_terms;
5882
+ if (!terms) throw validation("Purchase intent has no current terms");
5883
+ const zeroRail = isExactlyZero(terms.money.rail_amount);
5884
+ const option = request.payment_option_id ? terms.payment_options.find(
5885
+ (candidate) => candidate.id === request.payment_option_id && candidate.status === chunkSFUJMS5E_js.PAYMENT_OPTION_STATUS.ELIGIBLE
5886
+ ) : void 0;
5887
+ const acceptedBaseTermsChanged = !sameDecimal(request.accepted_due_now, terms.money.due_now) || request.currency !== terms.money.currency;
5888
+ if (request.accepted_intent_revision !== intent.revision || request.accepted_terms_version !== terms.terms_version || acceptedBaseTermsChanged) {
5889
+ const deltas = acceptedBaseTermsChanged ? [
5890
+ {
5891
+ kind: chunkSFUJMS5E_js.CHECKOUT_TERMS_DELTA_KIND.MONEY,
5892
+ component: chunkSFUJMS5E_js.CHECKOUT_TERMS_COMPONENT.DUE_NOW,
5893
+ accepted: request.accepted_due_now,
5894
+ replacement: terms.money.due_now
5895
+ }
5896
+ ] : [
5897
+ {
5898
+ kind: chunkSFUJMS5E_js.CHECKOUT_TERMS_DELTA_KIND.PAYMENT_OPTION,
5899
+ accepted_option_id: request.payment_option_id ?? null,
5900
+ accepted_customer_debit_amount: request.accepted_customer_debit_amount,
5901
+ replacement_option_id: option?.id ?? null,
5902
+ replacement_customer_debit_amount: option?.customer_debit_amount ?? null
5903
+ }
5904
+ ];
5905
+ return {
5906
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED,
5907
+ intent_id: intent.id,
5908
+ replacement: terms,
5909
+ deltas
5910
+ };
5911
+ }
5912
+ if (!zeroRail && !option || zeroRail && request.payment_option_id != null) {
5913
+ return {
5914
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.SELECTION_UNAVAILABLE,
5915
+ intent_id: intent.id,
5916
+ lines: intent.lines.map((line) => ({
5917
+ line_id: line.id,
5918
+ reason: chunkSFUJMS5E_js.CHECKOUT_INVALIDATION_REASON.PAYMENT_OPTION_CHANGED
5919
+ }))
5920
+ };
5921
+ }
5922
+ const acceptedCustomerDebitMatches = zeroRail ? isExactlyZero(request.accepted_customer_debit_amount) : Boolean(
5923
+ option && sameDecimal(request.accepted_customer_debit_amount, option.customer_debit_amount)
5924
+ );
5925
+ if (!acceptedCustomerDebitMatches) {
5926
+ return {
5927
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED,
5928
+ intent_id: intent.id,
5929
+ replacement: terms,
5930
+ deltas: [
5931
+ {
5932
+ kind: chunkSFUJMS5E_js.CHECKOUT_TERMS_DELTA_KIND.PAYMENT_OPTION,
5933
+ accepted_option_id: request.payment_option_id ?? null,
5934
+ accepted_customer_debit_amount: request.accepted_customer_debit_amount,
5935
+ replacement_option_id: option?.id ?? null,
5936
+ replacement_customer_debit_amount: option?.customer_debit_amount ?? null
5937
+ }
5938
+ ]
5939
+ };
5940
+ }
5941
+ if (intent.mint_request.source.kind !== chunkSFUJMS5E_js.PURCHASE_INTENT_SOURCE_KIND.CART) {
5942
+ throw validation("The mock currently confirms cart purchase intents only");
5943
+ }
5944
+ const checkoutInput = intent.mint_request.checkout;
5945
+ if (!checkoutInput) throw validation("Cart checkout input is required");
5946
+ const cart = registry.carts.get(intent.mint_request.source.cart_id);
5947
+ if (!cart || cart.status !== MOCK_PURCHASE_INTENT.CART_STATUS.ACTIVE) {
5948
+ return { status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.SOURCE_UNAVAILABLE, intent_id: intent.id };
5949
+ }
5950
+ const attemptId = ids.raw(MOCK_PURCHASE_INTENT.ID_PREFIX.ATTEMPT);
5951
+ const orderId = ids.order();
5952
+ const orderNumber = ids.orderNumber();
5953
+ const paymentId = zeroRail ? void 0 : ids.payment();
5954
+ const paymentReference = zeroRail ? void 0 : ids.payment();
5955
+ const needsProvider = option?.method_kind === chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD || option?.method_kind === chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY;
5956
+ const paid = zeroRail;
5957
+ const order = {
5958
+ id: orderId,
5959
+ business_id: cart.business_id,
5960
+ user_friendly_id: orderNumber,
5961
+ channel: cart.channel,
5962
+ status: paid ? MOCK_PURCHASE_INTENT.ORDER_STATUS.CONFIRMED : MOCK_PURCHASE_INTENT.ORDER_STATUS.PENDING,
5963
+ payment_state: paid ? MOCK_PURCHASE_INTENT.PAYMENT_STATE.PAID : MOCK_PURCHASE_INTENT.PAYMENT_STATE.NOT_PAID,
5964
+ order_type: checkoutInput.order_type,
5965
+ customer_id: session.customer_id,
5966
+ customer_name: checkoutInput.customer.name,
5967
+ customer_email: checkoutInput.customer.email,
5968
+ customer_phone: checkoutInput.customer.phone,
5969
+ delivery_address: checkoutInput.address_info.street_address,
5970
+ delivery_fee: cart.delivery_fee,
5971
+ subtotal: cart.subtotal,
5972
+ tax_amount: cart.tax_amount,
5973
+ service_charge: cart.service_charge,
5974
+ total_discounts: cart.total_discounts,
5975
+ total_price: cart.total_price,
5976
+ currency: cart.currency,
5977
+ items: cart.items,
5978
+ applied_discount_ids: cart.applied_discount_ids,
5979
+ applied_discount_codes: cart.applied_discount_codes,
5980
+ payment_id: paymentId,
5981
+ payment_reference: paymentReference,
5982
+ metadata: checkoutInput.metadata,
5983
+ created_at: clock.iso(),
5984
+ updated_at: clock.iso()
5985
+ };
5986
+ registry.orders.put(orderId, order);
5987
+ registry.carts.put(cart.id, {
5988
+ ...cart,
5989
+ status: MOCK_PURCHASE_INTENT.CART_STATUS.CONVERTED,
5990
+ updated_at: clock.iso()
5991
+ });
5992
+ bus.emit(
5993
+ MOCK_PURCHASE_INTENT.EVENT.ORDER_CREATED,
5994
+ { order_id: orderId, order_number: orderNumber },
5995
+ cart.business_id
5996
+ );
5997
+ if (paid) {
5998
+ if (paymentReference) {
5999
+ bus.emit(
6000
+ MOCK_PURCHASE_INTENT.EVENT.PAYMENT_CAPTURED,
6001
+ { order_id: orderId, reference: paymentReference },
6002
+ cart.business_id
6003
+ );
6004
+ }
6005
+ bus.emit(
6006
+ MOCK_PURCHASE_INTENT.EVENT.ORDER_CONFIRMED,
6007
+ { order_id: orderId },
6008
+ cart.business_id
6009
+ );
6010
+ }
6011
+ let confirmation;
6012
+ if (option?.method_kind === chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY) {
6013
+ confirmation = {
6014
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED,
6015
+ intent_id: intent.id,
6016
+ attempt_id: attemptId,
6017
+ order_id: orderId,
6018
+ authorization_type: chunkEV2EVOYS_js.AUTHORIZATION_TYPE.OTP,
6019
+ display_text: "Approve on your mobile money app"
6020
+ };
6021
+ } else if (option?.method_kind === chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD) {
6022
+ confirmation = {
6023
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED,
6024
+ intent_id: intent.id,
6025
+ attempt_id: attemptId,
6026
+ order_id: orderId,
6027
+ provider: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_PROVIDER.PAYSTACK,
6028
+ client_secret: `access_${paymentReference}`,
6029
+ public_key: MOCK_PURCHASE_INTENT.MOCK_PAYSTACK_PUBLIC_KEY
6030
+ };
6031
+ } else {
6032
+ confirmation = {
6033
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED,
6034
+ intent_id: intent.id,
6035
+ attempt_id: attemptId,
6036
+ order_id: orderId
6037
+ };
6038
+ }
6039
+ if (needsProvider && !paymentId) {
6040
+ throw validation("Provider-backed purchase intent has no payment authority");
6041
+ }
6042
+ registry.purchaseIntents.put(intent.id, {
6043
+ ...intent,
6044
+ status: chunkSFUJMS5E_js.PURCHASE_INTENT_STATUS.CONVERTED,
6045
+ converted_order_id: orderId,
6046
+ updated_at: clock.iso(),
6047
+ last_confirmation: confirmation
6048
+ });
6049
+ return confirmation;
6050
+ },
6051
+ submitAction(session, intentId, attemptId, request) {
6052
+ const intent = stored(session, intentId);
6053
+ const previous = intent.last_confirmation;
6054
+ if (!previous || previous.status !== chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED || previous.attempt_id !== attemptId) {
6055
+ throw validation("Purchase-intent attempt is not awaiting authorization");
6056
+ }
6057
+ if (!request.authorization) throw validation("authorization required");
6058
+ const order = registry.orders.get(previous.order_id);
6059
+ if (!order || !order.payment_id) {
6060
+ throw notFound(`Purchase-intent attempt ${attemptId} not found`);
6061
+ }
6062
+ return completeProviderOrder(intent, order, attemptId);
6063
+ }
6064
+ };
6065
+ }
6066
+
5360
6067
  // src/mock/domain/orders.ts
5361
6068
  function createOrderService(opts) {
5362
6069
  const { registry, clock, bus } = opts;
@@ -5735,6 +6442,7 @@ function createDeliveryService() {
5735
6442
  rate_id: "dlvrt_mock_standard",
5736
6443
  name: "Standard",
5737
6444
  fee: standardFree ? money(0) : money(15),
6445
+ fee_status: "priced",
5738
6446
  currency: "GHS",
5739
6447
  free_delivery_applied: standardFree,
5740
6448
  free_over_amount: money(200),
@@ -5748,6 +6456,7 @@ function createDeliveryService() {
5748
6456
  name: "Express",
5749
6457
  description: "Delivered within the hour",
5750
6458
  fee: money(25),
6459
+ fee_status: "priced",
5751
6460
  currency: "GHS",
5752
6461
  free_delivery_applied: false,
5753
6462
  eta_min_minutes: 30,
@@ -10644,7 +11353,7 @@ var ID_PREFIX = {
10644
11353
  product: "prod_",
10645
11354
  service: "svc_"
10646
11355
  };
10647
- var DEFAULT_CURRENCY = "GHS";
11356
+ var DEFAULT_CURRENCY2 = "GHS";
10648
11357
  function slugify(value) {
10649
11358
  return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
10650
11359
  }
@@ -10679,7 +11388,7 @@ function makeSeedContext(registry) {
10679
11388
  const business = {
10680
11389
  business_type: "other",
10681
11390
  email: `hello@${handle}.test`,
10682
- default_currency: DEFAULT_CURRENCY,
11391
+ default_currency: DEFAULT_CURRENCY2,
10683
11392
  default_offers_table_service: false,
10684
11393
  default_accepts_online_orders: true,
10685
11394
  status: "active",
@@ -10858,7 +11567,8 @@ function createDeps(options = {}) {
10858
11567
  const inventory = createInventoryService({ registry });
10859
11568
  const cart = createCartService({ registry, clock, ids, bus, inventory });
10860
11569
  const orders = createOrderService({ registry, clock, bus });
10861
- const checkout = createCheckoutService({ registry, clock, ids, bus});
11570
+ const payments = createPaymentService({ registry, clock, bus });
11571
+ const purchaseIntents = createPurchaseIntentMockService({ registry, clock, ids, bus });
10862
11572
  const subscriptions = createSubscriptionService({ registry, clock, bus });
10863
11573
  const scheduling = createSchedulingService({ registry, clock, bus });
10864
11574
  const fx = createFxService({ registry, clock, ids });
@@ -10879,7 +11589,8 @@ function createDeps(options = {}) {
10879
11589
  business,
10880
11590
  catalogue,
10881
11591
  cart,
10882
- checkout,
11592
+ payments,
11593
+ purchaseIntents,
10883
11594
  orders,
10884
11595
  subscriptions,
10885
11596
  scheduling,