@e22m4u/js-trie-router 0.5.0 → 0.5.2

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 (94) hide show
  1. package/dist/cjs/index.cjs +413 -265
  2. package/eslint.config.js +2 -0
  3. package/package.json +22 -16
  4. package/src/debuggable-service.d.ts +6 -0
  5. package/src/hooks/hook-invoker.d.ts +25 -0
  6. package/src/hooks/hook-invoker.js +18 -12
  7. package/src/hooks/hook-invoker.spec.js +18 -18
  8. package/src/hooks/hook-registry.d.ts +93 -0
  9. package/src/hooks/hook-registry.js +45 -19
  10. package/src/hooks/hook-registry.spec.js +2 -2
  11. package/src/hooks/index.d.ts +2 -0
  12. package/src/index.d.ts +9 -0
  13. package/src/index.js +1 -1
  14. package/src/parsers/body-parser.d.ts +52 -0
  15. package/src/parsers/body-parser.js +31 -17
  16. package/src/parsers/body-parser.spec.js +5 -5
  17. package/src/parsers/cookies-parser.d.ts +15 -0
  18. package/src/parsers/cookies-parser.js +2 -2
  19. package/src/parsers/index.d.ts +4 -0
  20. package/src/parsers/query-parser.d.ts +21 -0
  21. package/src/parsers/request-parser.d.ts +34 -0
  22. package/src/parsers/request-parser.js +5 -4
  23. package/src/parsers/request-parser.spec.js +3 -3
  24. package/src/request-context.d.ts +101 -0
  25. package/src/request-context.js +16 -13
  26. package/src/request-context.spec.js +4 -4
  27. package/src/route/index.d.ts +2 -0
  28. package/src/route/index.js +2 -0
  29. package/src/route/route.d.ts +105 -0
  30. package/src/{route.js → route/route.js} +15 -37
  31. package/src/{route.spec.js → route/route.spec.js} +163 -173
  32. package/src/route/validate-route-definition.d.ts +8 -0
  33. package/src/route/validate-route-definition.js +79 -0
  34. package/src/route/validate-route-definition.spec.js +220 -0
  35. package/src/route-registry.d.ts +39 -0
  36. package/src/route-registry.js +10 -8
  37. package/src/route-registry.spec.js +2 -5
  38. package/src/router-options.d.ts +18 -0
  39. package/src/router-options.js +4 -3
  40. package/src/senders/data-sender.d.ts +15 -0
  41. package/src/senders/error-sender.d.ts +30 -0
  42. package/src/senders/error-sender.js +3 -1
  43. package/src/senders/index.d.ts +2 -0
  44. package/src/trie-router.d.ts +104 -0
  45. package/src/trie-router.js +14 -7
  46. package/src/trie-router.spec.js +26 -26
  47. package/src/types.d.ts +19 -0
  48. package/src/utils/clone-deep.d.ts +6 -0
  49. package/src/utils/create-cookie-string.d.ts +6 -0
  50. package/src/utils/create-cookie-string.js +29 -0
  51. package/src/utils/{create-cookies-string.spec.js → create-cookie-string.spec.js} +7 -7
  52. package/src/utils/create-error.d.ts +14 -0
  53. package/src/utils/create-error.js +12 -8
  54. package/src/utils/create-error.spec.js +2 -2
  55. package/src/utils/create-request-mock.d.ts +27 -0
  56. package/src/utils/create-request-mock.js +84 -62
  57. package/src/utils/create-request-mock.spec.js +14 -13
  58. package/src/utils/create-response-mock.d.ts +17 -0
  59. package/src/utils/create-response-mock.js +2 -1
  60. package/src/utils/create-route-mock.d.ts +18 -0
  61. package/src/utils/create-route-mock.js +2 -2
  62. package/src/utils/create-route-mock.spec.js +2 -2
  63. package/src/utils/fetch-request-body.d.ts +26 -0
  64. package/src/utils/fetch-request-body.js +13 -9
  65. package/src/utils/fetch-request-body.spec.js +2 -2
  66. package/src/utils/get-request-pathname.d.ts +8 -0
  67. package/src/utils/get-request-pathname.js +5 -4
  68. package/src/utils/get-request-pathname.spec.js +2 -2
  69. package/src/utils/index.d.ts +15 -0
  70. package/src/utils/index.js +2 -3
  71. package/src/utils/is-promise.d.ts +10 -0
  72. package/src/utils/is-promise.js +6 -2
  73. package/src/utils/is-readable-stream.d.ts +9 -0
  74. package/src/utils/is-readable-stream.js +3 -1
  75. package/src/utils/is-response-sent.d.ts +8 -0
  76. package/src/utils/is-response-sent.js +3 -3
  77. package/src/utils/is-response-sent.spec.js +2 -2
  78. package/src/utils/is-writable-stream.d.ts +9 -0
  79. package/src/utils/is-writable-stream.js +3 -1
  80. package/src/utils/parse-content-type.d.ts +15 -0
  81. package/src/utils/parse-content-type.js +12 -7
  82. package/src/utils/parse-content-type.spec.js +21 -0
  83. package/src/utils/parse-cookie-string.d.ts +19 -0
  84. package/src/utils/{parse-cookies.js → parse-cookie-string.js} +11 -7
  85. package/src/utils/parse-cookie-string.spec.js +49 -0
  86. package/src/utils/to-camel-case.d.ts +6 -0
  87. package/src/utils/to-camel-case.js +6 -5
  88. package/src/utils/to-camel-case.spec.js +2 -2
  89. package/tsconfig.json +14 -0
  90. package/jsconfig.json +0 -7
  91. package/src/utils/create-cookies-string.js +0 -24
  92. package/src/utils/create-debugger.js +0 -22
  93. package/src/utils/create-debugger.spec.js +0 -30
  94. package/src/utils/parse-cookies.spec.js +0 -42
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -41,6 +42,7 @@ __export(index_exports, {
41
42
  HttpMethod: () => HttpMethod,
42
43
  METHODS_WITH_BODY: () => METHODS_WITH_BODY,
43
44
  QueryParser: () => QueryParser,
45
+ ROOT_PATH: () => ROOT_PATH,
44
46
  RequestContext: () => RequestContext,
45
47
  RequestParser: () => RequestParser,
46
48
  Route: () => Route,
@@ -50,8 +52,7 @@ __export(index_exports, {
50
52
  TrieRouter: () => TrieRouter,
51
53
  UNPARSABLE_MEDIA_TYPES: () => UNPARSABLE_MEDIA_TYPES,
52
54
  cloneDeep: () => cloneDeep,
53
- createCookiesString: () => createCookiesString,
54
- createDebugger: () => createDebugger,
55
+ createCookieString: () => createCookieString,
55
56
  createError: () => createError,
56
57
  createRequestMock: () => createRequestMock,
57
58
  createResponseMock: () => createResponseMock,
@@ -63,18 +64,18 @@ __export(index_exports, {
63
64
  isResponseSent: () => isResponseSent,
64
65
  isWritableStream: () => isWritableStream,
65
66
  parseContentType: () => parseContentType,
66
- parseCookies: () => parseCookies,
67
+ parseCookieString: () => parseCookieString,
67
68
  parseJsonBody: () => parseJsonBody,
68
- toCamelCase: () => toCamelCase
69
+ toCamelCase: () => toCamelCase,
70
+ validateRouteDefinition: () => validateRouteDefinition
69
71
  });
70
72
  module.exports = __toCommonJS(index_exports);
71
73
 
72
- // src/route.js
73
- var import_js_format13 = require("@e22m4u/js-format");
74
+ // src/route/route.js
74
75
  var import_js_debug = require("@e22m4u/js-debug");
75
76
 
76
77
  // src/hooks/hook-invoker.js
77
- var import_js_format12 = require("@e22m4u/js-format");
78
+ var import_js_format11 = require("@e22m4u/js-format");
78
79
 
79
80
  // src/debuggable-service.js
80
81
  var import_js_service = require("@e22m4u/js-service");
@@ -122,8 +123,12 @@ __name(cloneDeep, "cloneDeep");
122
123
 
123
124
  // src/utils/is-promise.js
124
125
  function isPromise(value) {
125
- if (!value) return false;
126
- if (typeof value !== "object") return false;
126
+ if (!value) {
127
+ return false;
128
+ }
129
+ if (typeof value !== "object") {
130
+ return false;
131
+ }
127
132
  return typeof value.then === "function";
128
133
  }
129
134
  __name(isPromise, "isPromise");
@@ -131,74 +136,45 @@ __name(isPromise, "isPromise");
131
136
  // src/utils/create-error.js
132
137
  var import_js_format = require("@e22m4u/js-format");
133
138
  function createError(errorCtor, message, ...args) {
134
- if (typeof errorCtor !== "function")
135
- throw new import_js_format.Errorf(
136
- 'The first argument of "createError" should be a constructor, but %v was given.',
139
+ if (typeof errorCtor !== "function") {
140
+ throw new import_js_format.InvalidArgumentError(
141
+ 'The first parameter of "createError" must be a constructor, but %v was given.',
137
142
  errorCtor
138
143
  );
139
- if (message != null && typeof message !== "string")
140
- throw new import_js_format.Errorf(
141
- 'The second argument of "createError" should be a String, but %v was given.',
144
+ }
145
+ if (message != null && typeof message !== "string") {
146
+ throw new import_js_format.InvalidArgumentError(
147
+ 'The second parameter of "createError" must be a String, but %v was given.',
142
148
  message
143
149
  );
144
- if (message == null) return new errorCtor();
150
+ }
151
+ if (message == null) {
152
+ return new errorCtor();
153
+ }
145
154
  const interpolatedMessage = (0, import_js_format.format)(message, ...args);
146
155
  return new errorCtor(interpolatedMessage);
147
156
  }
148
157
  __name(createError, "createError");
149
158
 
150
- // src/utils/parse-cookies.js
151
- var import_js_format2 = require("@e22m4u/js-format");
152
- function parseCookies(input) {
153
- if (typeof input !== "string")
154
- throw new import_js_format2.Errorf(
155
- 'The first parameter of "parseCookies" should be a String, but %v was given.',
156
- input
157
- );
158
- return input.split(";").filter((v) => v !== "").map((v) => v.split("=")).reduce((cookies, tuple) => {
159
- const key = decodeURIComponent(tuple[0]).trim();
160
- const value = tuple[1] !== void 0 ? decodeURIComponent(tuple[1]).trim() : "";
161
- cookies[key] = value;
162
- return cookies;
163
- }, {});
164
- }
165
- __name(parseCookies, "parseCookies");
166
-
167
159
  // src/utils/to-camel-case.js
168
- var import_js_format3 = require("@e22m4u/js-format");
160
+ var import_js_format2 = require("@e22m4u/js-format");
169
161
  function toCamelCase(input) {
170
- if (typeof input !== "string")
171
- throw new import_js_format3.Errorf(
172
- 'The first argument of "toCamelCase" should be a String, but %v was given.',
162
+ if (typeof input !== "string") {
163
+ throw new import_js_format2.InvalidArgumentError(
164
+ 'The first parameter of "toCamelCase" must be a String, but %v was given.',
173
165
  input
174
166
  );
167
+ }
175
168
  return input.replace(/(^\w|[A-Z]|\b\w)/g, (c) => c.toUpperCase()).replace(/\W+/g, "").replace(/(^\w)/g, (c) => c.toLowerCase());
176
169
  }
177
170
  __name(toCamelCase, "toCamelCase");
178
171
 
179
- // src/utils/create-debugger.js
180
- var import_debug = __toESM(require("debug"), 1);
181
- var import_js_format4 = require("@e22m4u/js-format");
182
- function createDebugger(name) {
183
- if (typeof name !== "string")
184
- throw new import_js_format4.Errorf(
185
- 'The first argument of "createDebugger" should be a String, but %v was given.',
186
- name
187
- );
188
- const debug = (0, import_debug.default)(`jsTrieRouter:${name}`);
189
- return function(message, ...args) {
190
- const interpolatedMessage = (0, import_js_format4.format)(message, ...args);
191
- return debug(interpolatedMessage);
192
- };
193
- }
194
- __name(createDebugger, "createDebugger");
195
-
196
172
  // src/utils/is-response-sent.js
197
- var import_js_format5 = require("@e22m4u/js-format");
173
+ var import_js_format3 = require("@e22m4u/js-format");
198
174
  function isResponseSent(response) {
199
175
  if (!response || typeof response !== "object" || Array.isArray(response) || typeof response.headersSent !== "boolean") {
200
- throw new import_js_format5.Errorf(
201
- 'The first argument of "isResponseSent" should be an instance of ServerResponse, but %v was given.',
176
+ throw new import_js_format3.InvalidArgumentError(
177
+ 'The first parameter of "isResponseSent" must be an instance of ServerResponse, but %v was given.',
202
178
  response
203
179
  );
204
180
  }
@@ -210,7 +186,7 @@ __name(isResponseSent, "isResponseSent");
210
186
  function createRouteMock(options = {}) {
211
187
  return new Route({
212
188
  method: options.method || HttpMethod.GET,
213
- path: options.path || "/",
189
+ path: options.path || ROOT_PATH,
214
190
  handler: options.handler || (() => "OK")
215
191
  });
216
192
  }
@@ -218,26 +194,33 @@ __name(createRouteMock, "createRouteMock");
218
194
 
219
195
  // src/utils/is-readable-stream.js
220
196
  function isReadableStream(value) {
221
- if (!value || typeof value !== "object") return false;
197
+ if (!value || typeof value !== "object") {
198
+ return false;
199
+ }
222
200
  return typeof value.pipe === "function";
223
201
  }
224
202
  __name(isReadableStream, "isReadableStream");
225
203
 
226
204
  // src/utils/parse-content-type.js
227
- var import_js_format6 = require("@e22m4u/js-format");
205
+ var import_js_format4 = require("@e22m4u/js-format");
228
206
  function parseContentType(input) {
229
- if (typeof input !== "string")
230
- throw new import_js_format6.Errorf(
231
- 'The parameter "input" of "parseContentType" should be a String, but %v was given.',
207
+ if (typeof input !== "string") {
208
+ throw new import_js_format4.InvalidArgumentError(
209
+ "The first parameter of `parseContentType` must be a String, but %v was given.",
232
210
  input
233
211
  );
212
+ }
234
213
  const res = { mediaType: void 0, charset: void 0, boundary: void 0 };
235
214
  const re = /^\s*([^\s;/]+\/[^\s;/]+)(?:;\s*charset=([^\s;]+))?(?:;\s*boundary=([^\s;]+))?.*$/i;
236
215
  const matches = re.exec(input);
237
216
  if (matches && matches[1]) {
238
217
  res.mediaType = matches[1];
239
- if (matches[2]) res.charset = matches[2];
240
- if (matches[3]) res.boundary = matches[3];
218
+ if (matches[2]) {
219
+ res.charset = matches[2];
220
+ }
221
+ if (matches[3]) {
222
+ res.boundary = matches[3];
223
+ }
241
224
  }
242
225
  return res;
243
226
  }
@@ -245,7 +228,9 @@ __name(parseContentType, "parseContentType");
245
228
 
246
229
  // src/utils/is-writable-stream.js
247
230
  function isWritableStream(value) {
248
- if (!value || typeof value !== "object") return false;
231
+ if (!value || typeof value !== "object") {
232
+ return false;
233
+ }
249
234
  return typeof value.end === "function";
250
235
  }
251
236
  __name(isWritableStream, "isWritableStream");
@@ -253,7 +238,7 @@ __name(isWritableStream, "isWritableStream");
253
238
  // src/utils/fetch-request-body.js
254
239
  var import_http_errors = __toESM(require("http-errors"), 1);
255
240
  var import_http = require("http");
256
- var import_js_format7 = require("@e22m4u/js-format");
241
+ var import_js_format5 = require("@e22m4u/js-format");
257
242
  var CHARACTER_ENCODING_LIST = [
258
243
  "ascii",
259
244
  "utf8",
@@ -265,40 +250,44 @@ var CHARACTER_ENCODING_LIST = [
265
250
  "latin1"
266
251
  ];
267
252
  function fetchRequestBody(request, bodyBytesLimit = 0) {
268
- if (!(request instanceof import_http.IncomingMessage))
269
- throw new import_js_format7.Errorf(
270
- 'The first parameter of "fetchRequestBody" should be an IncomingMessage instance, but %v was given.',
253
+ if (!(request instanceof import_http.IncomingMessage)) {
254
+ throw new import_js_format5.InvalidArgumentError(
255
+ 'The first parameter of "fetchRequestBody" must be an IncomingMessage instance, but %v was given.',
271
256
  request
272
257
  );
273
- if (typeof bodyBytesLimit !== "number")
274
- throw new import_js_format7.Errorf(
275
- 'The parameter "bodyBytesLimit" of "fetchRequestBody" should be a number, but %v was given.',
258
+ }
259
+ if (typeof bodyBytesLimit !== "number") {
260
+ throw new import_js_format5.InvalidArgumentError(
261
+ 'The parameter "bodyBytesLimit" of "fetchRequestBody" must be a number, but %v was given.',
276
262
  bodyBytesLimit
277
263
  );
264
+ }
278
265
  return new Promise((resolve, reject) => {
279
266
  const contentLength = parseInt(
280
267
  request.headers["content-length"] || "0",
281
268
  10
282
269
  );
283
- if (bodyBytesLimit && contentLength && contentLength > bodyBytesLimit)
270
+ if (bodyBytesLimit && contentLength && contentLength > bodyBytesLimit) {
284
271
  throw createError(
285
272
  import_http_errors.default.PayloadTooLarge,
286
273
  "Request body limit is %s bytes, but %s bytes given.",
287
274
  bodyBytesLimit,
288
275
  contentLength
289
276
  );
277
+ }
290
278
  let encoding = "utf-8";
291
279
  const contentType = request.headers["content-type"] || "";
292
280
  if (contentType) {
293
281
  const parsedContentType = parseContentType(contentType);
294
282
  if (parsedContentType && parsedContentType.charset) {
295
283
  encoding = parsedContentType.charset.toLowerCase();
296
- if (!CHARACTER_ENCODING_LIST.includes(encoding))
284
+ if (!CHARACTER_ENCODING_LIST.includes(encoding)) {
297
285
  throw createError(
298
286
  import_http_errors.default.UnsupportedMediaType,
299
287
  "Request encoding %v is not supported.",
300
288
  encoding
301
289
  );
290
+ }
302
291
  }
303
292
  }
304
293
  const data = [];
@@ -344,112 +333,148 @@ function fetchRequestBody(request, bodyBytesLimit = 0) {
344
333
  }
345
334
  __name(fetchRequestBody, "fetchRequestBody");
346
335
 
336
+ // src/utils/parse-cookie-string.js
337
+ var import_js_format6 = require("@e22m4u/js-format");
338
+ function parseCookieString(input) {
339
+ if (typeof input !== "string") {
340
+ throw new import_js_format6.InvalidArgumentError(
341
+ 'The first parameter of "parseCookieString" must be a String, but %v was given.',
342
+ input
343
+ );
344
+ }
345
+ return input.split(";").filter((v) => v !== "").map((v) => v.split("=")).reduce((cookies, tuple) => {
346
+ const key = decodeURIComponent(tuple[0]).trim();
347
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
348
+ return cookies;
349
+ }
350
+ const value = tuple[1] !== void 0 ? decodeURIComponent(tuple[1]).trim() : "";
351
+ cookies[key] = value;
352
+ return cookies;
353
+ }, {});
354
+ }
355
+ __name(parseCookieString, "parseCookieString");
356
+
347
357
  // src/utils/create-request-mock.js
348
358
  var import_net = require("net");
349
359
  var import_tls = require("tls");
350
360
  var import_http2 = require("http");
351
361
  var import_querystring = __toESM(require("querystring"), 1);
352
- var import_js_format9 = require("@e22m4u/js-format");
353
-
354
- // src/utils/create-cookies-string.js
355
362
  var import_js_format8 = require("@e22m4u/js-format");
356
- function createCookiesString(data) {
357
- if (!data || typeof data !== "object" || Array.isArray(data))
358
- throw new import_js_format8.Errorf(
359
- 'The first parameter of "createCookiesString" should be an Object, but %v was given.',
363
+
364
+ // src/utils/create-cookie-string.js
365
+ var import_js_format7 = require("@e22m4u/js-format");
366
+ function createCookieString(data) {
367
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
368
+ throw new import_js_format7.InvalidArgumentError(
369
+ 'The first parameter of "createCookieString" must be an Object, but %v was given.',
360
370
  data
361
371
  );
372
+ }
362
373
  let cookies = "";
363
374
  for (const key in data) {
364
- if (!Object.prototype.hasOwnProperty.call(data, key)) continue;
375
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
376
+ continue;
377
+ }
365
378
  const val = data[key];
366
- if (val == null) continue;
379
+ if (val == null) {
380
+ continue;
381
+ }
367
382
  cookies += `${key}=${val}; `;
368
383
  }
369
384
  return cookies.trim();
370
385
  }
371
- __name(createCookiesString, "createCookiesString");
386
+ __name(createCookieString, "createCookieString");
372
387
 
373
388
  // src/utils/create-request-mock.js
374
389
  function createRequestMock(patch) {
375
390
  if (patch != null && typeof patch !== "object" || Array.isArray(patch)) {
376
- throw new import_js_format9.Errorf(
377
- 'The first parameter of "createRequestMock" should be an Object, but %v was given.',
391
+ throw new import_js_format8.InvalidArgumentError(
392
+ 'The first parameter of "createRequestMock" must be an Object, but %v was given.',
378
393
  patch
379
394
  );
380
395
  }
381
396
  patch = patch || {};
382
- if (patch.host != null && typeof patch.host !== "string")
383
- throw new import_js_format9.Errorf(
384
- 'The parameter "host" of "createRequestMock" should be a String, but %v was given.',
397
+ if (patch.host != null && typeof patch.host !== "string") {
398
+ throw new import_js_format8.InvalidArgumentError(
399
+ 'The parameter "host" of "createRequestMock" must be a String, but %v was given.',
385
400
  patch.host
386
401
  );
387
- if (patch.method != null && typeof patch.method !== "string")
388
- throw new import_js_format9.Errorf(
389
- 'The parameter "method" of "createRequestMock" should be a String, but %v was given.',
402
+ }
403
+ if (patch.method != null && typeof patch.method !== "string") {
404
+ throw new import_js_format8.InvalidArgumentError(
405
+ 'The parameter "method" of "createRequestMock" must be a String, but %v was given.',
390
406
  patch.method
391
407
  );
392
- if (patch.secure != null && typeof patch.secure !== "boolean")
393
- throw new import_js_format9.Errorf(
394
- 'The parameter "secure" of "createRequestMock" should be a Boolean, but %v was given.',
408
+ }
409
+ if (patch.secure != null && typeof patch.secure !== "boolean") {
410
+ throw new import_js_format8.InvalidArgumentError(
411
+ 'The parameter "secure" of "createRequestMock" must be a Boolean, but %v was given.',
395
412
  patch.secure
396
413
  );
397
- if (patch.path != null && typeof patch.path !== "string")
398
- throw new import_js_format9.Errorf(
399
- 'The parameter "path" of "createRequestMock" should be a String, but %v was given.',
414
+ }
415
+ if (patch.path != null && typeof patch.path !== "string") {
416
+ throw new import_js_format8.InvalidArgumentError(
417
+ 'The parameter "path" of "createRequestMock" must be a String, but %v was given.',
400
418
  patch.path
401
419
  );
420
+ }
402
421
  if (patch.query != null && typeof patch.query !== "object" && typeof patch.query !== "string" || Array.isArray(patch.query)) {
403
- throw new import_js_format9.Errorf(
404
- 'The parameter "query" of "createRequestMock" should be a String or Object, but %v was given.',
422
+ throw new import_js_format8.InvalidArgumentError(
423
+ 'The parameter "query" of "createRequestMock" must be a String or Object, but %v was given.',
405
424
  patch.query
406
425
  );
407
426
  }
408
427
  if (patch.cookies != null && typeof patch.cookies !== "string" && typeof patch.cookies !== "object" || Array.isArray(patch.cookies)) {
409
- throw new import_js_format9.Errorf(
410
- 'The parameter "cookies" of "createRequestMock" should be a String or Object, but %v was given.',
428
+ throw new import_js_format8.InvalidArgumentError(
429
+ 'The parameter "cookies" of "createRequestMock" must be a String or Object, but %v was given.',
411
430
  patch.cookies
412
431
  );
413
432
  }
414
433
  if (patch.headers != null && typeof patch.headers !== "object" || Array.isArray(patch.headers)) {
415
- throw new import_js_format9.Errorf(
416
- 'The parameter "headers" of "createRequestMock" should be an Object, but %v was given.',
434
+ throw new import_js_format8.InvalidArgumentError(
435
+ 'The parameter "headers" of "createRequestMock" must be an Object, but %v was given.',
417
436
  patch.headers
418
437
  );
419
438
  }
420
- if (patch.stream != null && !isReadableStream(patch.stream))
421
- throw new import_js_format9.Errorf(
422
- 'The parameter "stream" of "createRequestMock" should be a Stream, but %v was given.',
439
+ if (patch.stream != null && !isReadableStream(patch.stream)) {
440
+ throw new import_js_format8.InvalidArgumentError(
441
+ 'The parameter "stream" of "createRequestMock" must be a Stream, but %v was given.',
423
442
  patch.stream
424
443
  );
444
+ }
425
445
  if (patch.encoding != null) {
426
- if (typeof patch.encoding !== "string")
427
- throw new import_js_format9.Errorf(
428
- 'The parameter "encoding" of "createRequestMock" should be a String, but %v was given.',
446
+ if (typeof patch.encoding !== "string") {
447
+ throw new import_js_format8.InvalidArgumentError(
448
+ 'The parameter "encoding" of "createRequestMock" must be a String, but %v was given.',
429
449
  patch.encoding
430
450
  );
431
- if (!CHARACTER_ENCODING_LIST.includes(patch.encoding))
432
- throw new import_js_format9.Errorf(
451
+ }
452
+ if (!CHARACTER_ENCODING_LIST.includes(patch.encoding)) {
453
+ throw new import_js_format8.InvalidArgumentError(
433
454
  "Character encoding %v is not supported.",
434
455
  patch.encoding
435
456
  );
457
+ }
436
458
  }
437
459
  if (patch.stream) {
438
- if (patch.secure != null)
439
- throw new import_js_format9.Errorf(
460
+ if (patch.secure != null) {
461
+ throw new import_js_format8.InvalidArgumentError(
440
462
  'The "createRequestMock" does not allow specifying the "stream" and "secure" options simultaneously.'
441
463
  );
442
- if (patch.body != null)
443
- throw new import_js_format9.Errorf(
464
+ }
465
+ if (patch.body != null) {
466
+ throw new import_js_format8.InvalidArgumentError(
444
467
  'The "createRequestMock" does not allow specifying the "stream" and "body" options simultaneously.'
445
468
  );
446
- if (patch.encoding != null)
447
- throw new import_js_format9.Errorf(
469
+ }
470
+ if (patch.encoding != null) {
471
+ throw new import_js_format8.InvalidArgumentError(
448
472
  'The "createRequestMock" does not allow specifying the "stream" and "encoding" options simultaneously.'
449
473
  );
474
+ }
450
475
  }
451
476
  const request = patch.stream || createRequestStream(patch.secure, patch.body, patch.encoding);
452
- request.url = createRequestUrl(patch.path || "/", patch.query);
477
+ request.url = createRequestUrl(patch.path || ROOT_PATH, patch.query);
453
478
  request.headers = createRequestHeaders(
454
479
  patch.host,
455
480
  patch.secure,
@@ -463,14 +488,17 @@ function createRequestMock(patch) {
463
488
  }
464
489
  __name(createRequestMock, "createRequestMock");
465
490
  function createRequestStream(secure, body, encoding) {
466
- if (encoding != null && typeof encoding !== "string")
467
- throw new import_js_format9.Errorf(
468
- 'The parameter "encoding" of "createRequestStream" should be a String, but %v was given.',
491
+ if (encoding != null && typeof encoding !== "string") {
492
+ throw new import_js_format8.InvalidArgumentError(
493
+ 'The parameter "encoding" of "createRequestStream" must be a String, but %v was given.',
469
494
  encoding
470
495
  );
496
+ }
471
497
  encoding = encoding || "utf-8";
472
498
  let socket = new import_net.Socket();
473
- if (secure) socket = new import_tls.TLSSocket(socket);
499
+ if (secure) {
500
+ socket = new import_tls.TLSSocket(socket);
501
+ }
474
502
  const request = new import_http2.IncomingMessage(socket);
475
503
  if (body != null) {
476
504
  if (typeof body === "string") {
@@ -486,21 +514,24 @@ function createRequestStream(secure, body, encoding) {
486
514
  }
487
515
  __name(createRequestStream, "createRequestStream");
488
516
  function createRequestUrl(path, query) {
489
- if (typeof path !== "string")
490
- throw new import_js_format9.Errorf(
491
- 'The parameter "path" of "createRequestUrl" should be a String, but %v was given.',
517
+ if (typeof path !== "string") {
518
+ throw new import_js_format8.InvalidArgumentError(
519
+ 'The parameter "path" of "createRequestUrl" must be a String, but %v was given.',
492
520
  path
493
521
  );
522
+ }
494
523
  if (query != null && typeof query !== "string" && typeof query !== "object" || Array.isArray(query)) {
495
- throw new import_js_format9.Errorf(
496
- 'The parameter "query" of "createRequestUrl" should be a String or Object, but %v was given.',
524
+ throw new import_js_format8.InvalidArgumentError(
525
+ 'The parameter "query" of "createRequestUrl" must be a String or Object, but %v was given.',
497
526
  query
498
527
  );
499
528
  }
500
- let url = ("/" + path).replace("//", "/");
529
+ let url = (ROOT_PATH + path).replace("//", "/");
501
530
  if (typeof query === "object") {
502
531
  const qs = import_querystring.default.stringify(query);
503
- if (qs) url += `?${qs}`;
532
+ if (qs) {
533
+ url += `?${qs}`;
534
+ }
504
535
  } else if (typeof query === "string") {
505
536
  url += `?${query.replace(/^\?/, "")}`;
506
537
  }
@@ -508,47 +539,52 @@ function createRequestUrl(path, query) {
508
539
  }
509
540
  __name(createRequestUrl, "createRequestUrl");
510
541
  function createRequestHeaders(host, secure, body, cookies, encoding, headers) {
511
- if (host != null && typeof host !== "string")
512
- throw new import_js_format9.Errorf(
542
+ if (host != null && typeof host !== "string") {
543
+ throw new import_js_format8.InvalidArgumentError(
513
544
  'The parameter "host" of "createRequestHeaders" a non-empty String, but %v was given.',
514
545
  host
515
546
  );
547
+ }
516
548
  host = host || "localhost";
517
- if (secure != null && typeof secure !== "boolean")
518
- throw new import_js_format9.Errorf(
519
- 'The parameter "secure" of "createRequestHeaders" should be a String, but %v was given.',
549
+ if (secure != null && typeof secure !== "boolean") {
550
+ throw new import_js_format8.InvalidArgumentError(
551
+ 'The parameter "secure" of "createRequestHeaders" must be a String, but %v was given.',
520
552
  secure
521
553
  );
554
+ }
522
555
  secure = Boolean(secure);
523
556
  if (cookies != null && typeof cookies !== "object" && typeof cookies !== "string" || Array.isArray(cookies)) {
524
- throw new import_js_format9.Errorf(
525
- 'The parameter "cookies" of "createRequestHeaders" should be a String or Object, but %v was given.',
557
+ throw new import_js_format8.InvalidArgumentError(
558
+ 'The parameter "cookies" of "createRequestHeaders" must be a String or Object, but %v was given.',
526
559
  cookies
527
560
  );
528
561
  }
529
562
  if (headers != null && typeof headers !== "object" || Array.isArray(headers)) {
530
- throw new import_js_format9.Errorf(
531
- 'The parameter "headers" of "createRequestHeaders" should be an Object, but %v was given.',
563
+ throw new import_js_format8.InvalidArgumentError(
564
+ 'The parameter "headers" of "createRequestHeaders" must be an Object, but %v was given.',
532
565
  headers
533
566
  );
534
567
  }
535
568
  headers = headers || {};
536
- if (encoding != null && typeof encoding !== "string")
537
- throw new import_js_format9.Errorf(
538
- 'The parameter "encoding" of "createRequestHeaders" should be a String, but %v was given.',
569
+ if (encoding != null && typeof encoding !== "string") {
570
+ throw new import_js_format8.InvalidArgumentError(
571
+ 'The parameter "encoding" of "createRequestHeaders" must be a String, but %v was given.',
539
572
  encoding
540
573
  );
574
+ }
541
575
  encoding = encoding || "utf-8";
542
576
  const obj = { ...headers };
543
577
  obj["host"] = host;
544
- if (secure) obj["x-forwarded-proto"] = "https";
578
+ if (secure) {
579
+ obj["x-forwarded-proto"] = "https";
580
+ }
545
581
  if (cookies != null) {
546
582
  if (typeof cookies === "string") {
547
583
  obj["cookie"] = obj["cookie"] ? obj["cookie"] : "";
548
584
  obj["cookie"] += obj["cookie"] ? `; ${cookies}` : cookies;
549
585
  } else if (typeof cookies === "object") {
550
586
  obj["cookie"] = obj["cookie"] ? obj["cookie"] : "";
551
- const newCookies = createCookiesString(cookies);
587
+ const newCookies = createCookieString(cookies);
552
588
  obj["cookie"] += obj["cookie"] ? `; ${newCookies}` : newCookies;
553
589
  }
554
590
  }
@@ -629,10 +665,11 @@ function patchHeaders(response) {
629
665
  Object.defineProperty(response, "setHeader", {
630
666
  configurable: true,
631
667
  value: /* @__PURE__ */ __name(function(name, value) {
632
- if (this.headersSent)
668
+ if (this.headersSent) {
633
669
  throw new Error(
634
670
  "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client"
635
671
  );
672
+ }
636
673
  const key = name.toLowerCase();
637
674
  this._headers[key] = String(value);
638
675
  return this;
@@ -683,20 +720,20 @@ function patchBody(response) {
683
720
  __name(patchBody, "patchBody");
684
721
 
685
722
  // src/utils/get-request-pathname.js
686
- var import_js_format10 = require("@e22m4u/js-format");
723
+ var import_js_format9 = require("@e22m4u/js-format");
687
724
  function getRequestPathname(request) {
688
725
  if (!request || typeof request !== "object" || Array.isArray(request) || typeof request.url !== "string") {
689
- throw new import_js_format10.Errorf(
690
- 'The first argument of "getRequestPathname" should be an instance of IncomingMessage, but %v was given.',
726
+ throw new import_js_format9.InvalidArgumentError(
727
+ 'The first parameter of "getRequestPathname" must be an instance of IncomingMessage, but %v was given.',
691
728
  request
692
729
  );
693
730
  }
694
- return (request.url || "/").replace(/\?.*$/, "");
731
+ return (request.url || ROOT_PATH).replace(/\?.*$/, "");
695
732
  }
696
733
  __name(getRequestPathname, "getRequestPathname");
697
734
 
698
735
  // src/hooks/hook-registry.js
699
- var import_js_format11 = require("@e22m4u/js-format");
736
+ var import_js_format10 = require("@e22m4u/js-format");
700
737
  var RouterHookType = {
701
738
  PRE_HANDLER: "preHandler",
702
739
  POST_HANDLER: "postHandler"
@@ -717,16 +754,25 @@ var _HookRegistry = class _HookRegistry {
717
754
  * @returns {this}
718
755
  */
719
756
  addHook(type, hook) {
720
- if (!type || typeof type !== "string")
721
- throw new import_js_format11.Errorf("The hook type is required, but %v was given.", type);
722
- if (!Object.values(RouterHookType).includes(type))
723
- throw new import_js_format11.Errorf("The hook type %v is not supported.", type);
724
- if (!hook || typeof hook !== "function")
725
- throw new import_js_format11.Errorf(
726
- "The hook %v should be a Function, but %v was given.",
757
+ if (!type || typeof type !== "string") {
758
+ throw new import_js_format10.InvalidArgumentError(
759
+ "The hook type is required, but %v was given.",
760
+ type
761
+ );
762
+ }
763
+ if (!Object.values(RouterHookType).includes(type)) {
764
+ throw new import_js_format10.InvalidArgumentError(
765
+ "The hook type %v is not supported.",
766
+ type
767
+ );
768
+ }
769
+ if (!hook || typeof hook !== "function") {
770
+ throw new import_js_format10.InvalidArgumentError(
771
+ "The hook %v must be a Function, but %v was given.",
727
772
  type,
728
773
  hook
729
774
  );
775
+ }
730
776
  const hooks = this._hooks.get(type) || [];
731
777
  hooks.push(hook);
732
778
  this._hooks.set(type, hooks);
@@ -740,16 +786,25 @@ var _HookRegistry = class _HookRegistry {
740
786
  * @returns {boolean}
741
787
  */
742
788
  hasHook(type, hook) {
743
- if (!type || typeof type !== "string")
744
- throw new import_js_format11.Errorf("The hook type is required, but %v was given.", type);
745
- if (!Object.values(RouterHookType).includes(type))
746
- throw new import_js_format11.Errorf("The hook type %v is not supported.", type);
747
- if (!hook || typeof hook !== "function")
748
- throw new import_js_format11.Errorf(
749
- "The hook %v should be a Function, but %v was given.",
789
+ if (!type || typeof type !== "string") {
790
+ throw new import_js_format10.InvalidArgumentError(
791
+ "The hook type is required, but %v was given.",
792
+ type
793
+ );
794
+ }
795
+ if (!Object.values(RouterHookType).includes(type)) {
796
+ throw new import_js_format10.InvalidArgumentError(
797
+ "The hook type %v is not supported.",
798
+ type
799
+ );
800
+ }
801
+ if (!hook || typeof hook !== "function") {
802
+ throw new import_js_format10.InvalidArgumentError(
803
+ "The hook %v must be a Function, but %v was given.",
750
804
  type,
751
805
  hook
752
806
  );
807
+ }
753
808
  const hooks = this._hooks.get(type) || [];
754
809
  return hooks.indexOf(hook) > -1;
755
810
  }
@@ -760,10 +815,18 @@ var _HookRegistry = class _HookRegistry {
760
815
  * @returns {Function[]}
761
816
  */
762
817
  getHooks(type) {
763
- if (!type || typeof type !== "string")
764
- throw new import_js_format11.Errorf("The hook type is required, but %v was given.", type);
765
- if (!Object.values(RouterHookType).includes(type))
766
- throw new import_js_format11.Errorf("The hook type %v is not supported.", type);
818
+ if (!type || typeof type !== "string") {
819
+ throw new import_js_format10.InvalidArgumentError(
820
+ "The hook type is required, but %v was given.",
821
+ type
822
+ );
823
+ }
824
+ if (!Object.values(RouterHookType).includes(type)) {
825
+ throw new import_js_format10.InvalidArgumentError(
826
+ "The hook type %v is not supported.",
827
+ type
828
+ );
829
+ }
767
830
  return this._hooks.get(type) || [];
768
831
  }
769
832
  };
@@ -782,21 +845,27 @@ var _HookInvoker = class _HookInvoker extends DebuggableService {
782
845
  * @returns {Promise<*>|*}
783
846
  */
784
847
  invokeAndContinueUntilValueReceived(route, hookType, response, ...args) {
785
- if (!route || !(route instanceof Route))
786
- throw new import_js_format12.Errorf(
787
- 'The parameter "route" of the HookInvoker.invokeAndContinueUntilValueReceived should be a Route instance, but %v was given.',
848
+ if (!route || !(route instanceof Route)) {
849
+ throw new import_js_format11.InvalidArgumentError(
850
+ 'The parameter "route" of the HookInvoker.invokeAndContinueUntilValueReceived must be a Route instance, but %v was given.',
788
851
  route
789
852
  );
790
- if (!hookType || typeof hookType !== "string")
791
- throw new import_js_format12.Errorf(
792
- 'The parameter "hookType" of the HookInvoker.invokeAndContinueUntilValueReceived should be a non-empty String, but %v was given.',
853
+ }
854
+ if (!hookType || typeof hookType !== "string") {
855
+ throw new import_js_format11.InvalidArgumentError(
856
+ 'The parameter "hookType" of the HookInvoker.invokeAndContinueUntilValueReceived must be a non-empty String, but %v was given.',
793
857
  hookType
794
858
  );
795
- if (!Object.values(RouterHookType).includes(hookType))
796
- throw new import_js_format12.Errorf("The hook type %v is not supported.", hookType);
859
+ }
860
+ if (!Object.values(RouterHookType).includes(hookType)) {
861
+ throw new import_js_format11.InvalidArgumentError(
862
+ "The hook type %v is not supported.",
863
+ hookType
864
+ );
865
+ }
797
866
  if (!response || typeof response !== "object" || Array.isArray(response) || typeof response.headersSent !== "boolean") {
798
- throw new import_js_format12.Errorf(
799
- 'The parameter "response" of the HookInvoker.invokeAndContinueUntilValueReceived should be a ServerResponse instance, but %v was given.',
867
+ throw new import_js_format11.InvalidArgumentError(
868
+ 'The parameter "response" of the HookInvoker.invokeAndContinueUntilValueReceived must be a ServerResponse instance, but %v was given.',
800
869
  response
801
870
  );
802
871
  }
@@ -845,7 +914,79 @@ var _HookInvoker = class _HookInvoker extends DebuggableService {
845
914
  __name(_HookInvoker, "HookInvoker");
846
915
  var HookInvoker = _HookInvoker;
847
916
 
848
- // src/route.js
917
+ // src/route/validate-route-definition.js
918
+ var import_js_format12 = require("@e22m4u/js-format");
919
+ function validateRouteDefinition(routeDef) {
920
+ if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef)) {
921
+ throw new import_js_format12.InvalidArgumentError(
922
+ "Route definition must be an Object, but %v was given.",
923
+ routeDef
924
+ );
925
+ }
926
+ if (!routeDef.method || typeof routeDef.method !== "string") {
927
+ throw new import_js_format12.InvalidArgumentError(
928
+ 'Option "method" must be a non-empty String, but %v was given.',
929
+ routeDef.method
930
+ );
931
+ }
932
+ if (!routeDef.path || typeof routeDef.path !== "string") {
933
+ throw new import_js_format12.InvalidArgumentError(
934
+ 'Option "path" must be a non-empty String, but %v was given.',
935
+ routeDef.path
936
+ );
937
+ }
938
+ if (typeof routeDef.handler !== "function") {
939
+ throw new import_js_format12.InvalidArgumentError(
940
+ 'Option "handler" must be a Function, but %v was given.',
941
+ routeDef.handler
942
+ );
943
+ }
944
+ if (routeDef.preHandler !== void 0) {
945
+ if (Array.isArray(routeDef.preHandler)) {
946
+ routeDef.preHandler.forEach((preHandler) => {
947
+ if (typeof preHandler !== "function") {
948
+ throw new import_js_format12.InvalidArgumentError(
949
+ "Route pre-handler must be a Function, but %v was given.",
950
+ preHandler
951
+ );
952
+ }
953
+ });
954
+ } else if (typeof routeDef.preHandler !== "function") {
955
+ throw new import_js_format12.InvalidArgumentError(
956
+ 'Option "preHandler" must be a Function or an Array, but %v was given.',
957
+ routeDef.preHandler
958
+ );
959
+ }
960
+ }
961
+ if (routeDef.postHandler !== void 0) {
962
+ if (Array.isArray(routeDef.postHandler)) {
963
+ routeDef.postHandler.forEach((postHandler) => {
964
+ if (typeof postHandler !== "function") {
965
+ throw new import_js_format12.InvalidArgumentError(
966
+ "Route post-handler must be a Function, but %v was given.",
967
+ postHandler
968
+ );
969
+ }
970
+ });
971
+ } else if (typeof routeDef.postHandler !== "function") {
972
+ throw new import_js_format12.InvalidArgumentError(
973
+ 'Option "postHandler" must be a Function or an Array, but %v was given.',
974
+ routeDef.postHandler
975
+ );
976
+ }
977
+ }
978
+ if (routeDef.meta !== void 0) {
979
+ if (!routeDef.meta || typeof routeDef.meta !== "object" || Array.isArray(routeDef.meta)) {
980
+ throw new import_js_format12.InvalidArgumentError(
981
+ 'Option "meta" must be an Object, but %v was given.',
982
+ routeDef.meta
983
+ );
984
+ }
985
+ }
986
+ }
987
+ __name(validateRouteDefinition, "validateRouteDefinition");
988
+
989
+ // src/route/route.js
849
990
  var HttpMethod = {
850
991
  GET: "GET",
851
992
  POST: "POST",
@@ -853,6 +994,7 @@ var HttpMethod = {
853
994
  PATCH: "PATCH",
854
995
  DELETE: "DELETE"
855
996
  };
997
+ var ROOT_PATH = "/";
856
998
  var _Route = class _Route extends import_js_debug.Debuggable {
857
999
  /**
858
1000
  * Method.
@@ -939,44 +1081,20 @@ var _Route = class _Route extends import_js_debug.Debuggable {
939
1081
  noEnvironmentNamespace: true,
940
1082
  noInstantiationMessage: true
941
1083
  });
942
- if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef))
943
- throw new import_js_format13.Errorf(
944
- "The first parameter of Route.constructor should be an Object, but %v was given.",
945
- routeDef
946
- );
947
- if (!routeDef.method || typeof routeDef.method !== "string")
948
- throw new import_js_format13.Errorf(
949
- 'The option "method" of the Route should be a non-empty String, but %v was given.',
950
- routeDef.method
951
- );
1084
+ validateRouteDefinition(routeDef);
952
1085
  this._method = routeDef.method.toUpperCase();
953
- if (typeof routeDef.path !== "string")
954
- throw new import_js_format13.Errorf(
955
- 'The option "path" of the Route should be a String, but %v was given.',
956
- routeDef.path
957
- );
958
1086
  this._path = routeDef.path;
959
- if (typeof routeDef.handler !== "function")
960
- throw new import_js_format13.Errorf(
961
- 'The option "handler" of the Route should be a Function, but %v was given.',
962
- routeDef.handler
963
- );
964
- if (routeDef.meta != null) {
965
- if (typeof routeDef.meta !== "object" || Array.isArray(routeDef.meta))
966
- throw new import_js_format13.Errorf(
967
- 'The option "meta" of the Route should be a plain Object, but %v was given.',
968
- routeDef.meta
969
- );
1087
+ if (routeDef.meta !== void 0) {
970
1088
  this._meta = cloneDeep(routeDef.meta);
971
1089
  }
972
1090
  this._handler = routeDef.handler;
973
- if (routeDef.preHandler != null) {
1091
+ if (routeDef.preHandler !== void 0) {
974
1092
  const preHandlerHooks = Array.isArray(routeDef.preHandler) ? routeDef.preHandler : [routeDef.preHandler];
975
1093
  preHandlerHooks.forEach((hook) => {
976
1094
  this._hookRegistry.addHook(RouterHookType.PRE_HANDLER, hook);
977
1095
  });
978
1096
  }
979
- if (routeDef.postHandler != null) {
1097
+ if (routeDef.postHandler !== void 0) {
980
1098
  const postHandlerHooks = Array.isArray(routeDef.postHandler) ? routeDef.postHandler : [routeDef.postHandler];
981
1099
  postHandlerHooks.forEach((hook) => {
982
1100
  this._hookRegistry.addHook(RouterHookType.POST_HANDLER, hook);
@@ -1006,10 +1124,9 @@ var Route = _Route;
1006
1124
 
1007
1125
  // src/parsers/body-parser.js
1008
1126
  var import_http_errors2 = __toESM(require("http-errors"), 1);
1009
- var import_js_format15 = require("@e22m4u/js-format");
1010
1127
 
1011
1128
  // src/router-options.js
1012
- var import_js_format14 = require("@e22m4u/js-format");
1129
+ var import_js_format13 = require("@e22m4u/js-format");
1013
1130
  var _RouterOptions = class _RouterOptions extends DebuggableService {
1014
1131
  /**
1015
1132
  * Request body bytes limit.
@@ -1034,11 +1151,12 @@ var _RouterOptions = class _RouterOptions extends DebuggableService {
1034
1151
  * @returns {RouterOptions}
1035
1152
  */
1036
1153
  setRequestBodyBytesLimit(input) {
1037
- if (typeof input !== "number" || input < 0)
1038
- throw new import_js_format14.Errorf(
1154
+ if (typeof input !== "number" || input < 0) {
1155
+ throw new import_js_format13.InvalidArgumentError(
1039
1156
  'The option "requestBodyBytesLimit" must be a positive Number or 0, but %v was given.',
1040
1157
  input
1041
1158
  );
1159
+ }
1042
1160
  this._requestBodyBytesLimit = input;
1043
1161
  return this;
1044
1162
  }
@@ -1047,6 +1165,7 @@ __name(_RouterOptions, "RouterOptions");
1047
1165
  var RouterOptions = _RouterOptions;
1048
1166
 
1049
1167
  // src/parsers/body-parser.js
1168
+ var import_js_format14 = require("@e22m4u/js-format");
1050
1169
  var METHODS_WITH_BODY = ["POST", "PUT", "PATCH", "DELETE"];
1051
1170
  var UNPARSABLE_MEDIA_TYPES = ["multipart/form-data"];
1052
1171
  var _BodyParser = class _BodyParser extends DebuggableService {
@@ -1067,16 +1186,18 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1067
1186
  * @returns {this}
1068
1187
  */
1069
1188
  defineParser(mediaType, parser) {
1070
- if (!mediaType || typeof mediaType !== "string")
1071
- throw new import_js_format15.Errorf(
1072
- 'The parameter "mediaType" of BodyParser.defineParser should be a non-empty String, but %v was given.',
1189
+ if (!mediaType || typeof mediaType !== "string") {
1190
+ throw new import_js_format14.InvalidArgumentError(
1191
+ 'The parameter "mediaType" of BodyParser.defineParser must be a non-empty String, but %v was given.',
1073
1192
  mediaType
1074
1193
  );
1075
- if (!parser || typeof parser !== "function")
1076
- throw new import_js_format15.Errorf(
1077
- 'The parameter "parser" of BodyParser.defineParser should be a Function, but %v was given.',
1194
+ }
1195
+ if (!parser || typeof parser !== "function") {
1196
+ throw new import_js_format14.InvalidArgumentError(
1197
+ 'The parameter "parser" of BodyParser.defineParser must be a Function, but %v was given.',
1078
1198
  parser
1079
1199
  );
1200
+ }
1080
1201
  this._parsers[mediaType] = parser;
1081
1202
  return this;
1082
1203
  }
@@ -1087,11 +1208,12 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1087
1208
  * @returns {boolean}
1088
1209
  */
1089
1210
  hasParser(mediaType) {
1090
- if (!mediaType || typeof mediaType !== "string")
1091
- throw new import_js_format15.Errorf(
1092
- 'The parameter "mediaType" of BodyParser.hasParser should be a non-empty String, but %v was given.',
1211
+ if (!mediaType || typeof mediaType !== "string") {
1212
+ throw new import_js_format14.InvalidArgumentError(
1213
+ 'The parameter "mediaType" of BodyParser.hasParser must be a non-empty String, but %v was given.',
1093
1214
  mediaType
1094
1215
  );
1216
+ }
1095
1217
  return Boolean(this._parsers[mediaType]);
1096
1218
  }
1097
1219
  /**
@@ -1101,13 +1223,19 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1101
1223
  * @returns {this}
1102
1224
  */
1103
1225
  deleteParser(mediaType) {
1104
- if (!mediaType || typeof mediaType !== "string")
1105
- throw new import_js_format15.Errorf(
1106
- 'The parameter "mediaType" of BodyParser.deleteParser should be a non-empty String, but %v was given.',
1226
+ if (!mediaType || typeof mediaType !== "string") {
1227
+ throw new import_js_format14.InvalidArgumentError(
1228
+ 'The parameter "mediaType" of BodyParser.deleteParser must be a non-empty String, but %v was given.',
1107
1229
  mediaType
1108
1230
  );
1231
+ }
1109
1232
  const parser = this._parsers[mediaType];
1110
- if (!parser) throw new import_js_format15.Errorf("The parser of %v is not found.", mediaType);
1233
+ if (!parser) {
1234
+ throw new import_js_format14.InvalidArgumentError(
1235
+ "The parser of %v is not found.",
1236
+ mediaType
1237
+ );
1238
+ }
1111
1239
  delete this._parsers[mediaType];
1112
1240
  return this;
1113
1241
  }
@@ -1137,11 +1265,12 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1137
1265
  return;
1138
1266
  }
1139
1267
  const { mediaType } = parseContentType(contentType);
1140
- if (!mediaType)
1268
+ if (!mediaType) {
1141
1269
  throw createError(
1142
1270
  import_http_errors2.default.BadRequest,
1143
1271
  'Unable to parse the "content-type" header.'
1144
1272
  );
1273
+ }
1145
1274
  const parser = this._parsers[mediaType];
1146
1275
  if (!parser) {
1147
1276
  if (UNPARSABLE_MEDIA_TYPES.includes(mediaType)) {
@@ -1156,7 +1285,9 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1156
1285
  }
1157
1286
  const bodyBytesLimit = this.getService(RouterOptions).requestBodyBytesLimit;
1158
1287
  return fetchRequestBody(request, bodyBytesLimit).then((rawBody) => {
1159
- if (rawBody != null) return parser(rawBody);
1288
+ if (rawBody != null) {
1289
+ return parser(rawBody);
1290
+ }
1160
1291
  return rawBody;
1161
1292
  });
1162
1293
  }
@@ -1164,7 +1295,9 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1164
1295
  __name(_BodyParser, "BodyParser");
1165
1296
  var BodyParser = _BodyParser;
1166
1297
  function parseJsonBody(input) {
1167
- if (typeof input !== "string") return void 0;
1298
+ if (typeof input !== "string") {
1299
+ return void 0;
1300
+ }
1168
1301
  try {
1169
1302
  return JSON.parse(input);
1170
1303
  } catch (error) {
@@ -1215,7 +1348,7 @@ var _CookiesParser = class _CookiesParser extends DebuggableService {
1215
1348
  parse(request) {
1216
1349
  const debug = this.getDebuggerFor(this.parse);
1217
1350
  const cookiesString = request.headers["cookie"] || "";
1218
- const cookies = parseCookies(cookiesString);
1351
+ const cookies = parseCookieString(cookiesString);
1219
1352
  const cookiesKeys = Object.keys(cookies);
1220
1353
  if (cookiesKeys.length) {
1221
1354
  cookiesKeys.forEach((key) => {
@@ -1236,7 +1369,7 @@ var CookiesParser = _CookiesParser;
1236
1369
 
1237
1370
  // src/parsers/request-parser.js
1238
1371
  var import_http3 = require("http");
1239
- var import_js_format16 = require("@e22m4u/js-format");
1372
+ var import_js_format15 = require("@e22m4u/js-format");
1240
1373
  var _RequestParser = class _RequestParser extends DebuggableService {
1241
1374
  /**
1242
1375
  * Parse.
@@ -1245,11 +1378,12 @@ var _RequestParser = class _RequestParser extends DebuggableService {
1245
1378
  * @returns {Promise<object>|object}
1246
1379
  */
1247
1380
  parse(request) {
1248
- if (!(request instanceof import_http3.IncomingMessage))
1249
- throw new import_js_format16.Errorf(
1250
- "The first argument of RequestParser.parse should be an instance of IncomingMessage, but %v was given.",
1381
+ if (!(request instanceof import_http3.IncomingMessage)) {
1382
+ throw new import_js_format15.InvalidArgumentError(
1383
+ "The first parameter of RequestParser.parse must be an instance of IncomingMessage, but %v was given.",
1251
1384
  request
1252
1385
  );
1386
+ }
1253
1387
  const data = {};
1254
1388
  const promises = [];
1255
1389
  const parsedQuery = this.getService(QueryParser).parse(request);
@@ -1278,9 +1412,9 @@ __name(_RequestParser, "RequestParser");
1278
1412
  var RequestParser = _RequestParser;
1279
1413
 
1280
1414
  // src/route-registry.js
1281
- var import_js_format17 = require("@e22m4u/js-format");
1282
1415
  var import_js_path_trie = require("@e22m4u/js-path-trie");
1283
1416
  var import_js_service2 = require("@e22m4u/js-service");
1417
+ var import_js_format16 = require("@e22m4u/js-format");
1284
1418
  var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1285
1419
  /**
1286
1420
  * Constructor.
@@ -1294,16 +1428,17 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1294
1428
  /**
1295
1429
  * Define route.
1296
1430
  *
1297
- * @param {import('./route.js').RouteDefinition} routeDef
1431
+ * @param {import('./route/index.js').RouteDefinition} routeDef
1298
1432
  * @returns {Route}
1299
1433
  */
1300
1434
  defineRoute(routeDef) {
1301
1435
  const debug = this.getDebuggerFor(this.defineRoute);
1302
- if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef))
1303
- throw new import_js_format17.Errorf(
1304
- "The route definition should be an Object, but %v was given.",
1436
+ if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef)) {
1437
+ throw new import_js_format16.InvalidArgumentError(
1438
+ "The route definition must be an Object, but %v was given.",
1305
1439
  routeDef
1306
1440
  );
1441
+ }
1307
1442
  const route = new Route(routeDef);
1308
1443
  const triePath = `${route.method}/${route.path}`;
1309
1444
  this._trie.add(triePath, route);
@@ -1322,14 +1457,14 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1322
1457
  */
1323
1458
  matchRouteByRequest(request) {
1324
1459
  const debug = this.getDebuggerFor(this.matchRouteByRequest);
1325
- const requestPath = (request.url || "/").replace(/\?.*$/, "");
1460
+ const requestPath = getRequestPathname(request);
1326
1461
  debug(
1327
1462
  "Matching routes with the request %s %v.",
1328
1463
  request.method.toUpperCase(),
1329
1464
  requestPath
1330
1465
  );
1331
1466
  const rawTriePath = `${request.method.toUpperCase()}/${requestPath}`;
1332
- const triePath = rawTriePath.replace(/\/+/g, "/");
1467
+ const triePath = rawTriePath.replace(/\/+/g, ROOT_PATH);
1333
1468
  const resolved = this._trie.match(triePath);
1334
1469
  if (resolved) {
1335
1470
  const route = resolved.value;
@@ -1363,7 +1498,7 @@ __name(_RouteRegistry, "RouteRegistry");
1363
1498
  var RouteRegistry = _RouteRegistry;
1364
1499
 
1365
1500
  // src/request-context.js
1366
- var import_js_format18 = require("@e22m4u/js-format");
1501
+ var import_js_format17 = require("@e22m4u/js-format");
1367
1502
  var import_js_service3 = require("@e22m4u/js-service");
1368
1503
  var _RequestContext = class _RequestContext {
1369
1504
  /**
@@ -1461,7 +1596,7 @@ var _RequestContext = class _RequestContext {
1461
1596
  /**
1462
1597
  * Route meta.
1463
1598
  *
1464
- * @type {import('./route.js').RouteMeta}
1599
+ * @type {import('./route/index.js').RouteMeta}
1465
1600
  */
1466
1601
  get meta() {
1467
1602
  return this.route.meta;
@@ -1495,7 +1630,9 @@ var _RequestContext = class _RequestContext {
1495
1630
  * @returns {string}
1496
1631
  */
1497
1632
  get pathname() {
1498
- if (this._pathname != null) return this._pathname;
1633
+ if (this._pathname != null) {
1634
+ return this._pathname;
1635
+ }
1499
1636
  this._pathname = getRequestPathname(this.request);
1500
1637
  return this._pathname;
1501
1638
  }
@@ -1508,29 +1645,30 @@ var _RequestContext = class _RequestContext {
1508
1645
  * @param {Route} route
1509
1646
  */
1510
1647
  constructor(container, request, response, route) {
1511
- if (!(0, import_js_service3.isServiceContainer)(container))
1512
- throw new import_js_format18.Errorf(
1513
- 'The parameter "container" of RequestContext.constructor should be an instance of ServiceContainer, but %v was given.',
1648
+ if (!(0, import_js_service3.isServiceContainer)(container)) {
1649
+ throw new import_js_format17.InvalidArgumentError(
1650
+ 'The parameter "container" of RequestContext.constructor must be an instance of ServiceContainer, but %v was given.',
1514
1651
  container
1515
1652
  );
1653
+ }
1516
1654
  this._container = container;
1517
1655
  if (!request || typeof request !== "object" || Array.isArray(request) || !isReadableStream(request)) {
1518
- throw new import_js_format18.Errorf(
1519
- 'The parameter "request" of RequestContext.constructor should be an instance of IncomingMessage, but %v was given.',
1656
+ throw new import_js_format17.InvalidArgumentError(
1657
+ 'The parameter "request" of RequestContext.constructor must be an instance of IncomingMessage, but %v was given.',
1520
1658
  request
1521
1659
  );
1522
1660
  }
1523
1661
  this._request = request;
1524
1662
  if (!response || typeof response !== "object" || Array.isArray(response) || !isWritableStream(response)) {
1525
- throw new import_js_format18.Errorf(
1526
- 'The parameter "response" of RequestContext.constructor should be an instance of ServerResponse, but %v was given.',
1663
+ throw new import_js_format17.InvalidArgumentError(
1664
+ 'The parameter "response" of RequestContext.constructor must be an instance of ServerResponse, but %v was given.',
1527
1665
  response
1528
1666
  );
1529
1667
  }
1530
1668
  this._response = response;
1531
1669
  if (!(route instanceof Route)) {
1532
- throw new import_js_format18.Errorf(
1533
- 'The parameter "route" of RequestContext.constructor should be an instance of Route, but %v was given.',
1670
+ throw new import_js_format17.InvalidArgumentError(
1671
+ 'The parameter "route" of RequestContext.constructor must be an instance of Route, but %v was given.',
1534
1672
  route
1535
1673
  );
1536
1674
  }
@@ -1545,7 +1683,7 @@ var import_js_service4 = require("@e22m4u/js-service");
1545
1683
  var import_http4 = require("http");
1546
1684
 
1547
1685
  // src/senders/data-sender.js
1548
- var import_js_format19 = require("@e22m4u/js-format");
1686
+ var import_js_format18 = require("@e22m4u/js-format");
1549
1687
  var _DataSender = class _DataSender extends DebuggableService {
1550
1688
  /**
1551
1689
  * Send.
@@ -1584,7 +1722,7 @@ var _DataSender = class _DataSender extends DebuggableService {
1584
1722
  debugMsg = "The Buffer was sent as binary data.";
1585
1723
  } else {
1586
1724
  response.setHeader("content-type", "application/json");
1587
- debugMsg = (0, import_js_format19.format)("The %v was sent as JSON.", typeof data);
1725
+ debugMsg = (0, import_js_format18.format)("The %v was sent as JSON.", typeof data);
1588
1726
  data = JSON.stringify(data);
1589
1727
  }
1590
1728
  break;
@@ -1632,7 +1770,9 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
1632
1770
  body.error.message = (0, import_statuses.default)(statusCode);
1633
1771
  }
1634
1772
  EXPOSED_ERROR_PROPERTIES.forEach((name) => {
1635
- if (name in safeError) body.error[name] = safeError[name];
1773
+ if (name in safeError) {
1774
+ body.error[name] = safeError[name];
1775
+ }
1636
1776
  });
1637
1777
  const requestData = {
1638
1778
  url: request.url,
@@ -1712,7 +1852,7 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1712
1852
  * ```
1713
1853
  *
1714
1854
  * @param {import('./route-registry.js').RouteDefinition} routeDef
1715
- * @returns {import('./route.js').Route}
1855
+ * @returns {import('./route/index.js').Route}
1716
1856
  */
1717
1857
  defineRoute(routeDef) {
1718
1858
  return this.getService(RouteRegistry).defineRoute(routeDef);
@@ -1746,7 +1886,7 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1746
1886
  */
1747
1887
  async _handleRequest(request, response) {
1748
1888
  const debug = this.getDebuggerFor(this._handleRequest);
1749
- const requestPath = (request.url || "/").replace(/\?.*$/, "");
1889
+ const requestPath = getRequestPathname(request);
1750
1890
  debug(
1751
1891
  "Preparing to handle an incoming request %s %v.",
1752
1892
  request.method,
@@ -1780,10 +1920,14 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1780
1920
  response,
1781
1921
  context
1782
1922
  );
1783
- if (isPromise(data)) data = await data;
1923
+ if (isPromise(data)) {
1924
+ data = await data;
1925
+ }
1784
1926
  if (!isResponseSent(response) && data == null) {
1785
1927
  data = route.handle(context);
1786
- if (isPromise(data)) data = await data;
1928
+ if (isPromise(data)) {
1929
+ data = await data;
1930
+ }
1787
1931
  let postHandlerData = hookInvoker.invokeAndContinueUntilValueReceived(
1788
1932
  route,
1789
1933
  RouterHookType.POST_HANDLER,
@@ -1791,9 +1935,12 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1791
1935
  context,
1792
1936
  data
1793
1937
  );
1794
- if (isPromise(postHandlerData))
1938
+ if (isPromise(postHandlerData)) {
1795
1939
  postHandlerData = await postHandlerData;
1796
- if (postHandlerData != null) data = postHandlerData;
1940
+ }
1941
+ if (postHandlerData != null) {
1942
+ data = postHandlerData;
1943
+ }
1797
1944
  }
1798
1945
  } catch (error) {
1799
1946
  this.getService(ErrorSender).send(request, response, error);
@@ -1872,6 +2019,7 @@ var TrieRouter = _TrieRouter;
1872
2019
  HttpMethod,
1873
2020
  METHODS_WITH_BODY,
1874
2021
  QueryParser,
2022
+ ROOT_PATH,
1875
2023
  RequestContext,
1876
2024
  RequestParser,
1877
2025
  Route,
@@ -1881,8 +2029,7 @@ var TrieRouter = _TrieRouter;
1881
2029
  TrieRouter,
1882
2030
  UNPARSABLE_MEDIA_TYPES,
1883
2031
  cloneDeep,
1884
- createCookiesString,
1885
- createDebugger,
2032
+ createCookieString,
1886
2033
  createError,
1887
2034
  createRequestMock,
1888
2035
  createResponseMock,
@@ -1894,7 +2041,8 @@ var TrieRouter = _TrieRouter;
1894
2041
  isResponseSent,
1895
2042
  isWritableStream,
1896
2043
  parseContentType,
1897
- parseCookies,
2044
+ parseCookieString,
1898
2045
  parseJsonBody,
1899
- toCamelCase
2046
+ toCamelCase,
2047
+ validateRouteDefinition
1900
2048
  });