@e22m4u/js-trie-router 0.4.2 → 0.4.4

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.
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ## @e22m4u/js-trie-router
2
2
 
3
+ ![npm version](https://badge.fury.io/js/@e22m4u%2Fjs-trie-router.svg)
4
+ ![license](https://img.shields.io/badge/license-mit-blue.svg)
5
+
3
6
  HTTP маршрутизатор для Node.js на основе
4
7
  [префиксного дерева](https://ru.wikipedia.org/wiki/Trie) (trie).
5
8
 
@@ -19,7 +22,8 @@ HTTP маршрутизатор для Node.js на основе
19
22
  - [preHandler](#prehandler)
20
23
  - [postHandler](#posthandler)
21
24
  - [Глобальные хуки](#глобальные-хуки)
22
- - [Метаданные](#метаданные)
25
+ - [Метаданные маршрута](#метаданные-маршрута)
26
+ - [Состояние запроса](#состояние-запроса)
23
27
  - [Отладка](#отладка)
24
28
  - [Тестирование](#тестирование)
25
29
  - [Лицензия](#лицензия)
@@ -97,6 +101,7 @@ server.listen(3000, 'localhost'); // прослушивание за
97
101
  - `response: ServerResponse` нативный поток ответа сервера;
98
102
  - `route: Route` экземпляр текущего маршрута;
99
103
  - `meta: object` геттер для доступа к метаданным маршрута (`route.meta`);
104
+ - `state: object` объект для обмена данными между хуками и обработчиком;
100
105
 
101
106
  Пример доступа к контексту из обработчика маршрута.
102
107
 
@@ -121,6 +126,7 @@ router.defineRoute({
121
126
  console.log(ctx.response); // ServerResponse
122
127
  console.log(ctx.route); // Route
123
128
  console.log(ctx.meta); // {prop: 'value'}
129
+ console.log(ctx.state); // {}
124
130
  // ...
125
131
  },
126
132
  });
@@ -262,7 +268,7 @@ router.addPostHandler((ctx, data) => {
262
268
  отличное от `undefined` и `null`, то такое значение будет использовано
263
269
  как ответ сервера.
264
270
 
265
- ### Метаданные
271
+ ### Метаданные маршрута
266
272
 
267
273
  Иногда требуется связать с маршрутом дополнительные, статические данные, которые
268
274
  могут быть использованы хуками для расширения функционала. Например, это могут
@@ -290,7 +296,7 @@ router.addPreHandler((ctx) => {
290
296
  router.defineRoute({
291
297
  method: HttpMethod.GET,
292
298
  path: '/',
293
- meta: {foo: 'bar'}, // <= мета-данные
299
+ meta: {foo: 'bar'}, // <= метаданные
294
300
  handler(ctx) {
295
301
  return 'Hello World!';
296
302
  },
@@ -300,6 +306,38 @@ server.on('request', router.requestListener);
300
306
  server.listen(3000, 'localhost');
301
307
  ```
302
308
 
309
+ ### Состояние запроса
310
+
311
+ Объект `ctx.state` инициализируется как пустой объект `{}` для каждого нового
312
+ запроса. Он предназначен для передачи динамических данных (например, профиля
313
+ пользователя после авторизации) из `preHandler` хуков в основной обработчик
314
+ маршрута или `postHandler` хуки.
315
+
316
+ ```js
317
+ import http from 'http';
318
+ import {TrieRouter, HttpMethod} from '@e22m4u/js-trie-router';
319
+
320
+ const router = new TrieRouter();
321
+
322
+ // глобальный хук авторизации
323
+ router.addPreHandler((ctx) => {
324
+ // логика получения пользователя (например, из заголовков)
325
+ const user = {id: 1, name: 'John', role: 'admin'};
326
+ // сохранение данных в state
327
+ ctx.state.user = user;
328
+ });
329
+
330
+ router.defineRoute({
331
+ method: HttpMethod.GET,
332
+ path: '/profile',
333
+ handler(ctx) {
334
+ // доступ к данным, установленным в хуке
335
+ const user = ctx.state.user;
336
+ return `Hello, ${user.name}!`;
337
+ },
338
+ });
339
+ ```
340
+
303
341
  ## Отладка
304
342
 
305
343
  Установка переменной `DEBUG` включает вывод логов.
@@ -1454,6 +1454,12 @@ var _RequestContext = class _RequestContext {
1454
1454
  * @type {*}
1455
1455
  */
1456
1456
  body;
1457
+ /**
1458
+ * State.
1459
+ *
1460
+ * @type {object}
1461
+ */
1462
+ state = {};
1457
1463
  /**
1458
1464
  * Route meta.
1459
1465
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-trie-router",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "HTTP маршрутизатор для Node.js на основе префиксного дерева",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  "@e22m4u/js-path-trie": "~0.0.13",
44
44
  "@e22m4u/js-service": "~0.4.6",
45
45
  "debug": "~4.4.3",
46
- "http-errors": "~2.0.0",
46
+ "http-errors": "~2.0.1",
47
47
  "statuses": "~2.0.2"
48
48
  },
49
49
  "devDependencies": {
@@ -58,13 +58,13 @@
58
58
  "eslint": "~9.39.1",
59
59
  "eslint-config-prettier": "~10.1.8",
60
60
  "eslint-plugin-chai-expect": "~3.1.0",
61
- "eslint-plugin-jsdoc": "~61.2.1",
61
+ "eslint-plugin-jsdoc": "~61.4.1",
62
62
  "eslint-plugin-mocha": "~11.2.0",
63
63
  "globals": "~16.5.0",
64
64
  "husky": "~9.1.7",
65
65
  "mocha": "~11.7.5",
66
66
  "prettier": "~3.6.2",
67
- "rimraf": "~6.1.0",
67
+ "rimraf": "~6.1.2",
68
68
  "typescript": "~5.9.3"
69
69
  }
70
70
  }
@@ -60,6 +60,11 @@ export declare class RequestContext {
60
60
  */
61
61
  body: unknown;
62
62
 
63
+ /**
64
+ * State.
65
+ */
66
+ state: Record<string, any>;
67
+
63
68
  /**
64
69
  * Route meta.
65
70
  */
@@ -111,6 +111,13 @@ export class RequestContext {
111
111
  */
112
112
  body;
113
113
 
114
+ /**
115
+ * State.
116
+ *
117
+ * @type {object}
118
+ */
119
+ state = {};
120
+
114
121
  /**
115
122
  * Route meta.
116
123
  *
@@ -166,4 +166,15 @@ describe('RequestContext', function () {
166
166
  expect(ctx.pathname).to.be.eq('/overridden');
167
167
  });
168
168
  });
169
+
170
+ describe('state', function () {
171
+ it('has an empty object by default', function () {
172
+ const req = createRequestMock({path: '/pathname'});
173
+ const res = createResponseMock();
174
+ const route = createRouteMock();
175
+ const cont = new ServiceContainer();
176
+ const ctx = new RequestContext(cont, req, res, route);
177
+ expect(ctx.state).to.be.eql({});
178
+ });
179
+ });
169
180
  });
@@ -13,7 +13,6 @@ type RouteMockOptions = {
13
13
  /**
14
14
  * Create route mock.
15
15
  *
16
- * @param {Route} options
17
- * @returns {Route}
16
+ * @param options
18
17
  */
19
- export function createRouteMock(options: RouteMockOptions): Route;
18
+ export function createRouteMock(options?: RouteMockOptions): Route;
@@ -2,15 +2,15 @@ import {Route, HttpMethod} from '../route.js';
2
2
 
3
3
  /**
4
4
  * @typedef {object} RouteMockOptions
5
- * @property {HttpMethod} method
6
- * @property {string} path
7
- * @property {import('../route.js').RouteHandler} handler
5
+ * @property {string|undefined} method
6
+ * @property {string|undefined} path
7
+ * @property {Function|undefined} handler
8
8
  */
9
9
 
10
10
  /**
11
11
  * Create route mock.
12
12
  *
13
- * @param {Route} options
13
+ * @param {RouteMockOptions|undefined} options
14
14
  * @returns {Route}
15
15
  */
16
16
  export function createRouteMock(options = {}) {