@e22m4u/js-trie-router 0.2.1 → 0.3.0

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 (69) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/index.cjs +225 -213
  3. package/examples/{cookie-parsing-example.js → cookies-parsing-example.js} +8 -8
  4. package/examples/params-parsing-example.js +11 -7
  5. package/examples/query-parsing-example.js +11 -7
  6. package/examples/uptime-example.js +4 -4
  7. package/package.json +8 -7
  8. package/src/debuggable-service.d.ts +2 -10
  9. package/src/debuggable-service.js +16 -17
  10. package/src/hooks/hook-invoker.js +3 -4
  11. package/src/hooks/hook-invoker.spec.js +3 -3
  12. package/src/hooks/hook-registry.d.ts +1 -1
  13. package/src/hooks/hook-registry.js +6 -7
  14. package/src/hooks/hook-registry.spec.js +14 -5
  15. package/src/parsers/body-parser.js +10 -11
  16. package/src/parsers/body-parser.spec.js +4 -4
  17. package/src/parsers/cookies-parser.d.ts +15 -0
  18. package/src/parsers/cookies-parser.js +33 -0
  19. package/src/parsers/{cookie-parser.spec.js → cookies-parser.spec.js} +6 -6
  20. package/src/parsers/index.d.ts +1 -1
  21. package/src/parsers/index.js +1 -1
  22. package/src/parsers/query-parser.js +4 -3
  23. package/src/parsers/request-parser.d.ts +2 -2
  24. package/src/parsers/request-parser.js +7 -7
  25. package/src/parsers/request-parser.spec.js +12 -12
  26. package/src/request-context.d.ts +3 -3
  27. package/src/request-context.js +5 -5
  28. package/src/request-context.spec.js +3 -3
  29. package/src/route-registry.js +14 -14
  30. package/src/route-registry.spec.js +4 -1
  31. package/src/route.d.ts +12 -7
  32. package/src/route.js +16 -14
  33. package/src/route.spec.js +13 -7
  34. package/src/router-options.js +1 -1
  35. package/src/router-options.spec.js +1 -1
  36. package/src/senders/data-sender.js +6 -5
  37. package/src/senders/error-sender.js +11 -4
  38. package/src/trie-router.js +46 -38
  39. package/src/trie-router.spec.js +54 -3
  40. package/src/utils/create-cookies-string.d.ts +6 -0
  41. package/src/utils/{create-cookie-string.js → create-cookies-string.js} +4 -4
  42. package/src/utils/{create-cookie-string.spec.js → create-cookies-string.spec.js} +7 -7
  43. package/src/utils/create-debugger.js +1 -1
  44. package/src/utils/create-debugger.spec.js +1 -1
  45. package/src/utils/create-error.js +2 -2
  46. package/src/utils/create-error.spec.js +2 -2
  47. package/src/utils/create-request-mock.d.ts +1 -1
  48. package/src/utils/create-request-mock.js +47 -43
  49. package/src/utils/create-request-mock.spec.js +18 -18
  50. package/src/utils/fetch-request-body.d.ts +11 -2
  51. package/src/utils/fetch-request-body.js +10 -17
  52. package/src/utils/fetch-request-body.spec.js +8 -9
  53. package/src/utils/get-request-pathname.js +1 -1
  54. package/src/utils/get-request-pathname.spec.js +1 -1
  55. package/src/utils/index.d.ts +2 -2
  56. package/src/utils/index.js +2 -2
  57. package/src/utils/is-readable-stream.js +1 -2
  58. package/src/utils/is-response-sent.js +1 -1
  59. package/src/utils/is-response-sent.spec.js +1 -1
  60. package/src/utils/parse-content-type.js +1 -1
  61. package/src/utils/parse-cookies.d.ts +19 -0
  62. package/src/utils/{parse-cookie.js → parse-cookies.js} +8 -5
  63. package/src/utils/{parse-cookie.spec.js → parse-cookies.spec.js} +13 -8
  64. package/src/utils/to-camel-case.js +1 -1
  65. package/src/utils/to-camel-case.spec.js +1 -1
  66. package/src/parsers/cookie-parser.d.ts +0 -15
  67. package/src/parsers/cookie-parser.js +0 -32
  68. package/src/utils/create-cookie-string.d.ts +0 -6
  69. package/src/utils/parse-cookie.d.ts +0 -19
@@ -31,9 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.js
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
- BUFFER_ENCODING_LIST: () => BUFFER_ENCODING_LIST,
35
34
  BodyParser: () => BodyParser,
36
- CookieParser: () => CookieParser,
35
+ CHARACTER_ENCODING_LIST: () => CHARACTER_ENCODING_LIST,
36
+ CookiesParser: () => CookiesParser,
37
37
  DataSender: () => DataSender,
38
38
  EXPOSED_ERROR_PROPERTIES: () => EXPOSED_ERROR_PROPERTIES,
39
39
  ErrorSender: () => ErrorSender,
@@ -50,7 +50,7 @@ __export(index_exports, {
50
50
  RouterOptions: () => RouterOptions,
51
51
  TrieRouter: () => TrieRouter,
52
52
  UNPARSABLE_MEDIA_TYPES: () => UNPARSABLE_MEDIA_TYPES,
53
- createCookieString: () => createCookieString,
53
+ createCookiesString: () => createCookiesString,
54
54
  createDebugger: () => createDebugger,
55
55
  createError: () => createError,
56
56
  createRequestMock: () => createRequestMock,
@@ -62,7 +62,7 @@ __export(index_exports, {
62
62
  isResponseSent: () => isResponseSent,
63
63
  isWritableStream: () => isWritableStream,
64
64
  parseContentType: () => parseContentType,
65
- parseCookie: () => parseCookie,
65
+ parseCookies: () => parseCookies,
66
66
  parseJsonBody: () => parseJsonBody,
67
67
  toCamelCase: () => toCamelCase
68
68
  });
@@ -82,48 +82,49 @@ function isPromise(value) {
82
82
  }
83
83
  __name(isPromise, "isPromise");
84
84
 
85
- // src/utils/parse-cookie.js
86
- var import_js_format = require("@e22m4u/js-format");
87
- function parseCookie(input) {
88
- if (typeof input !== "string")
89
- throw new import_js_format.Errorf(
90
- 'The first parameter of "parseCookie" should be a String, but %v given.',
91
- input
92
- );
93
- return input.split(";").filter((v) => v !== "").map((v) => v.split("=")).reduce((cookies, tuple) => {
94
- const key = decodeURIComponent(tuple[0]).trim();
95
- cookies[key] = decodeURIComponent(tuple[1]).trim();
96
- return cookies;
97
- }, {});
98
- }
99
- __name(parseCookie, "parseCookie");
100
-
101
85
  // src/utils/create-error.js
86
+ var import_js_format = require("@e22m4u/js-format");
102
87
  var import_js_format2 = require("@e22m4u/js-format");
103
- var import_js_format3 = require("@e22m4u/js-format");
104
88
  function createError(errorCtor, message, ...args) {
105
89
  if (typeof errorCtor !== "function")
106
- throw new import_js_format3.Errorf(
107
- 'The first argument of "createError" should be a constructor, but %v given.',
90
+ throw new import_js_format2.Errorf(
91
+ 'The first argument of "createError" should be a constructor, but %v was given.',
108
92
  errorCtor
109
93
  );
110
94
  if (message != null && typeof message !== "string")
111
- throw new import_js_format3.Errorf(
112
- 'The second argument of "createError" should be a String, but %v given.',
95
+ throw new import_js_format2.Errorf(
96
+ 'The second argument of "createError" should be a String, but %v was given.',
113
97
  message
114
98
  );
115
99
  if (message == null) return new errorCtor();
116
- const interpolatedMessage = (0, import_js_format2.format)(message, ...args);
100
+ const interpolatedMessage = (0, import_js_format.format)(message, ...args);
117
101
  return new errorCtor(interpolatedMessage);
118
102
  }
119
103
  __name(createError, "createError");
120
104
 
105
+ // src/utils/parse-cookies.js
106
+ var import_js_format3 = require("@e22m4u/js-format");
107
+ function parseCookies(input) {
108
+ if (typeof input !== "string")
109
+ throw new import_js_format3.Errorf(
110
+ 'The first parameter of "parseCookies" should be a String, but %v was given.',
111
+ input
112
+ );
113
+ return input.split(";").filter((v) => v !== "").map((v) => v.split("=")).reduce((cookies, tuple) => {
114
+ const key = decodeURIComponent(tuple[0]).trim();
115
+ const value = tuple[1] !== void 0 ? decodeURIComponent(tuple[1]).trim() : "";
116
+ cookies[key] = value;
117
+ return cookies;
118
+ }, {});
119
+ }
120
+ __name(parseCookies, "parseCookies");
121
+
121
122
  // src/utils/to-camel-case.js
122
123
  var import_js_format4 = require("@e22m4u/js-format");
123
124
  function toCamelCase(input) {
124
125
  if (typeof input !== "string")
125
126
  throw new import_js_format4.Errorf(
126
- 'The first argument of "toCamelCase" should be a String, but %v given.',
127
+ 'The first argument of "toCamelCase" should be a String, but %v was given.',
127
128
  input
128
129
  );
129
130
  return input.replace(/(^\w|[A-Z]|\b\w)/g, (c) => c.toUpperCase()).replace(/\W+/g, "").replace(/(^\w)/g, (c) => c.toLowerCase());
@@ -136,13 +137,13 @@ var import_js_format5 = require("@e22m4u/js-format");
136
137
  function createDebugger(name) {
137
138
  if (typeof name !== "string")
138
139
  throw new import_js_format5.Errorf(
139
- 'The first argument of "createDebugger" should be a String, but %v given.',
140
+ 'The first argument of "createDebugger" should be a String, but %v was given.',
140
141
  name
141
142
  );
142
- const debug2 = (0, import_debug.default)(`jsTrieRouter:${name}`);
143
+ const debug = (0, import_debug.default)(`jsTrieRouter:${name}`);
143
144
  return function(message, ...args) {
144
145
  const interpolatedMessage = (0, import_js_format5.format)(message, ...args);
145
- return debug2(interpolatedMessage);
146
+ return debug(interpolatedMessage);
146
147
  };
147
148
  }
148
149
  __name(createDebugger, "createDebugger");
@@ -152,7 +153,7 @@ var import_js_format6 = require("@e22m4u/js-format");
152
153
  function isResponseSent(res) {
153
154
  if (!res || typeof res !== "object" || Array.isArray(res) || typeof res.headersSent !== "boolean") {
154
155
  throw new import_js_format6.Errorf(
155
- 'The first argument of "isResponseSent" should be an instance of ServerResponse, but %v given.',
156
+ 'The first argument of "isResponseSent" should be an instance of ServerResponse, but %v was given.',
156
157
  res
157
158
  );
158
159
  }
@@ -172,7 +173,7 @@ var import_js_format7 = require("@e22m4u/js-format");
172
173
  function parseContentType(input) {
173
174
  if (typeof input !== "string")
174
175
  throw new import_js_format7.Errorf(
175
- 'The parameter "input" of "parseContentType" should be a String, but %v given.',
176
+ 'The parameter "input" of "parseContentType" should be a String, but %v was given.',
176
177
  input
177
178
  );
178
179
  const res = { mediaType: void 0, charset: void 0, boundary: void 0 };
@@ -196,9 +197,9 @@ __name(isWritableStream, "isWritableStream");
196
197
 
197
198
  // src/utils/fetch-request-body.js
198
199
  var import_http_errors = __toESM(require("http-errors"), 1);
199
- var import_js_format8 = require("@e22m4u/js-format");
200
200
  var import_http = require("http");
201
- var BUFFER_ENCODING_LIST = [
201
+ var import_js_format8 = require("@e22m4u/js-format");
202
+ var CHARACTER_ENCODING_LIST = [
202
203
  "ascii",
203
204
  "utf8",
204
205
  "utf-8",
@@ -206,21 +207,17 @@ var BUFFER_ENCODING_LIST = [
206
207
  "utf-16le",
207
208
  "ucs2",
208
209
  "ucs-2",
209
- "base64",
210
- "base64url",
211
- "latin1",
212
- "binary",
213
- "hex"
210
+ "latin1"
214
211
  ];
215
212
  function fetchRequestBody(req, bodyBytesLimit = 0) {
216
213
  if (!(req instanceof import_http.IncomingMessage))
217
214
  throw new import_js_format8.Errorf(
218
- 'The first parameter of "fetchRequestBody" should be an IncomingMessage instance, but %v given.',
215
+ 'The first parameter of "fetchRequestBody" should be an IncomingMessage instance, but %v was given.',
219
216
  req
220
217
  );
221
218
  if (typeof bodyBytesLimit !== "number")
222
219
  throw new import_js_format8.Errorf(
223
- 'The parameter "bodyBytesLimit" of "fetchRequestBody" should be a number, but %v given.',
220
+ 'The parameter "bodyBytesLimit" of "fetchRequestBody" should be a number, but %v was given.',
224
221
  bodyBytesLimit
225
222
  );
226
223
  return new Promise((resolve, reject) => {
@@ -238,7 +235,7 @@ function fetchRequestBody(req, bodyBytesLimit = 0) {
238
235
  const parsedContentType = parseContentType(contentType);
239
236
  if (parsedContentType && parsedContentType.charset) {
240
237
  encoding = parsedContentType.charset.toLowerCase();
241
- if (!BUFFER_ENCODING_LIST.includes(encoding))
238
+ if (!CHARACTER_ENCODING_LIST.includes(encoding))
242
239
  throw createError(
243
240
  import_http_errors.default.UnsupportedMediaType,
244
241
  "Request encoding %v is not supported.",
@@ -274,7 +271,7 @@ function fetchRequestBody(req, bodyBytesLimit = 0) {
274
271
  return;
275
272
  }
276
273
  const buffer = Buffer.concat(data);
277
- const body = Buffer.from(buffer, encoding).toString();
274
+ const body = buffer.toString(encoding);
278
275
  resolve(body || void 0);
279
276
  }, "onEnd");
280
277
  const onError = /* @__PURE__ */ __name((error) => {
@@ -296,12 +293,12 @@ var import_http2 = require("http");
296
293
  var import_querystring = __toESM(require("querystring"), 1);
297
294
  var import_js_format10 = require("@e22m4u/js-format");
298
295
 
299
- // src/utils/create-cookie-string.js
296
+ // src/utils/create-cookies-string.js
300
297
  var import_js_format9 = require("@e22m4u/js-format");
301
- function createCookieString(data) {
298
+ function createCookiesString(data) {
302
299
  if (!data || typeof data !== "object" || Array.isArray(data))
303
300
  throw new import_js_format9.Errorf(
304
- 'The first parameter of "createCookieString" should be an Object, but %v given.',
301
+ 'The first parameter of "createCookiesString" should be an Object, but %v was given.',
305
302
  data
306
303
  );
307
304
  let cookies = "";
@@ -313,68 +310,71 @@ function createCookieString(data) {
313
310
  }
314
311
  return cookies.trim();
315
312
  }
316
- __name(createCookieString, "createCookieString");
313
+ __name(createCookiesString, "createCookiesString");
317
314
 
318
315
  // src/utils/create-request-mock.js
319
316
  function createRequestMock(patch) {
320
317
  if (patch != null && typeof patch !== "object" || Array.isArray(patch)) {
321
318
  throw new import_js_format10.Errorf(
322
- 'The first parameter of "createRequestMock" should be an Object, but %v given.',
319
+ 'The first parameter of "createRequestMock" should be an Object, but %v was given.',
323
320
  patch
324
321
  );
325
322
  }
326
323
  patch = patch || {};
327
324
  if (patch.host != null && typeof patch.host !== "string")
328
325
  throw new import_js_format10.Errorf(
329
- 'The parameter "host" of "createRequestMock" should be a String, but %v given.',
326
+ 'The parameter "host" of "createRequestMock" should be a String, but %v was given.',
330
327
  patch.host
331
328
  );
332
329
  if (patch.method != null && typeof patch.method !== "string")
333
330
  throw new import_js_format10.Errorf(
334
- 'The parameter "method" of "createRequestMock" should be a String, but %v given.',
331
+ 'The parameter "method" of "createRequestMock" should be a String, but %v was given.',
335
332
  patch.method
336
333
  );
337
334
  if (patch.secure != null && typeof patch.secure !== "boolean")
338
335
  throw new import_js_format10.Errorf(
339
- 'The parameter "secure" of "createRequestMock" should be a Boolean, but %v given.',
336
+ 'The parameter "secure" of "createRequestMock" should be a Boolean, but %v was given.',
340
337
  patch.secure
341
338
  );
342
339
  if (patch.path != null && typeof patch.path !== "string")
343
340
  throw new import_js_format10.Errorf(
344
- 'The parameter "path" of "createRequestMock" should be a String, but %v given.',
341
+ 'The parameter "path" of "createRequestMock" should be a String, but %v was given.',
345
342
  patch.path
346
343
  );
347
344
  if (patch.query != null && typeof patch.query !== "object" && typeof patch.query !== "string" || Array.isArray(patch.query)) {
348
345
  throw new import_js_format10.Errorf(
349
- 'The parameter "query" of "createRequestMock" should be a String or Object, but %v given.',
346
+ 'The parameter "query" of "createRequestMock" should be a String or Object, but %v was given.',
350
347
  patch.query
351
348
  );
352
349
  }
353
- if (patch.cookie != null && typeof patch.cookie !== "string" && typeof patch.cookie !== "object" || Array.isArray(patch.cookie)) {
350
+ if (patch.cookies != null && typeof patch.cookies !== "string" && typeof patch.cookies !== "object" || Array.isArray(patch.cookies)) {
354
351
  throw new import_js_format10.Errorf(
355
- 'The parameter "cookie" of "createRequestMock" should be a String or Object, but %v given.',
356
- patch.cookie
352
+ 'The parameter "cookies" of "createRequestMock" should be a String or Object, but %v was given.',
353
+ patch.cookies
357
354
  );
358
355
  }
359
356
  if (patch.headers != null && typeof patch.headers !== "object" || Array.isArray(patch.headers)) {
360
357
  throw new import_js_format10.Errorf(
361
- 'The parameter "headers" of "createRequestMock" should be an Object, but %v given.',
358
+ 'The parameter "headers" of "createRequestMock" should be an Object, but %v was given.',
362
359
  patch.headers
363
360
  );
364
361
  }
365
362
  if (patch.stream != null && !isReadableStream(patch.stream))
366
363
  throw new import_js_format10.Errorf(
367
- 'The parameter "stream" of "createRequestMock" should be a Stream, but %v given.',
364
+ 'The parameter "stream" of "createRequestMock" should be a Stream, but %v was given.',
368
365
  patch.stream
369
366
  );
370
367
  if (patch.encoding != null) {
371
368
  if (typeof patch.encoding !== "string")
372
369
  throw new import_js_format10.Errorf(
373
- 'The parameter "encoding" of "createRequestMock" should be a String, but %v given.',
370
+ 'The parameter "encoding" of "createRequestMock" should be a String, but %v was given.',
371
+ patch.encoding
372
+ );
373
+ if (!CHARACTER_ENCODING_LIST.includes(patch.encoding))
374
+ throw new import_js_format10.Errorf(
375
+ "Character encoding %v is not supported.",
374
376
  patch.encoding
375
377
  );
376
- if (!BUFFER_ENCODING_LIST.includes(patch.encoding))
377
- throw new import_js_format10.Errorf("Buffer encoding %v is not supported.", patch.encoding);
378
378
  }
379
379
  if (patch.stream) {
380
380
  if (patch.secure != null)
@@ -396,7 +396,7 @@ function createRequestMock(patch) {
396
396
  patch.host,
397
397
  patch.secure,
398
398
  patch.body,
399
- patch.cookie,
399
+ patch.cookies,
400
400
  patch.encoding,
401
401
  patch.headers
402
402
  );
@@ -407,7 +407,7 @@ __name(createRequestMock, "createRequestMock");
407
407
  function createRequestStream(secure, body, encoding) {
408
408
  if (encoding != null && typeof encoding !== "string")
409
409
  throw new import_js_format10.Errorf(
410
- 'The parameter "encoding" of "createRequestStream" should be a String, but %v given.',
410
+ 'The parameter "encoding" of "createRequestStream" should be a String, but %v was given.',
411
411
  encoding
412
412
  );
413
413
  encoding = encoding || "utf-8";
@@ -430,12 +430,12 @@ __name(createRequestStream, "createRequestStream");
430
430
  function createRequestUrl(path, query) {
431
431
  if (typeof path !== "string")
432
432
  throw new import_js_format10.Errorf(
433
- 'The parameter "path" of "createRequestUrl" should be a String, but %v given.',
433
+ 'The parameter "path" of "createRequestUrl" should be a String, but %v was given.',
434
434
  path
435
435
  );
436
436
  if (query != null && typeof query !== "string" && typeof query !== "object" || Array.isArray(query)) {
437
437
  throw new import_js_format10.Errorf(
438
- 'The parameter "query" of "createRequestUrl" should be a String or Object, but %v given.',
438
+ 'The parameter "query" of "createRequestUrl" should be a String or Object, but %v was given.',
439
439
  query
440
440
  );
441
441
  }
@@ -449,48 +449,49 @@ function createRequestUrl(path, query) {
449
449
  return url;
450
450
  }
451
451
  __name(createRequestUrl, "createRequestUrl");
452
- function createRequestHeaders(host, secure, body, cookie, encoding, headers) {
452
+ function createRequestHeaders(host, secure, body, cookies, encoding, headers) {
453
453
  if (host != null && typeof host !== "string")
454
454
  throw new import_js_format10.Errorf(
455
- 'The parameter "host" of "createRequestHeaders" a non-empty String, but %v given.',
455
+ 'The parameter "host" of "createRequestHeaders" a non-empty String, but %v was given.',
456
456
  host
457
457
  );
458
458
  host = host || "localhost";
459
459
  if (secure != null && typeof secure !== "boolean")
460
460
  throw new import_js_format10.Errorf(
461
- 'The parameter "secure" of "createRequestHeaders" should be a String, but %v given.',
461
+ 'The parameter "secure" of "createRequestHeaders" should be a String, but %v was given.',
462
462
  secure
463
463
  );
464
464
  secure = Boolean(secure);
465
- if (cookie != null && typeof cookie !== "object" && typeof cookie !== "string" || Array.isArray(cookie)) {
465
+ if (cookies != null && typeof cookies !== "object" && typeof cookies !== "string" || Array.isArray(cookies)) {
466
466
  throw new import_js_format10.Errorf(
467
- 'The parameter "cookie" of "createRequestHeaders" should be a String or Object, but %v given.',
468
- cookie
467
+ 'The parameter "cookies" of "createRequestHeaders" should be a String or Object, but %v was given.',
468
+ cookies
469
469
  );
470
470
  }
471
471
  if (headers != null && typeof headers !== "object" || Array.isArray(headers)) {
472
472
  throw new import_js_format10.Errorf(
473
- 'The parameter "headers" of "createRequestHeaders" should be an Object, but %v given.',
473
+ 'The parameter "headers" of "createRequestHeaders" should be an Object, but %v was given.',
474
474
  headers
475
475
  );
476
476
  }
477
477
  headers = headers || {};
478
478
  if (encoding != null && typeof encoding !== "string")
479
479
  throw new import_js_format10.Errorf(
480
- 'The parameter "encoding" of "createRequestHeaders" should be a String, but %v given.',
480
+ 'The parameter "encoding" of "createRequestHeaders" should be a String, but %v was given.',
481
481
  encoding
482
482
  );
483
483
  encoding = encoding || "utf-8";
484
484
  const obj = { ...headers };
485
485
  obj["host"] = host;
486
486
  if (secure) obj["x-forwarded-proto"] = "https";
487
- if (cookie != null) {
488
- if (typeof cookie === "string") {
487
+ if (cookies != null) {
488
+ if (typeof cookies === "string") {
489
489
  obj["cookie"] = obj["cookie"] ? obj["cookie"] : "";
490
- obj["cookie"] += cookie;
491
- } else if (typeof cookie === "object") {
490
+ obj["cookie"] += obj["cookie"] ? `; ${cookies}` : cookies;
491
+ } else if (typeof cookies === "object") {
492
492
  obj["cookie"] = obj["cookie"] ? obj["cookie"] : "";
493
- obj["cookie"] += createCookieString(cookie);
493
+ const newCookies = createCookiesString(cookies);
494
+ obj["cookie"] += obj["cookie"] ? `; ${newCookies}` : newCookies;
494
495
  }
495
496
  }
496
497
  if (obj["content-type"] == null) {
@@ -624,7 +625,7 @@ var import_js_format11 = require("@e22m4u/js-format");
624
625
  function getRequestPathname(req) {
625
626
  if (!req || typeof req !== "object" || Array.isArray(req) || typeof req.url !== "string") {
626
627
  throw new import_js_format11.Errorf(
627
- 'The first argument of "getRequestPathname" should be an instance of IncomingMessage, but %v given.',
628
+ 'The first argument of "getRequestPathname" should be an instance of IncomingMessage, but %v was given.',
628
629
  req
629
630
  );
630
631
  }
@@ -634,38 +635,11 @@ __name(getRequestPathname, "getRequestPathname");
634
635
 
635
636
  // src/hooks/hook-registry.js
636
637
  var import_js_format12 = require("@e22m4u/js-format");
637
-
638
- // src/debuggable-service.js
639
- var import_js_service = require("@e22m4u/js-service");
640
- var import_js_service2 = require("@e22m4u/js-service");
641
- var _DebuggableService = class _DebuggableService extends import_js_service.Service {
642
- /**
643
- * Debug.
644
- *
645
- * @type {Function}
646
- */
647
- debug;
648
- /**
649
- * Constructor.
650
- *
651
- * @param {ServiceContainer} container
652
- */
653
- constructor(container) {
654
- super(container);
655
- const serviceName = toCamelCase(this.constructor.name);
656
- this.debug = createDebugger(serviceName);
657
- this.debug("The %v is created.", this.constructor);
658
- }
659
- };
660
- __name(_DebuggableService, "DebuggableService");
661
- var DebuggableService = _DebuggableService;
662
-
663
- // src/hooks/hook-registry.js
664
638
  var HookType = {
665
639
  PRE_HANDLER: "preHandler",
666
640
  POST_HANDLER: "postHandler"
667
641
  };
668
- var _HookRegistry = class _HookRegistry extends DebuggableService {
642
+ var _HookRegistry = class _HookRegistry {
669
643
  /**
670
644
  * Hooks.
671
645
  *
@@ -682,12 +656,12 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
682
656
  */
683
657
  addHook(type, hook) {
684
658
  if (!type || typeof type !== "string")
685
- throw new import_js_format12.Errorf("The hook type is required, but %v given.", type);
659
+ throw new import_js_format12.Errorf("The hook type is required, but %v was given.", type);
686
660
  if (!Object.values(HookType).includes(type))
687
661
  throw new import_js_format12.Errorf("The hook type %v is not supported.", type);
688
662
  if (!hook || typeof hook !== "function")
689
663
  throw new import_js_format12.Errorf(
690
- "The hook %v should be a Function, but %v given.",
664
+ "The hook %v should be a Function, but %v was given.",
691
665
  type,
692
666
  hook
693
667
  );
@@ -705,12 +679,12 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
705
679
  */
706
680
  hasHook(type, hook) {
707
681
  if (!type || typeof type !== "string")
708
- throw new import_js_format12.Errorf("The hook type is required, but %v given.", type);
682
+ throw new import_js_format12.Errorf("The hook type is required, but %v was given.", type);
709
683
  if (!Object.values(HookType).includes(type))
710
684
  throw new import_js_format12.Errorf("The hook type %v is not supported.", type);
711
685
  if (!hook || typeof hook !== "function")
712
686
  throw new import_js_format12.Errorf(
713
- "The hook %v should be a Function, but %v given.",
687
+ "The hook %v should be a Function, but %v was given.",
714
688
  type,
715
689
  hook
716
690
  );
@@ -725,7 +699,7 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
725
699
  */
726
700
  getHooks(type) {
727
701
  if (!type || typeof type !== "string")
728
- throw new import_js_format12.Errorf("The hook type is required, but %v given.", type);
702
+ throw new import_js_format12.Errorf("The hook type is required, but %v was given.", type);
729
703
  if (!Object.values(HookType).includes(type))
730
704
  throw new import_js_format12.Errorf("The hook type %v is not supported.", type);
731
705
  return this._hooks.get(type) || [];
@@ -734,6 +708,25 @@ var _HookRegistry = class _HookRegistry extends DebuggableService {
734
708
  __name(_HookRegistry, "HookRegistry");
735
709
  var HookRegistry = _HookRegistry;
736
710
 
711
+ // src/debuggable-service.js
712
+ var import_js_service = require("@e22m4u/js-service");
713
+ var MODULE_DEBUG_NAMESPACE = "jsTrieRouter";
714
+ var _DebuggableService = class _DebuggableService extends import_js_service.DebuggableService {
715
+ /**
716
+ * Constructor.
717
+ *
718
+ * @param {ServiceContainer} container
719
+ */
720
+ constructor(container = void 0) {
721
+ super(container, {
722
+ namespace: MODULE_DEBUG_NAMESPACE,
723
+ noEnvironmentNamespace: true
724
+ });
725
+ }
726
+ };
727
+ __name(_DebuggableService, "DebuggableService");
728
+ var DebuggableService = _DebuggableService;
729
+
737
730
  // src/hooks/hook-invoker.js
738
731
  var _HookInvoker = class _HookInvoker extends DebuggableService {
739
732
  /**
@@ -748,19 +741,19 @@ var _HookInvoker = class _HookInvoker extends DebuggableService {
748
741
  invokeAndContinueUntilValueReceived(route, hookType, response, ...args) {
749
742
  if (!route || !(route instanceof Route))
750
743
  throw new import_js_format13.Errorf(
751
- 'The parameter "route" of the HookInvoker.invokeAndContinueUntilValueReceived should be a Route instance, but %v given.',
744
+ 'The parameter "route" of the HookInvoker.invokeAndContinueUntilValueReceived should be a Route instance, but %v was given.',
752
745
  route
753
746
  );
754
747
  if (!hookType || typeof hookType !== "string")
755
748
  throw new import_js_format13.Errorf(
756
- 'The parameter "hookType" of the HookInvoker.invokeAndContinueUntilValueReceived should be a non-empty String, but %v given.',
749
+ 'The parameter "hookType" of the HookInvoker.invokeAndContinueUntilValueReceived should be a non-empty String, but %v was given.',
757
750
  hookType
758
751
  );
759
752
  if (!Object.values(HookType).includes(hookType))
760
753
  throw new import_js_format13.Errorf("The hook type %v is not supported.", hookType);
761
754
  if (!response || typeof response !== "object" || Array.isArray(response) || typeof response.headersSent !== "boolean") {
762
755
  throw new import_js_format13.Errorf(
763
- 'The parameter "response" of the HookInvoker.invokeAndContinueUntilValueReceived should be a ServerResponse instance, but %v given.',
756
+ 'The parameter "response" of the HookInvoker.invokeAndContinueUntilValueReceived should be a ServerResponse instance, but %v was given.',
764
757
  response
765
758
  );
766
759
  }
@@ -779,7 +772,6 @@ var _HookInvoker = class _HookInvoker extends DebuggableService {
779
772
  } else if (isPromise(result)) {
780
773
  result = result.then((prevVal) => {
781
774
  if (isResponseSent(response)) {
782
- result = response;
783
775
  return;
784
776
  }
785
777
  if (prevVal != null) return prevVal;
@@ -796,6 +788,7 @@ __name(_HookInvoker, "HookInvoker");
796
788
  var HookInvoker = _HookInvoker;
797
789
 
798
790
  // src/route.js
791
+ var import_js_debug = require("@e22m4u/js-debug");
799
792
  var HttpMethod = {
800
793
  GET: "GET",
801
794
  POST: "POST",
@@ -803,8 +796,7 @@ var HttpMethod = {
803
796
  PATCH: "PATCH",
804
797
  DELETE: "DELETE"
805
798
  };
806
- var debug = createDebugger("route");
807
- var _Route = class _Route {
799
+ var _Route = class _Route extends import_js_debug.Debuggable {
808
800
  /**
809
801
  * Method.
810
802
  *
@@ -871,26 +863,31 @@ var _Route = class _Route {
871
863
  * @param {RouteDefinition} routeDef
872
864
  */
873
865
  constructor(routeDef) {
866
+ super({
867
+ namespace: MODULE_DEBUG_NAMESPACE,
868
+ noEnvironmentNamespace: true,
869
+ noInstantiationMessage: true
870
+ });
874
871
  if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef))
875
872
  throw new import_js_format14.Errorf(
876
- "The first parameter of Route.controller should be an Object, but %v given.",
873
+ "The first parameter of Route.constructor should be an Object, but %v was given.",
877
874
  routeDef
878
875
  );
879
876
  if (!routeDef.method || typeof routeDef.method !== "string")
880
877
  throw new import_js_format14.Errorf(
881
- 'The option "method" of the Route should be a non-empty String, but %v given.',
878
+ 'The option "method" of the Route should be a non-empty String, but %v was given.',
882
879
  routeDef.method
883
880
  );
884
881
  this._method = routeDef.method.toUpperCase();
885
882
  if (typeof routeDef.path !== "string")
886
883
  throw new import_js_format14.Errorf(
887
- 'The option "path" of the Route should be a String, but %v given.',
884
+ 'The option "path" of the Route should be a String, but %v was given.',
888
885
  routeDef.path
889
886
  );
890
887
  this._path = routeDef.path;
891
888
  if (typeof routeDef.handler !== "function")
892
889
  throw new import_js_format14.Errorf(
893
- 'The option "handler" of the Route should be a Function, but %v given.',
890
+ 'The option "handler" of the Route should be a Function, but %v was given.',
894
891
  routeDef.handler
895
892
  );
896
893
  this._handler = routeDef.handler;
@@ -906,6 +903,7 @@ var _Route = class _Route {
906
903
  this._hookRegistry.addHook(HookType.POST_HANDLER, hook);
907
904
  });
908
905
  }
906
+ this.ctorDebug("A new route %s %v was created.", this._method, this._path);
909
907
  }
910
908
  /**
911
909
  * Handle request.
@@ -914,6 +912,7 @@ var _Route = class _Route {
914
912
  * @returns {*}
915
913
  */
916
914
  handle(context) {
915
+ const debug = this.getDebuggerFor(this.handle);
917
916
  const requestPath = getRequestPathname(context.req);
918
917
  debug(
919
918
  "Invoking the Route handler for the request %s %v.",
@@ -937,22 +936,23 @@ var _DataSender = class _DataSender extends DebuggableService {
937
936
  * @returns {undefined}
938
937
  */
939
938
  send(res, data) {
939
+ const debug = this.getDebuggerFor(this.send);
940
940
  if (data === res || res.headersSent) {
941
- this.debug(
942
- "Response sending was skipped because its headers where sent already ."
941
+ debug(
942
+ "Response sending was skipped because its headers where sent already."
943
943
  );
944
944
  return;
945
945
  }
946
946
  if (data == null) {
947
947
  res.statusCode = 204;
948
948
  res.end();
949
- this.debug("The empty response was sent.");
949
+ debug("The empty response was sent.");
950
950
  return;
951
951
  }
952
952
  if (isReadableStream(data)) {
953
953
  res.setHeader("Content-Type", "application/octet-stream");
954
954
  data.pipe(res);
955
- this.debug("The stream response was sent.");
955
+ debug("The stream response was sent.");
956
956
  return;
957
957
  }
958
958
  let debugMsg;
@@ -976,7 +976,7 @@ var _DataSender = class _DataSender extends DebuggableService {
976
976
  break;
977
977
  }
978
978
  res.end(data);
979
- this.debug(debugMsg);
979
+ debug(debugMsg);
980
980
  }
981
981
  };
982
982
  __name(_DataSender, "DataSender");
@@ -996,6 +996,7 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
996
996
  * @returns {undefined}
997
997
  */
998
998
  send(req, res, error) {
999
+ const debug = this.getDebuggerFor(this.send);
999
1000
  let safeError = {};
1000
1001
  if (error) {
1001
1002
  if (typeof error === "object") {
@@ -1027,11 +1028,16 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
1027
1028
  };
1028
1029
  console.warn((0, import_util.inspect)(requestData, inspectOptions));
1029
1030
  console.warn((0, import_util.inspect)(body, inspectOptions));
1031
+ if (error.stack) {
1032
+ console.log(error.stack);
1033
+ } else {
1034
+ console.error(error);
1035
+ }
1030
1036
  res.statusCode = statusCode;
1031
1037
  res.setHeader("content-type", "application/json; charset=utf-8");
1032
1038
  res.end(JSON.stringify(body, null, 2), "utf-8");
1033
- this.debug(
1034
- "The %s error is sent for the request %s %v.",
1039
+ debug(
1040
+ "The %s error was sent for the request %s %v.",
1035
1041
  statusCode,
1036
1042
  req.method,
1037
1043
  getRequestPathname(req)
@@ -1045,11 +1051,12 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
1045
1051
  * @returns {undefined}
1046
1052
  */
1047
1053
  send404(req, res) {
1054
+ const debug = this.getDebuggerFor(this.send404);
1048
1055
  res.statusCode = 404;
1049
1056
  res.setHeader("content-type", "text/plain; charset=utf-8");
1050
1057
  res.end("404 Not Found", "utf-8");
1051
- this.debug(
1052
- "The 404 error is sent for the request %s %v.",
1058
+ debug(
1059
+ "The 404 error was sent for the request %s %v.",
1053
1060
  req.method,
1054
1061
  getRequestPathname(req)
1055
1062
  );
@@ -1090,7 +1097,7 @@ var _RouterOptions = class _RouterOptions extends DebuggableService {
1090
1097
  setRequestBodyBytesLimit(input) {
1091
1098
  if (typeof input !== "number" || input < 0)
1092
1099
  throw new import_js_format16.Errorf(
1093
- 'The option "requestBodyBytesLimit" must be a positive Number or 0, but %v given.',
1100
+ 'The option "requestBodyBytesLimit" must be a positive Number or 0, but %v was given.',
1094
1101
  input
1095
1102
  );
1096
1103
  this._requestBodyBytesLimit = input;
@@ -1123,12 +1130,12 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1123
1130
  defineParser(mediaType, parser) {
1124
1131
  if (!mediaType || typeof mediaType !== "string")
1125
1132
  throw new import_js_format17.Errorf(
1126
- 'The parameter "mediaType" of BodyParser.defineParser should be a non-empty String, but %v given.',
1133
+ 'The parameter "mediaType" of BodyParser.defineParser should be a non-empty String, but %v was given.',
1127
1134
  mediaType
1128
1135
  );
1129
1136
  if (!parser || typeof parser !== "function")
1130
1137
  throw new import_js_format17.Errorf(
1131
- 'The parameter "parser" of BodyParser.defineParser should be a Function, but %v given.',
1138
+ 'The parameter "parser" of BodyParser.defineParser should be a Function, but %v was given.',
1132
1139
  parser
1133
1140
  );
1134
1141
  this._parsers[mediaType] = parser;
@@ -1143,7 +1150,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1143
1150
  hasParser(mediaType) {
1144
1151
  if (!mediaType || typeof mediaType !== "string")
1145
1152
  throw new import_js_format17.Errorf(
1146
- 'The parameter "mediaType" of BodyParser.hasParser should be a non-empty String, but %v given.',
1153
+ 'The parameter "mediaType" of BodyParser.hasParser should be a non-empty String, but %v was given.',
1147
1154
  mediaType
1148
1155
  );
1149
1156
  return Boolean(this._parsers[mediaType]);
@@ -1157,7 +1164,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1157
1164
  deleteParser(mediaType) {
1158
1165
  if (!mediaType || typeof mediaType !== "string")
1159
1166
  throw new import_js_format17.Errorf(
1160
- 'The parameter "mediaType" of BodyParser.deleteParser should be a non-empty String, but %v given.',
1167
+ 'The parameter "mediaType" of BodyParser.deleteParser should be a non-empty String, but %v was given.',
1161
1168
  mediaType
1162
1169
  );
1163
1170
  const parser = this._parsers[mediaType];
@@ -1172,8 +1179,9 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1172
1179
  * @returns {Promise<*>|undefined}
1173
1180
  */
1174
1181
  parse(req) {
1182
+ const debug = this.getDebuggerFor(this.parse);
1175
1183
  if (!METHODS_WITH_BODY.includes(req.method.toUpperCase())) {
1176
- this.debug(
1184
+ debug(
1177
1185
  "Body parsing was skipped for the %s request.",
1178
1186
  req.method.toUpperCase()
1179
1187
  );
@@ -1184,8 +1192,8 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1184
1192
  "$1"
1185
1193
  );
1186
1194
  if (!contentType) {
1187
- this.debug(
1188
- "Body parsing was skipped because the request has no content type."
1195
+ debug(
1196
+ "Body parsing was skipped because the request had no content type."
1189
1197
  );
1190
1198
  return;
1191
1199
  }
@@ -1198,7 +1206,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1198
1206
  const parser = this._parsers[mediaType];
1199
1207
  if (!parser) {
1200
1208
  if (UNPARSABLE_MEDIA_TYPES.includes(mediaType)) {
1201
- this.debug("Body parsing was skipped for %v.", mediaType);
1209
+ debug("Body parsing was skipped for %v.", mediaType);
1202
1210
  return;
1203
1211
  }
1204
1212
  throw createError(
@@ -1221,9 +1229,7 @@ function parseJsonBody(input) {
1221
1229
  try {
1222
1230
  return JSON.parse(input);
1223
1231
  } catch (error) {
1224
- if (process.env["DEBUG"] || process.env["NODE_ENV"] === "development")
1225
- console.warn(error);
1226
- throw createError(import_http_errors2.default.BadRequest, "Unable to parse request body.");
1232
+ throw createError(import_http_errors2.default.BadRequest, error.message);
1227
1233
  }
1228
1234
  }
1229
1235
  __name(parseJsonBody, "parseJsonBody");
@@ -1238,16 +1244,17 @@ var _QueryParser = class _QueryParser extends DebuggableService {
1238
1244
  * @returns {object}
1239
1245
  */
1240
1246
  parse(req) {
1247
+ const debug = this.getDebuggerFor(this.parse);
1241
1248
  const queryStr = req.url.replace(/^[^?]*\??/, "");
1242
1249
  const query = queryStr ? import_querystring2.default.parse(queryStr) : {};
1243
1250
  const queryKeys = Object.keys(query);
1244
1251
  if (queryKeys.length) {
1245
1252
  queryKeys.forEach((key) => {
1246
- this.debug("The query %v has the value %v.", key, query[key]);
1253
+ debug("The query parameter %v had the value %v.", key, query[key]);
1247
1254
  });
1248
1255
  } else {
1249
- this.debug(
1250
- "The request %s %v has no query.",
1256
+ debug(
1257
+ "The request %s %v had no query parameters.",
1251
1258
  req.method,
1252
1259
  getRequestPathname(req)
1253
1260
  );
@@ -1258,8 +1265,8 @@ var _QueryParser = class _QueryParser extends DebuggableService {
1258
1265
  __name(_QueryParser, "QueryParser");
1259
1266
  var QueryParser = _QueryParser;
1260
1267
 
1261
- // src/parsers/cookie-parser.js
1262
- var _CookieParser = class _CookieParser extends DebuggableService {
1268
+ // src/parsers/cookies-parser.js
1269
+ var _CookiesParser = class _CookiesParser extends DebuggableService {
1263
1270
  /**
1264
1271
  * Parse
1265
1272
  *
@@ -1267,25 +1274,26 @@ var _CookieParser = class _CookieParser extends DebuggableService {
1267
1274
  * @returns {object}
1268
1275
  */
1269
1276
  parse(req) {
1270
- const cookieString = req.headers["cookie"] || "";
1271
- const cookie = parseCookie(cookieString);
1272
- const cookieKeys = Object.keys(cookie);
1273
- if (cookieKeys.length) {
1274
- cookieKeys.forEach((key) => {
1275
- this.debug("The cookie %v has the value %v.", key, cookie[key]);
1277
+ const debug = this.getDebuggerFor(this.parse);
1278
+ const cookiesString = req.headers["cookie"] || "";
1279
+ const cookies = parseCookies(cookiesString);
1280
+ const cookiesKeys = Object.keys(cookies);
1281
+ if (cookiesKeys.length) {
1282
+ cookiesKeys.forEach((key) => {
1283
+ debug("The cookie %v had the value %v.", key, cookies[key]);
1276
1284
  });
1277
1285
  } else {
1278
- this.debug(
1279
- "The request %s %v has no cookie.",
1286
+ debug(
1287
+ "The request %s %v had no cookies.",
1280
1288
  req.method,
1281
1289
  getRequestPathname(req)
1282
1290
  );
1283
1291
  }
1284
- return cookie;
1292
+ return cookies;
1285
1293
  }
1286
1294
  };
1287
- __name(_CookieParser, "CookieParser");
1288
- var CookieParser = _CookieParser;
1295
+ __name(_CookiesParser, "CookiesParser");
1296
+ var CookiesParser = _CookiesParser;
1289
1297
 
1290
1298
  // src/parsers/request-parser.js
1291
1299
  var import_http3 = require("http");
@@ -1300,7 +1308,7 @@ var _RequestParser = class _RequestParser extends DebuggableService {
1300
1308
  parse(req) {
1301
1309
  if (!(req instanceof import_http3.IncomingMessage))
1302
1310
  throw new import_js_format18.Errorf(
1303
- "The first argument of RequestParser.parse should be an instance of IncomingMessage, but %v given.",
1311
+ "The first argument of RequestParser.parse should be an instance of IncomingMessage, but %v was given.",
1304
1312
  req
1305
1313
  );
1306
1314
  const data = {};
@@ -1311,11 +1319,11 @@ var _RequestParser = class _RequestParser extends DebuggableService {
1311
1319
  } else {
1312
1320
  data.query = parsedQuery;
1313
1321
  }
1314
- const parsedCookie = this.getService(CookieParser).parse(req);
1315
- if (isPromise(parsedCookie)) {
1316
- promises.push(parsedCookie.then((v) => data.cookie = v));
1322
+ const parsedCookies = this.getService(CookiesParser).parse(req);
1323
+ if (isPromise(parsedCookies)) {
1324
+ promises.push(parsedCookies.then((v) => data.cookies = v));
1317
1325
  } else {
1318
- data.cookie = parsedCookie;
1326
+ data.cookies = parsedCookies;
1319
1327
  }
1320
1328
  const parsedBody = this.getService(BodyParser).parse(req);
1321
1329
  if (isPromise(parsedBody)) {
@@ -1323,7 +1331,7 @@ var _RequestParser = class _RequestParser extends DebuggableService {
1323
1331
  } else {
1324
1332
  data.body = parsedBody;
1325
1333
  }
1326
- data.headers = JSON.parse(JSON.stringify(req.headers));
1334
+ data.headers = Object.assign({}, req.headers);
1327
1335
  return promises.length ? Promise.all(promises).then(() => data) : data;
1328
1336
  }
1329
1337
  };
@@ -1333,7 +1341,7 @@ var RequestParser = _RequestParser;
1333
1341
  // src/route-registry.js
1334
1342
  var import_js_format19 = require("@e22m4u/js-format");
1335
1343
  var import_js_path_trie = require("@e22m4u/js-path-trie");
1336
- var import_js_service3 = require("@e22m4u/js-service");
1344
+ var import_js_service2 = require("@e22m4u/js-service");
1337
1345
  var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1338
1346
  /**
1339
1347
  * Constructor.
@@ -1351,16 +1359,17 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1351
1359
  * @returns {Route}
1352
1360
  */
1353
1361
  defineRoute(routeDef) {
1362
+ const debug = this.getDebuggerFor(this.defineRoute);
1354
1363
  if (!routeDef || typeof routeDef !== "object" || Array.isArray(routeDef))
1355
1364
  throw new import_js_format19.Errorf(
1356
- "The route definition should be an Object, but %v given.",
1365
+ "The route definition should be an Object, but %v was given.",
1357
1366
  routeDef
1358
1367
  );
1359
1368
  const route = new Route(routeDef);
1360
1369
  const triePath = `${route.method}/${route.path}`;
1361
1370
  this._trie.add(triePath, route);
1362
- this.debug(
1363
- "The route %s %v is registered.",
1371
+ debug(
1372
+ "The route %s %v was registered.",
1364
1373
  route.method.toUpperCase(),
1365
1374
  route.path
1366
1375
  );
@@ -1373,9 +1382,10 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1373
1382
  * @returns {ResolvedRoute|undefined}
1374
1383
  */
1375
1384
  matchRouteByRequest(req) {
1385
+ const debug = this.getDebuggerFor(this.matchRouteByRequest);
1376
1386
  const requestPath = (req.url || "/").replace(/\?.*$/, "");
1377
- this.debug(
1378
- "Matching %s %v with registered routes.",
1387
+ debug(
1388
+ "Matching routes with the request %s %v.",
1379
1389
  req.method.toUpperCase(),
1380
1390
  requestPath
1381
1391
  );
@@ -1383,28 +1393,26 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1383
1393
  const resolved = this._trie.match(triePath);
1384
1394
  if (resolved) {
1385
1395
  const route = resolved.value;
1386
- this.debug(
1387
- "The request %s %v was matched to the route %s %v.",
1388
- req.method.toUpperCase(),
1389
- requestPath,
1396
+ debug(
1397
+ "The route %s %v was matched.",
1390
1398
  route.method.toUpperCase(),
1391
1399
  route.path
1392
1400
  );
1393
1401
  const paramNames = Object.keys(resolved.params);
1394
- if (paramNames) {
1402
+ if (paramNames.length) {
1395
1403
  paramNames.forEach((name) => {
1396
- this.debug(
1397
- "The path parameter %v has the value %v.",
1404
+ debug(
1405
+ "The path parameter %v had the value %v.",
1398
1406
  name,
1399
1407
  resolved.params[name]
1400
1408
  );
1401
1409
  });
1402
1410
  } else {
1403
- this.debug("No path parameters found.");
1411
+ debug("No path parameters found.");
1404
1412
  }
1405
1413
  return { route, params: resolved.params };
1406
1414
  }
1407
- this.debug(
1415
+ debug(
1408
1416
  "No matched route for the request %s %v.",
1409
1417
  req.method.toUpperCase(),
1410
1418
  requestPath
@@ -1416,8 +1424,8 @@ var RouteRegistry = _RouteRegistry;
1416
1424
 
1417
1425
  // src/request-context.js
1418
1426
  var import_js_format20 = require("@e22m4u/js-format");
1427
+ var import_js_service3 = require("@e22m4u/js-service");
1419
1428
  var import_js_service4 = require("@e22m4u/js-service");
1420
- var import_js_service5 = require("@e22m4u/js-service");
1421
1429
  var _RequestContext = class _RequestContext {
1422
1430
  /**
1423
1431
  * Service container.
@@ -1456,11 +1464,11 @@ var _RequestContext = class _RequestContext {
1456
1464
  */
1457
1465
  headers = {};
1458
1466
  /**
1459
- * Parsed cookie.
1467
+ * Parsed cookies.
1460
1468
  *
1461
1469
  * @type {object}
1462
1470
  */
1463
- cookie = {};
1471
+ cookies = {};
1464
1472
  /**
1465
1473
  * Parsed body.
1466
1474
  *
@@ -1508,22 +1516,22 @@ var _RequestContext = class _RequestContext {
1508
1516
  * @param {import('http').ServerResponse} response
1509
1517
  */
1510
1518
  constructor(container, request, response) {
1511
- if (!(0, import_js_service5.isServiceContainer)(container))
1519
+ if (!(0, import_js_service4.isServiceContainer)(container))
1512
1520
  throw new import_js_format20.Errorf(
1513
- 'The parameter "container" of RequestContext.constructor should be an instance of ServiceContainer, but %v given.',
1521
+ 'The parameter "container" of RequestContext.constructor should be an instance of ServiceContainer, but %v was given.',
1514
1522
  container
1515
1523
  );
1516
1524
  this.container = container;
1517
1525
  if (!request || typeof request !== "object" || Array.isArray(request) || !isReadableStream(request)) {
1518
1526
  throw new import_js_format20.Errorf(
1519
- 'The parameter "request" of RequestContext.constructor should be an instance of IncomingMessage, but %v given.',
1527
+ 'The parameter "request" of RequestContext.constructor should be an instance of IncomingMessage, but %v was given.',
1520
1528
  request
1521
1529
  );
1522
1530
  }
1523
1531
  this.req = request;
1524
1532
  if (!response || typeof response !== "object" || Array.isArray(response) || !isWritableStream(response)) {
1525
1533
  throw new import_js_format20.Errorf(
1526
- 'The parameter "response" of RequestContext.constructor should be an instance of ServerResponse, but %v given.',
1534
+ 'The parameter "response" of RequestContext.constructor should be an instance of ServerResponse, but %v was given.',
1527
1535
  response
1528
1536
  );
1529
1537
  }
@@ -1534,7 +1542,7 @@ __name(_RequestContext, "RequestContext");
1534
1542
  var RequestContext = _RequestContext;
1535
1543
 
1536
1544
  // src/trie-router.js
1537
- var import_js_service6 = require("@e22m4u/js-service");
1545
+ var import_js_service5 = require("@e22m4u/js-service");
1538
1546
  var _TrieRouter = class _TrieRouter extends DebuggableService {
1539
1547
  /**
1540
1548
  * Define route.
@@ -1553,11 +1561,11 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1553
1561
  * ```
1554
1562
  * const router = new TrieRouter();
1555
1563
  * router.defineRoute({
1556
- * method: HttpMethod.POST, // Request method.
1564
+ * method: HttpMethod.POST, // Request method.
1557
1565
  * path: '/users/:id', // The path template may have parameters.
1558
- * preHandler(ctx) { ... }, // The "preHandler" is executed before a route handler.
1566
+ * preHandler(ctx) { ... }, // The "preHandler" executes before a route handler.
1559
1567
  * handler(ctx) { ... }, // Request handler function.
1560
- * postHandler(ctx, data) { ... }, // The "postHandler" is executed after a route handler.
1568
+ * postHandler(ctx, data) { ... }, // The "postHandler" executes after a route handler.
1561
1569
  * });
1562
1570
  * ```
1563
1571
  *
@@ -1595,28 +1603,33 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1595
1603
  * @private
1596
1604
  */
1597
1605
  async _handleRequest(req, res) {
1606
+ const debug = this.getDebuggerFor(this._handleRequest);
1598
1607
  const requestPath = (req.url || "/").replace(/\?.*$/, "");
1599
- this.debug("Preparing to handle %s %v.", req.method, requestPath);
1608
+ debug(
1609
+ "Preparing to handle an incoming request %s %v.",
1610
+ req.method,
1611
+ requestPath
1612
+ );
1600
1613
  const resolved = this.getService(RouteRegistry).matchRouteByRequest(req);
1601
1614
  if (!resolved) {
1602
- this.debug("No route for the request %s %v.", req.method, requestPath);
1615
+ debug("No route for the request %s %v.", req.method, requestPath);
1603
1616
  this.getService(ErrorSender).send404(req, res);
1604
1617
  } else {
1605
1618
  const { route, params } = resolved;
1606
- const container = new import_js_service6.ServiceContainer(this.container);
1619
+ const container = new import_js_service5.ServiceContainer(this.container);
1607
1620
  const context = new RequestContext(container, req, res);
1608
1621
  container.set(RequestContext, context);
1609
1622
  context.params = params;
1610
- const reqDataOrPromise = this.getService(RequestParser).parse(req);
1611
- if (isPromise(reqDataOrPromise)) {
1612
- const reqData = await reqDataOrPromise;
1613
- Object.assign(context, reqData);
1614
- } else {
1615
- Object.assign(context, reqDataOrPromise);
1616
- }
1617
- let data, error;
1618
- const hookInvoker = this.getService(HookInvoker);
1623
+ let data;
1619
1624
  try {
1625
+ const reqDataOrPromise = this.getService(RequestParser).parse(req);
1626
+ if (isPromise(reqDataOrPromise)) {
1627
+ const reqData = await reqDataOrPromise;
1628
+ Object.assign(context, reqData);
1629
+ } else {
1630
+ Object.assign(context, reqDataOrPromise);
1631
+ }
1632
+ const hookInvoker = this.getService(HookInvoker);
1620
1633
  data = hookInvoker.invokeAndContinueUntilValueReceived(
1621
1634
  route,
1622
1635
  HookType.PRE_HANDLER,
@@ -1624,7 +1637,7 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1624
1637
  context
1625
1638
  );
1626
1639
  if (isPromise(data)) data = await data;
1627
- if (data == null) {
1640
+ if (!isResponseSent(res) && data == null) {
1628
1641
  data = route.handle(context);
1629
1642
  if (isPromise(data)) data = await data;
1630
1643
  let postHandlerData = hookInvoker.invokeAndContinueUntilValueReceived(
@@ -1638,12 +1651,11 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
1638
1651
  postHandlerData = await postHandlerData;
1639
1652
  if (postHandlerData != null) data = postHandlerData;
1640
1653
  }
1641
- } catch (err) {
1642
- error = err;
1643
- }
1644
- if (error) {
1654
+ } catch (error) {
1645
1655
  this.getService(ErrorSender).send(req, res, error);
1646
- } else {
1656
+ return;
1657
+ }
1658
+ if (!isResponseSent(res)) {
1647
1659
  this.getService(DataSender).send(res, data);
1648
1660
  }
1649
1661
  }
@@ -1685,9 +1697,9 @@ __name(_TrieRouter, "TrieRouter");
1685
1697
  var TrieRouter = _TrieRouter;
1686
1698
  // Annotate the CommonJS export names for ESM import in node:
1687
1699
  0 && (module.exports = {
1688
- BUFFER_ENCODING_LIST,
1689
1700
  BodyParser,
1690
- CookieParser,
1701
+ CHARACTER_ENCODING_LIST,
1702
+ CookiesParser,
1691
1703
  DataSender,
1692
1704
  EXPOSED_ERROR_PROPERTIES,
1693
1705
  ErrorSender,
@@ -1704,7 +1716,7 @@ var TrieRouter = _TrieRouter;
1704
1716
  RouterOptions,
1705
1717
  TrieRouter,
1706
1718
  UNPARSABLE_MEDIA_TYPES,
1707
- createCookieString,
1719
+ createCookiesString,
1708
1720
  createDebugger,
1709
1721
  createError,
1710
1722
  createRequestMock,
@@ -1716,7 +1728,7 @@ var TrieRouter = _TrieRouter;
1716
1728
  isResponseSent,
1717
1729
  isWritableStream,
1718
1730
  parseContentType,
1719
- parseCookie,
1731
+ parseCookies,
1720
1732
  parseJsonBody,
1721
1733
  toCamelCase
1722
1734
  });