@e22m4u/js-trie-router 0.5.7 → 0.5.9

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.
@@ -70,6 +70,7 @@ __export(index_exports, {
70
70
  parseCookieString: () => parseCookieString,
71
71
  parseJsonBody: () => parseJsonBody,
72
72
  toCamelCase: () => toCamelCase,
73
+ toPascalCase: () => toPascalCase,
73
74
  validateRouteDefinition: () => validateRouteDefinition
74
75
  });
75
76
  module.exports = __toCommonJS(index_exports);
@@ -200,6 +201,15 @@ function toCamelCase(input) {
200
201
  }
201
202
  __name(toCamelCase, "toCamelCase");
202
203
 
204
+ // src/utils/to-pascal-case.js
205
+ function toPascalCase(input) {
206
+ if (!input) {
207
+ return "";
208
+ }
209
+ return input.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([0-9])([a-zA-Z])/g, "$1 $2").replace(/[-_]+|[^\p{L}\p{N}]/gu, " ").toLowerCase().replace(new RegExp("(?:^|\\s)(\\p{L})", "gu"), (_, letter) => letter.toUpperCase()).replace(/\s+/g, "");
210
+ }
211
+ __name(toPascalCase, "toPascalCase");
212
+
203
213
  // src/utils/normalize-path.js
204
214
  function normalizePath(value, noStartingSlash = false) {
205
215
  if (typeof value !== "string") {
@@ -1157,7 +1167,7 @@ var _Route = class _Route extends import_js_debug.Debuggable {
1157
1167
  this._hookRegistry.addHook(RouterHookType.POST_HANDLER, hook);
1158
1168
  });
1159
1169
  }
1160
- this.ctorDebug("A new route %s %v was created.", this.method, this.path);
1170
+ this.ctorDebug("Created a route %s %v.", this.method, this.path);
1161
1171
  }
1162
1172
  /**
1163
1173
  * Handle request.
@@ -1168,11 +1178,7 @@ var _Route = class _Route extends import_js_debug.Debuggable {
1168
1178
  handle(context) {
1169
1179
  const debug = this.getDebuggerFor(this.handle);
1170
1180
  const requestPath = getRequestPathname(context.request);
1171
- debug(
1172
- "Invoking the Route handler for the request %s %v.",
1173
- this.method,
1174
- requestPath
1175
- );
1181
+ debug("Invoking a route handler %s %v.", this.method, requestPath);
1176
1182
  return this.handler(context);
1177
1183
  }
1178
1184
  };
@@ -1304,9 +1310,14 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1304
1310
  */
1305
1311
  parse(request) {
1306
1312
  const debug = this.getDebuggerFor(this.parse);
1313
+ debug(
1314
+ "Parsing a request body %s %v.",
1315
+ request.method.toUpperCase(),
1316
+ getRequestPathname(request)
1317
+ );
1307
1318
  if (!METHODS_WITH_BODY.includes(request.method.toUpperCase())) {
1308
1319
  debug(
1309
- "Body parsing was skipped for the %s request.",
1320
+ "Skipping body parsing for the %s method.",
1310
1321
  request.method.toUpperCase()
1311
1322
  );
1312
1323
  return;
@@ -1316,9 +1327,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1316
1327
  "$1"
1317
1328
  );
1318
1329
  if (!contentType) {
1319
- debug(
1320
- "Body parsing was skipped because the request had no content type."
1321
- );
1330
+ debug("Skipping body parsing because no content type is provided.");
1322
1331
  return;
1323
1332
  }
1324
1333
  const { mediaType } = parseContentType(contentType);
@@ -1331,7 +1340,7 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1331
1340
  const parser = this._parsers[mediaType];
1332
1341
  if (!parser) {
1333
1342
  if (UNPARSABLE_MEDIA_TYPES.includes(mediaType)) {
1334
- debug("Body parsing was skipped for %v.", mediaType);
1343
+ debug("Skipping body parsing for the media type %v.", mediaType);
1335
1344
  return;
1336
1345
  }
1337
1346
  throw createError(
@@ -1341,10 +1350,14 @@ var _BodyParser = class _BodyParser extends DebuggableService {
1341
1350
  );
1342
1351
  }
1343
1352
  const bodyBytesLimit = this.getService(RouterOptions).requestBodyBytesLimit;
1353
+ debug("Fetching a request body.");
1354
+ debug("Body limit is %v bytes.", bodyBytesLimit);
1344
1355
  return fetchRequestBody(request, bodyBytesLimit).then((rawBody) => {
1345
1356
  if (rawBody != null) {
1357
+ debug("Read %v bytes.", Buffer.byteLength(rawBody, "utf8"));
1346
1358
  return parser(rawBody);
1347
1359
  }
1360
+ debug("Request body has no content.");
1348
1361
  return rawBody;
1349
1362
  });
1350
1363
  }
@@ -1379,11 +1392,11 @@ var _QueryParser = class _QueryParser extends DebuggableService {
1379
1392
  const queryKeys = Object.keys(query);
1380
1393
  if (queryKeys.length) {
1381
1394
  queryKeys.forEach((key) => {
1382
- debug("The query parameter %v had the value %v.", key, query[key]);
1395
+ debug("Found a query parameter %v with a value %v.", key, query[key]);
1383
1396
  });
1384
1397
  } else {
1385
1398
  debug(
1386
- "The request %s %v had no query parameters.",
1399
+ "Request %s %v had no query parameters.",
1387
1400
  request.method,
1388
1401
  getRequestPathname(request)
1389
1402
  );
@@ -1409,11 +1422,11 @@ var _CookiesParser = class _CookiesParser extends DebuggableService {
1409
1422
  const cookiesKeys = Object.keys(cookies);
1410
1423
  if (cookiesKeys.length) {
1411
1424
  cookiesKeys.forEach((key) => {
1412
- debug("The cookie %v had the value %v.", key, cookies[key]);
1425
+ debug("Found a cookie %v with a value %v.", key, cookies[key]);
1413
1426
  });
1414
1427
  } else {
1415
1428
  debug(
1416
- "The request %s %v had no cookies.",
1429
+ "Request %s %v had no cookies.",
1417
1430
  request.method,
1418
1431
  getRequestPathname(request)
1419
1432
  );
@@ -1499,11 +1512,7 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1499
1512
  const route = new Route(routeDef);
1500
1513
  const triePath = `${route.method}/${route.path}`;
1501
1514
  this._trie.add(triePath, route);
1502
- debug(
1503
- "The route %s %v was registered.",
1504
- route.method.toUpperCase(),
1505
- route.path
1506
- );
1515
+ debug("Registered a route %s %v.", route.method.toUpperCase(), route.path);
1507
1516
  return route;
1508
1517
  }
1509
1518
  /**
@@ -1516,7 +1525,7 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1516
1525
  const debug = this.getDebuggerFor(this.matchRouteByRequest);
1517
1526
  const requestPath = getRequestPathname(request);
1518
1527
  debug(
1519
- "Matching routes with the request %s %v.",
1528
+ "Matching routes for the request %s %v.",
1520
1529
  request.method.toUpperCase(),
1521
1530
  requestPath
1522
1531
  );
@@ -1525,16 +1534,12 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1525
1534
  const resolved = this._trie.match(triePath);
1526
1535
  if (resolved) {
1527
1536
  const route = resolved.value;
1528
- debug(
1529
- "The route %s %v was matched.",
1530
- route.method.toUpperCase(),
1531
- route.path
1532
- );
1537
+ debug("Matched route is %s %v.", route.method.toUpperCase(), route.path);
1533
1538
  const paramNames = Object.keys(resolved.params);
1534
1539
  if (paramNames.length) {
1535
1540
  paramNames.forEach((name) => {
1536
1541
  debug(
1537
- "The path parameter %v had the value %v.",
1542
+ "Found a path parameter %v with a value %v.",
1538
1543
  name,
1539
1544
  resolved.params[name]
1540
1545
  );
@@ -1545,7 +1550,7 @@ var _RouteRegistry = class _RouteRegistry extends DebuggableService {
1545
1550
  return { route, params: resolved.params };
1546
1551
  }
1547
1552
  debug(
1548
- "No matched route for the request %s %v.",
1553
+ "No route found for the request %s %v.",
1549
1554
  request.method.toUpperCase(),
1550
1555
  requestPath
1551
1556
  );
@@ -1752,21 +1757,19 @@ var _DataSender = class _DataSender extends DebuggableService {
1752
1757
  send(response, data) {
1753
1758
  const debug = this.getDebuggerFor(this.send);
1754
1759
  if (data === response || response.headersSent) {
1755
- debug(
1756
- "Response sending was skipped because its headers where sent already."
1757
- );
1760
+ debug("Skipping response because headers have already been sent.");
1758
1761
  return;
1759
1762
  }
1760
1763
  if (data == null) {
1761
1764
  response.statusCode = 204;
1762
1765
  response.end();
1763
- debug("The empty response was sent.");
1766
+ debug("Empty response has been sent.");
1764
1767
  return;
1765
1768
  }
1766
1769
  if (isReadableStream(data)) {
1767
1770
  response.setHeader("Content-Type", "application/octet-stream");
1768
1771
  data.pipe(response);
1769
- debug("The stream response was sent.");
1772
+ debug("Sending response with a Stream.");
1770
1773
  return;
1771
1774
  }
1772
1775
  let debugMsg;
@@ -1776,16 +1779,19 @@ var _DataSender = class _DataSender extends DebuggableService {
1776
1779
  case "number":
1777
1780
  if (Buffer.isBuffer(data)) {
1778
1781
  response.setHeader("content-type", "application/octet-stream");
1779
- debugMsg = "The Buffer was sent as binary data.";
1782
+ debugMsg = "Buffer has been sent as binary data.";
1780
1783
  } else {
1781
1784
  response.setHeader("content-type", "application/json");
1782
- debugMsg = (0, import_js_format18.format)("The %v was sent as JSON.", typeof data);
1785
+ debugMsg = (0, import_js_format18.format)(
1786
+ "%v has been sent as JSON.",
1787
+ toPascalCase(typeof data)
1788
+ );
1783
1789
  data = JSON.stringify(data);
1784
1790
  }
1785
1791
  break;
1786
1792
  default:
1787
1793
  response.setHeader("content-type", "text/plain");
1788
- debugMsg = "The response data was sent as plain text.";
1794
+ debugMsg = "Response data has been sent as plain text.";
1789
1795
  data = String(data);
1790
1796
  break;
1791
1797
  }
@@ -1853,7 +1859,7 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
1853
1859
  response.setHeader("content-type", "application/json; charset=utf-8");
1854
1860
  response.end(JSON.stringify(body, null, 2), "utf-8");
1855
1861
  debug(
1856
- "The %s error was sent for the request %s %v.",
1862
+ "%s error has been sent for the request %s %v.",
1857
1863
  statusCode,
1858
1864
  request.method,
1859
1865
  getRequestPathname(request)
@@ -1872,7 +1878,7 @@ var _ErrorSender = class _ErrorSender extends DebuggableService {
1872
1878
  response.setHeader("content-type", "text/plain; charset=utf-8");
1873
1879
  response.end("404 Not Found", "utf-8");
1874
1880
  debug(
1875
- "The 404 error was sent for the request %s %v.",
1881
+ "404 error has been sent for the request %s %v.",
1876
1882
  request.method,
1877
1883
  getRequestPathname(request)
1878
1884
  );
@@ -2070,8 +2076,8 @@ var _RouterBranch = class _RouterBranch extends DebuggableService {
2070
2076
  validateRouterBranchDefinition(branchDef);
2071
2077
  this._definition = cloneDeep(branchDef);
2072
2078
  }
2073
- this.ctorDebug("Branch %v created.", normalizePath(branchDef.path, true));
2074
- this.ctorDebug("Branch path was %v.", this._definition.path);
2079
+ this.ctorDebug("Created a branch %v.", normalizePath(branchDef.path, true));
2080
+ this.ctorDebug("Branch path is %v.", this._definition.path);
2075
2081
  }
2076
2082
  /**
2077
2083
  * Define route.
@@ -2188,14 +2194,14 @@ var _TrieRouter = class _TrieRouter extends DebuggableService {
2188
2194
  async _handleRequest(request, response) {
2189
2195
  const debug = this.getDebuggerFor(this._handleRequest);
2190
2196
  const requestPath = getRequestPathname(request);
2191
- debug(
2192
- "Preparing to handle an incoming request %s %v.",
2193
- request.method,
2194
- requestPath
2195
- );
2197
+ debug("Handling an incoming request %s %v.", request.method, requestPath);
2196
2198
  const resolved = this.getService(RouteRegistry).matchRouteByRequest(request);
2197
2199
  if (!resolved) {
2198
- debug("No route for the request %s %v.", request.method, requestPath);
2200
+ debug(
2201
+ "No route found for the request %s %v.",
2202
+ request.method,
2203
+ requestPath
2204
+ );
2199
2205
  this.getService(ErrorSender).send404(request, response);
2200
2206
  } else {
2201
2207
  const { route, params } = resolved;
@@ -2348,5 +2354,6 @@ var TrieRouter = _TrieRouter;
2348
2354
  parseCookieString,
2349
2355
  parseJsonBody,
2350
2356
  toCamelCase,
2357
+ toPascalCase,
2351
2358
  validateRouteDefinition
2352
2359
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-trie-router",
3
- "version": "0.5.7",
3
+ "version": "0.5.9",
4
4
  "description": "HTTP маршрутизатор для Node.js на основе префиксного дерева",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
@@ -47,8 +47,8 @@
47
47
  "statuses": "~2.0.2"
48
48
  },
49
49
  "devDependencies": {
50
- "@commitlint/cli": "~20.2.0",
51
- "@commitlint/config-conventional": "~20.2.0",
50
+ "@commitlint/cli": "~20.3.0",
51
+ "@commitlint/config-conventional": "~20.3.0",
52
52
  "@eslint/js": "~9.39.2",
53
53
  "@types/chai": "~5.2.3",
54
54
  "@types/chai-as-promised": "~8.0.2",
@@ -120,8 +120,8 @@ export class RouterBranch extends DebuggableService {
120
120
  validateRouterBranchDefinition(branchDef);
121
121
  this._definition = cloneDeep(branchDef);
122
122
  }
123
- this.ctorDebug('Branch %v created.', normalizePath(branchDef.path, true));
124
- this.ctorDebug('Branch path was %v.', this._definition.path);
123
+ this.ctorDebug('Created a branch %v.', normalizePath(branchDef.path, true));
124
+ this.ctorDebug('Branch path is %v.', this._definition.path);
125
125
  }
126
126
 
127
127
  /**
@@ -7,6 +7,7 @@ import {
7
7
  createError,
8
8
  parseContentType,
9
9
  fetchRequestBody,
10
+ getRequestPathname,
10
11
  } from '../utils/index.js';
11
12
 
12
13
  /**
@@ -113,9 +114,14 @@ export class BodyParser extends DebuggableService {
113
114
  */
114
115
  parse(request) {
115
116
  const debug = this.getDebuggerFor(this.parse);
117
+ debug(
118
+ 'Parsing a request body %s %v.',
119
+ request.method.toUpperCase(),
120
+ getRequestPathname(request),
121
+ );
116
122
  if (!METHODS_WITH_BODY.includes(request.method.toUpperCase())) {
117
123
  debug(
118
- 'Body parsing was skipped for the %s request.',
124
+ 'Skipping body parsing for the %s method.',
119
125
  request.method.toUpperCase(),
120
126
  );
121
127
  return;
@@ -125,9 +131,7 @@ export class BodyParser extends DebuggableService {
125
131
  '$1',
126
132
  );
127
133
  if (!contentType) {
128
- debug(
129
- 'Body parsing was skipped because the request had no content type.',
130
- );
134
+ debug('Skipping body parsing because no content type is provided.');
131
135
  return;
132
136
  }
133
137
  const {mediaType} = parseContentType(contentType);
@@ -140,7 +144,7 @@ export class BodyParser extends DebuggableService {
140
144
  const parser = this._parsers[mediaType];
141
145
  if (!parser) {
142
146
  if (UNPARSABLE_MEDIA_TYPES.includes(mediaType)) {
143
- debug('Body parsing was skipped for %v.', mediaType);
147
+ debug('Skipping body parsing for the media type %v.', mediaType);
144
148
  return;
145
149
  }
146
150
  throw createError(
@@ -150,10 +154,14 @@ export class BodyParser extends DebuggableService {
150
154
  );
151
155
  }
152
156
  const bodyBytesLimit = this.getService(RouterOptions).requestBodyBytesLimit;
157
+ debug('Fetching a request body.');
158
+ debug('Body limit is %v bytes.', bodyBytesLimit);
153
159
  return fetchRequestBody(request, bodyBytesLimit).then(rawBody => {
154
160
  if (rawBody != null) {
161
+ debug('Read %v bytes.', Buffer.byteLength(rawBody, 'utf8'));
155
162
  return parser(rawBody);
156
163
  }
164
+ debug('Request body has no content.');
157
165
  return rawBody;
158
166
  });
159
167
  }
@@ -18,11 +18,11 @@ export class CookiesParser extends DebuggableService {
18
18
  const cookiesKeys = Object.keys(cookies);
19
19
  if (cookiesKeys.length) {
20
20
  cookiesKeys.forEach(key => {
21
- debug('The cookie %v had the value %v.', key, cookies[key]);
21
+ debug('Found a cookie %v with a value %v.', key, cookies[key]);
22
22
  });
23
23
  } else {
24
24
  debug(
25
- 'The request %s %v had no cookies.',
25
+ 'Request %s %v had no cookies.',
26
26
  request.method,
27
27
  getRequestPathname(request),
28
28
  );
@@ -19,11 +19,11 @@ export class QueryParser extends DebuggableService {
19
19
  const queryKeys = Object.keys(query);
20
20
  if (queryKeys.length) {
21
21
  queryKeys.forEach(key => {
22
- debug('The query parameter %v had the value %v.', key, query[key]);
22
+ debug('Found a query parameter %v with a value %v.', key, query[key]);
23
23
  });
24
24
  } else {
25
25
  debug(
26
- 'The request %s %v had no query parameters.',
26
+ 'Request %s %v had no query parameters.',
27
27
  request.method,
28
28
  getRequestPathname(request),
29
29
  );
@@ -55,7 +55,7 @@ export class RequestParser extends DebuggableService {
55
55
  } else {
56
56
  data.body = parsedBody;
57
57
  }
58
- // что бы предотвратить модификацию
58
+ // чтобы предотвратить модификацию
59
59
  // заголовков, возвращаем их копию
60
60
  data.headers = Object.assign({}, request.headers);
61
61
  // если имеются асинхронные операции, то результат
@@ -147,7 +147,7 @@ export class Route extends Debuggable {
147
147
  this._hookRegistry.addHook(RouterHookType.POST_HANDLER, hook);
148
148
  });
149
149
  }
150
- this.ctorDebug('A new route %s %v was created.', this.method, this.path);
150
+ this.ctorDebug('Created a route %s %v.', this.method, this.path);
151
151
  }
152
152
 
153
153
  /**
@@ -159,11 +159,7 @@ export class Route extends Debuggable {
159
159
  handle(context) {
160
160
  const debug = this.getDebuggerFor(this.handle);
161
161
  const requestPath = getRequestPathname(context.request);
162
- debug(
163
- 'Invoking the Route handler for the request %s %v.',
164
- this.method,
165
- requestPath,
166
- );
162
+ debug('Invoking a route handler %s %v.', this.method, requestPath);
167
163
  return this.handler(context);
168
164
  }
169
165
  }
@@ -43,11 +43,7 @@ export class RouteRegistry extends DebuggableService {
43
43
  const route = new Route(routeDef);
44
44
  const triePath = `${route.method}/${route.path}`;
45
45
  this._trie.add(triePath, route);
46
- debug(
47
- 'The route %s %v was registered.',
48
- route.method.toUpperCase(),
49
- route.path,
50
- );
46
+ debug('Registered a route %s %v.', route.method.toUpperCase(), route.path);
51
47
  return route;
52
48
  }
53
49
 
@@ -61,7 +57,7 @@ export class RouteRegistry extends DebuggableService {
61
57
  const debug = this.getDebuggerFor(this.matchRouteByRequest);
62
58
  const requestPath = getRequestPathname(request);
63
59
  debug(
64
- 'Matching routes with the request %s %v.',
60
+ 'Matching routes for the request %s %v.',
65
61
  request.method.toUpperCase(),
66
62
  requestPath,
67
63
  );
@@ -72,16 +68,12 @@ export class RouteRegistry extends DebuggableService {
72
68
  const resolved = this._trie.match(triePath);
73
69
  if (resolved) {
74
70
  const route = resolved.value;
75
- debug(
76
- 'The route %s %v was matched.',
77
- route.method.toUpperCase(),
78
- route.path,
79
- );
71
+ debug('Matched route is %s %v.', route.method.toUpperCase(), route.path);
80
72
  const paramNames = Object.keys(resolved.params);
81
73
  if (paramNames.length) {
82
74
  paramNames.forEach(name => {
83
75
  debug(
84
- 'The path parameter %v had the value %v.',
76
+ 'Found a path parameter %v with a value %v.',
85
77
  name,
86
78
  resolved.params[name],
87
79
  );
@@ -92,7 +84,7 @@ export class RouteRegistry extends DebuggableService {
92
84
  return {route, params: resolved.params};
93
85
  }
94
86
  debug(
95
- 'No matched route for the request %s %v.',
87
+ 'No route found for the request %s %v.',
96
88
  request.method.toUpperCase(),
97
89
  requestPath,
98
90
  );
@@ -1,6 +1,6 @@
1
1
  import {format} from '@e22m4u/js-format';
2
- import {isReadableStream} from '../utils/index.js';
3
2
  import {DebuggableService} from '../debuggable-service.js';
3
+ import {isReadableStream, toPascalCase} from '../utils/index.js';
4
4
 
5
5
  /**
6
6
  * Data sender.
@@ -20,10 +20,7 @@ export class DataSender extends DebuggableService {
20
20
  // заголовки, то считаем, что контроллер
21
21
  // уже отправил ответ самостоятельно
22
22
  if (data === response || response.headersSent) {
23
- debug(
24
- 'Response sending was skipped because ' +
25
- 'its headers where sent already.',
26
- );
23
+ debug('Skipping response because headers have already been sent.');
27
24
  return;
28
25
  }
29
26
  // если ответ контроллера пуст, то отправляем
@@ -31,7 +28,7 @@ export class DataSender extends DebuggableService {
31
28
  if (data == null) {
32
29
  response.statusCode = 204;
33
30
  response.end();
34
- debug('The empty response was sent.');
31
+ debug('Empty response has been sent.');
35
32
  return;
36
33
  }
37
34
  // если ответ контроллера является стримом,
@@ -39,7 +36,7 @@ export class DataSender extends DebuggableService {
39
36
  if (isReadableStream(data)) {
40
37
  response.setHeader('Content-Type', 'application/octet-stream');
41
38
  data.pipe(response);
42
- debug('The stream response was sent.');
39
+ debug('Sending response with a Stream.');
43
40
  return;
44
41
  }
45
42
  // подготовка данных перед отправкой, и установка
@@ -53,16 +50,19 @@ export class DataSender extends DebuggableService {
53
50
  // тип Buffer отправляется
54
51
  // как бинарные данные
55
52
  response.setHeader('content-type', 'application/octet-stream');
56
- debugMsg = 'The Buffer was sent as binary data.';
53
+ debugMsg = 'Buffer has been sent as binary data.';
57
54
  } else {
58
55
  response.setHeader('content-type', 'application/json');
59
- debugMsg = format('The %v was sent as JSON.', typeof data);
56
+ debugMsg = format(
57
+ '%v has been sent as JSON.',
58
+ toPascalCase(typeof data),
59
+ );
60
60
  data = JSON.stringify(data);
61
61
  }
62
62
  break;
63
63
  default:
64
64
  response.setHeader('content-type', 'text/plain');
65
- debugMsg = 'The response data was sent as plain text.';
65
+ debugMsg = 'Response data has been sent as plain text.';
66
66
  data = String(data);
67
67
  break;
68
68
  }
@@ -66,7 +66,7 @@ export class ErrorSender extends DebuggableService {
66
66
  response.setHeader('content-type', 'application/json; charset=utf-8');
67
67
  response.end(JSON.stringify(body, null, 2), 'utf-8');
68
68
  debug(
69
- 'The %s error was sent for the request %s %v.',
69
+ '%s error has been sent for the request %s %v.',
70
70
  statusCode,
71
71
  request.method,
72
72
  getRequestPathname(request),
@@ -86,7 +86,7 @@ export class ErrorSender extends DebuggableService {
86
86
  response.setHeader('content-type', 'text/plain; charset=utf-8');
87
87
  response.end('404 Not Found', 'utf-8');
88
88
  debug(
89
- 'The 404 error was sent for the request %s %v.',
89
+ '404 error has been sent for the request %s %v.',
90
90
  request.method,
91
91
  getRequestPathname(request),
92
92
  );
@@ -99,20 +99,20 @@ export class TrieRouter extends DebuggableService {
99
99
  async _handleRequest(request, response) {
100
100
  const debug = this.getDebuggerFor(this._handleRequest);
101
101
  const requestPath = getRequestPathname(request);
102
- debug(
103
- 'Preparing to handle an incoming request %s %v.',
104
- request.method,
105
- requestPath,
106
- );
102
+ debug('Handling an incoming request %s %v.', request.method, requestPath);
107
103
  const resolved =
108
104
  this.getService(RouteRegistry).matchRouteByRequest(request);
109
105
  if (!resolved) {
110
- debug('No route for the request %s %v.', request.method, requestPath);
106
+ debug(
107
+ 'No route found for the request %s %v.',
108
+ request.method,
109
+ requestPath,
110
+ );
111
111
  this.getService(ErrorSender).send404(request, response);
112
112
  } else {
113
113
  const {route, params} = resolved;
114
114
  // создание дочернего сервис-контейнера для передачи
115
- // в контекст запроса, что бы родительский контекст
115
+ // в контекст запроса, чтобы родительский контекст
116
116
  // нельзя было модифицировать
117
117
  const container = new ServiceContainer(this.container);
118
118
  const context = new RequestContext(container, request, response, route);
@@ -137,7 +137,7 @@ export class TrieRouter extends DebuggableService {
137
137
  // записывается в контекст передаваемый обработчику
138
138
  const reqDataOrPromise = this.getService(RequestParser).parse(request);
139
139
  // результат разбора может являться асинхронным, и вместо
140
- // того, что бы разрывать поток выполнения, стоит проверить,
140
+ // того, чтобы разрывать поток выполнения, стоит проверить,
141
141
  // действительно ли необходимо использование оператора "await"
142
142
  if (isPromise(reqDataOrPromise)) {
143
143
  const reqData = await reqDataOrPromise;
@@ -3,6 +3,7 @@ export * from './merge-deep.js';
3
3
  export * from './is-promise.js';
4
4
  export * from './create-error.js';
5
5
  export * from './to-camel-case.js';
6
+ export * from './to-pascal-case.js';
6
7
  export * from './normalize-path.js';
7
8
  export * from './is-response-sent.js';
8
9
  export * from './create-route-mock.js';
@@ -3,6 +3,7 @@ export * from './merge-deep.js';
3
3
  export * from './is-promise.js';
4
4
  export * from './create-error.js';
5
5
  export * from './to-camel-case.js';
6
+ export * from './to-pascal-case.js';
6
7
  export * from './normalize-path.js';
7
8
  export * from './is-response-sent.js';
8
9
  export * from './create-route-mock.js';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * To pascal case.
3
+ *
4
+ * @param input
5
+ */
6
+ export declare function toPascalCase(input: string): string;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * To pascal case.
3
+ *
4
+ * @param {string} input
5
+ * @returns {string}
6
+ */
7
+ export function toPascalCase(input) {
8
+ if (!input) {
9
+ return '';
10
+ }
11
+ return (
12
+ input
13
+ // splits camelCase words into separate words
14
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
15
+ // splits numbers and words
16
+ .replace(/([0-9])([a-zA-Z])/g, '$1 $2')
17
+ // replaces dashes, underscores, and special characters with spaces
18
+ .replace(/[-_]+|[^\p{L}\p{N}]/gu, ' ')
19
+ // converts the entire string to lowercase
20
+ .toLowerCase()
21
+ // capitalizes the first letter of each word
22
+ .replace(/(?:^|\s)(\p{L})/gu, (_, letter) => letter.toUpperCase())
23
+ // removes all spaces
24
+ .replace(/\s+/g, '')
25
+ );
26
+ }
@@ -0,0 +1,15 @@
1
+ import {expect} from 'chai';
2
+ import {toPascalCase} from './to-pascal-case.js';
3
+
4
+ describe('toPascalCase', function () {
5
+ it('returns a PascalCase string', function () {
6
+ expect(toPascalCase('hello world')).to.be.eq('HelloWorld');
7
+ expect(toPascalCase('snake_case')).to.be.eq('SnakeCase');
8
+ expect(toPascalCase('kebab-case')).to.be.eq('KebabCase');
9
+ expect(toPascalCase('alreadyCamel')).to.be.eq('AlreadyCamel');
10
+ expect(toPascalCase('AlreadyPascal')).to.be.eq('AlreadyPascal');
11
+ expect(toPascalCase(' single word ')).to.be.eq('SingleWord');
12
+ expect(toPascalCase('')).to.be.eq('');
13
+ expect(toPascalCase('1number')).to.be.eq('1Number');
14
+ });
15
+ });