@e22m4u/js-trie-router 0.4.0 → 0.4.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 (68) hide show
  1. package/.mocharc.cjs +1 -0
  2. package/README.md +49 -36
  3. package/dist/cjs/index.cjs +216 -157
  4. package/mocha-setup.js +4 -0
  5. package/package.json +2 -2
  6. package/src/debuggable-service.spec.js +1 -1
  7. package/src/hooks/hook-invoker.spec.js +1 -1
  8. package/src/hooks/hook-registry.spec.js +1 -1
  9. package/src/parsers/body-parser.d.ts +2 -2
  10. package/src/parsers/body-parser.js +6 -6
  11. package/src/parsers/body-parser.spec.js +2 -2
  12. package/src/parsers/cookies-parser.d.ts +2 -2
  13. package/src/parsers/cookies-parser.js +5 -5
  14. package/src/parsers/cookies-parser.spec.js +1 -1
  15. package/src/parsers/query-parser.d.ts +2 -2
  16. package/src/parsers/query-parser.js +5 -5
  17. package/src/parsers/query-parser.spec.js +1 -1
  18. package/src/parsers/request-parser.d.ts +2 -2
  19. package/src/parsers/request-parser.js +8 -8
  20. package/src/parsers/request-parser.spec.js +1 -1
  21. package/src/request-context.d.ts +13 -9
  22. package/src/request-context.js +75 -18
  23. package/src/request-context.spec.js +46 -18
  24. package/src/route-registry.d.ts +2 -2
  25. package/src/route-registry.js +7 -7
  26. package/src/route-registry.spec.js +1 -1
  27. package/src/route.js +1 -1
  28. package/src/route.spec.js +2 -2
  29. package/src/router-options.spec.js +1 -1
  30. package/src/senders/data-sender.d.ts +2 -2
  31. package/src/senders/data-sender.js +11 -11
  32. package/src/senders/data-sender.spec.js +1 -1
  33. package/src/senders/error-sender.d.ts +11 -6
  34. package/src/senders/error-sender.js +19 -19
  35. package/src/senders/error-sender.spec.js +6 -3
  36. package/src/trie-router.js +20 -24
  37. package/src/trie-router.spec.js +37 -25
  38. package/src/utils/clone-deep.js +1 -1
  39. package/src/utils/clone-deep.spec.js +1 -1
  40. package/src/utils/create-cookies-string.spec.js +1 -1
  41. package/src/utils/create-debugger.spec.js +1 -1
  42. package/src/utils/create-error.spec.js +1 -1
  43. package/src/utils/create-request-mock.js +11 -11
  44. package/src/utils/create-request-mock.spec.js +1 -1
  45. package/src/utils/create-response-mock.d.ts +2 -1
  46. package/src/utils/create-response-mock.js +30 -30
  47. package/src/utils/create-response-mock.spec.js +1 -1
  48. package/src/utils/create-route-mock.d.ts +19 -0
  49. package/src/utils/create-route-mock.js +22 -0
  50. package/src/utils/create-route-mock.spec.js +28 -0
  51. package/src/utils/fetch-request-body.d.ts +2 -2
  52. package/src/utils/fetch-request-body.js +16 -13
  53. package/src/utils/fetch-request-body.spec.js +1 -1
  54. package/src/utils/get-request-pathname.d.ts +2 -2
  55. package/src/utils/get-request-pathname.js +8 -8
  56. package/src/utils/get-request-pathname.spec.js +1 -1
  57. package/src/utils/index.d.ts +1 -0
  58. package/src/utils/index.js +1 -0
  59. package/src/utils/is-promise.spec.js +1 -1
  60. package/src/utils/is-readable-stream.spec.js +1 -1
  61. package/src/utils/is-response-sent.d.ts +2 -2
  62. package/src/utils/is-response-sent.js +8 -8
  63. package/src/utils/is-response-sent.spec.js +1 -1
  64. package/src/utils/is-writable-stream.spec.js +1 -1
  65. package/src/utils/parse-content-type.spec.js +1 -1
  66. package/src/utils/parse-cookies.spec.js +1 -1
  67. package/src/utils/to-camel-case.spec.js +1 -1
  68. package/src/chai.js +0 -7
package/mocha-setup.js ADDED
@@ -0,0 +1,4 @@
1
+ import * as chai from 'chai';
2
+ import chaiAsPromised from 'chai-as-promised';
3
+
4
+ chai.use(chaiAsPromised);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-trie-router",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "HTTP маршрутизатор для Node.js на основе префиксного дерева",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
@@ -58,7 +58,7 @@
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.0",
61
+ "eslint-plugin-jsdoc": "~61.2.1",
62
62
  "eslint-plugin-mocha": "~11.2.0",
63
63
  "globals": "~16.5.0",
64
64
  "husky": "~9.1.7",
@@ -1,4 +1,4 @@
1
- import {expect} from './chai.js';
1
+ import {expect} from 'chai';
2
2
  import {DebuggableService} from './debuggable-service.js';
3
3
 
4
4
  describe('DebuggableService', function () {
@@ -1,4 +1,4 @@
1
- import {expect} from '../chai.js';
1
+ import {expect} from 'chai';
2
2
  import {Route} from '../route.js';
3
3
  import {HttpMethod} from '../route.js';
4
4
  import {format} from '@e22m4u/js-format';
@@ -1,4 +1,4 @@
1
- import {expect} from '../chai.js';
1
+ import {expect} from 'chai';
2
2
  import {format} from '@e22m4u/js-format';
3
3
  import {HookRegistry} from './hook-registry.js';
4
4
  import {RouterHookType} from './hook-registry.js';
@@ -46,7 +46,7 @@ export declare class BodyParser extends DebuggableService {
46
46
  /**
47
47
  * Parse.
48
48
  *
49
- * @param req
49
+ * @param request
50
50
  */
51
- parse<T = unknown>(req: IncomingMessage): ValueOrPromise<T>;
51
+ parse<T = unknown>(request: IncomingMessage): ValueOrPromise<T>;
52
52
  }
@@ -96,19 +96,19 @@ export class BodyParser extends DebuggableService {
96
96
  /**
97
97
  * Parse.
98
98
  *
99
- * @param {import('http').IncomingMessage} req
99
+ * @param {import('http').IncomingMessage} request
100
100
  * @returns {Promise<*>|undefined}
101
101
  */
102
- parse(req) {
102
+ parse(request) {
103
103
  const debug = this.getDebuggerFor(this.parse);
104
- if (!METHODS_WITH_BODY.includes(req.method.toUpperCase())) {
104
+ if (!METHODS_WITH_BODY.includes(request.method.toUpperCase())) {
105
105
  debug(
106
106
  'Body parsing was skipped for the %s request.',
107
- req.method.toUpperCase(),
107
+ request.method.toUpperCase(),
108
108
  );
109
109
  return;
110
110
  }
111
- const contentType = (req.headers['content-type'] || '').replace(
111
+ const contentType = (request.headers['content-type'] || '').replace(
112
112
  /^([^;]+);.*$/,
113
113
  '$1',
114
114
  );
@@ -137,7 +137,7 @@ export class BodyParser extends DebuggableService {
137
137
  );
138
138
  }
139
139
  const bodyBytesLimit = this.getService(RouterOptions).requestBodyBytesLimit;
140
- return fetchRequestBody(req, bodyBytesLimit).then(rawBody => {
140
+ return fetchRequestBody(request, bodyBytesLimit).then(rawBody => {
141
141
  if (rawBody != null) return parser(rawBody);
142
142
  return rawBody;
143
143
  });
@@ -1,4 +1,4 @@
1
- import {expect} from '../chai.js';
1
+ import {expect} from 'chai';
2
2
  import HttpErrors from 'http-errors';
3
3
  import {HttpMethod} from '../route.js';
4
4
  import {format} from '@e22m4u/js-format';
@@ -104,7 +104,7 @@ describe('BodyParser', function () {
104
104
  });
105
105
  });
106
106
 
107
- describe('removesParser', function () {
107
+ describe('deleteParser', function () {
108
108
  it('requires the parameter "mediaType" to be a non-empty String', function () {
109
109
  const parser = new BodyParser();
110
110
  const throwable = v => () => parser.deleteParser(v);
@@ -9,7 +9,7 @@ export declare class CookiesParser extends DebuggableService {
9
9
  /**
10
10
  * Parse.
11
11
  *
12
- * @param req
12
+ * @param request
13
13
  */
14
- parse(req: IncomingMessage): ParsedCookies;
14
+ parse(request: IncomingMessage): ParsedCookies;
15
15
  }
@@ -9,12 +9,12 @@ export class CookiesParser extends DebuggableService {
9
9
  /**
10
10
  * Parse
11
11
  *
12
- * @param {import('http').IncomingMessage} req
12
+ * @param {import('http').IncomingMessage} request
13
13
  * @returns {object}
14
14
  */
15
- parse(req) {
15
+ parse(request) {
16
16
  const debug = this.getDebuggerFor(this.parse);
17
- const cookiesString = req.headers['cookie'] || '';
17
+ const cookiesString = request.headers['cookie'] || '';
18
18
  const cookies = parseCookies(cookiesString);
19
19
  const cookiesKeys = Object.keys(cookies);
20
20
  if (cookiesKeys.length) {
@@ -24,8 +24,8 @@ export class CookiesParser extends DebuggableService {
24
24
  } else {
25
25
  debug(
26
26
  'The request %s %v had no cookies.',
27
- req.method,
28
- getRequestPathname(req),
27
+ request.method,
28
+ getRequestPathname(request),
29
29
  );
30
30
  }
31
31
  return cookies;
@@ -1,4 +1,4 @@
1
- import {expect} from '../chai.js';
1
+ import {expect} from 'chai';
2
2
  import {CookiesParser} from './cookies-parser.js';
3
3
 
4
4
  describe('CookiesParser', function () {
@@ -15,7 +15,7 @@ export declare class QueryParser extends DebuggableService {
15
15
  /**
16
16
  * Parse.
17
17
  *
18
- * @param req
18
+ * @param request
19
19
  */
20
- parse(req: IncomingMessage): ParsedQuery;
20
+ parse(request: IncomingMessage): ParsedQuery;
21
21
  }
@@ -9,12 +9,12 @@ export class QueryParser extends DebuggableService {
9
9
  /**
10
10
  * Parse
11
11
  *
12
- * @param {import('http').IncomingMessage} req
12
+ * @param {import('http').IncomingMessage} request
13
13
  * @returns {object}
14
14
  */
15
- parse(req) {
15
+ parse(request) {
16
16
  const debug = this.getDebuggerFor(this.parse);
17
- const queryStr = req.url.replace(/^[^?]*\??/, '');
17
+ const queryStr = request.url.replace(/^[^?]*\??/, '');
18
18
  const query = queryStr ? querystring.parse(queryStr) : {};
19
19
  const queryKeys = Object.keys(query);
20
20
  if (queryKeys.length) {
@@ -24,8 +24,8 @@ export class QueryParser extends DebuggableService {
24
24
  } else {
25
25
  debug(
26
26
  'The request %s %v had no query parameters.',
27
- req.method,
28
- getRequestPathname(req),
27
+ request.method,
28
+ getRequestPathname(request),
29
29
  );
30
30
  }
31
31
  return query;
@@ -1,4 +1,4 @@
1
- import {expect} from '../chai.js';
1
+ import {expect} from 'chai';
2
2
  import {QueryParser} from './query-parser.js';
3
3
 
4
4
  describe('QueryParser', function () {
@@ -28,7 +28,7 @@ export declare class RequestParser extends DebuggableService {
28
28
  /**
29
29
  * Parse.
30
30
  *
31
- * @param req
31
+ * @param request
32
32
  */
33
- parse(req: IncomingMessage): ValueOrPromise<ParsedRequestData>;
33
+ parse(request: IncomingMessage): ValueOrPromise<ParsedRequestData>;
34
34
  }
@@ -13,15 +13,15 @@ export class RequestParser extends DebuggableService {
13
13
  /**
14
14
  * Parse.
15
15
  *
16
- * @param {IncomingMessage} req
16
+ * @param {IncomingMessage} request
17
17
  * @returns {Promise<object>|object}
18
18
  */
19
- parse(req) {
20
- if (!(req instanceof IncomingMessage))
19
+ parse(request) {
20
+ if (!(request instanceof IncomingMessage))
21
21
  throw new Errorf(
22
22
  'The first argument of RequestParser.parse should be ' +
23
23
  'an instance of IncomingMessage, but %v was given.',
24
- req,
24
+ request,
25
25
  );
26
26
  const data = {};
27
27
  const promises = [];
@@ -29,7 +29,7 @@ export class RequestParser extends DebuggableService {
29
29
  // значения, так как парсер может вернуть
30
30
  // Promise, и тогда придется разрывать
31
31
  // "eventLoop" с помощью "await"
32
- const parsedQuery = this.getService(QueryParser).parse(req);
32
+ const parsedQuery = this.getService(QueryParser).parse(request);
33
33
  if (isPromise(parsedQuery)) {
34
34
  promises.push(parsedQuery.then(v => (data.query = v)));
35
35
  } else {
@@ -39,7 +39,7 @@ export class RequestParser extends DebuggableService {
39
39
  // данные заголовка "cookie" с проверкой
40
40
  // значения на Promise, и разрываем
41
41
  // "eventLoop" при необходимости
42
- const parsedCookies = this.getService(CookiesParser).parse(req);
42
+ const parsedCookies = this.getService(CookiesParser).parse(request);
43
43
  if (isPromise(parsedCookies)) {
44
44
  promises.push(parsedCookies.then(v => (data.cookies = v)));
45
45
  } else {
@@ -48,7 +48,7 @@ export class RequestParser extends DebuggableService {
48
48
  // аналогично предыдущей операции, разбираем
49
49
  // тело запроса с проверкой результата
50
50
  // на наличие Promise
51
- const parsedBody = this.getService(BodyParser).parse(req);
51
+ const parsedBody = this.getService(BodyParser).parse(request);
52
52
  if (isPromise(parsedBody)) {
53
53
  promises.push(parsedBody.then(v => (data.body = v)));
54
54
  } else {
@@ -56,7 +56,7 @@ export class RequestParser extends DebuggableService {
56
56
  }
57
57
  // что бы предотвратить модификацию
58
58
  // заголовков, возвращаем их копию
59
- data.headers = Object.assign({}, req.headers);
59
+ data.headers = Object.assign({}, request.headers);
60
60
  // если имеются асинхронные операции, то результат
61
61
  // будет обернут в Promise, в противном случае
62
62
  // данные возвращаются сразу
@@ -1,4 +1,4 @@
1
- import {expect} from '../chai.js';
1
+ import {expect} from 'chai';
2
2
  import {HttpMethod} from '../route.js';
3
3
  import {format} from '@e22m4u/js-format';
4
4
  import {RequestParser} from './request-parser.js';
@@ -1,10 +1,8 @@
1
- import {ServerResponse} from 'http';
2
- import {IncomingMessage} from 'http';
3
- import {RouteMeta} from './route.js';
4
- import {ParsedQuery} from './parsers/index.js';
1
+ import {Route, RouteMeta} from './route.js';
5
2
  import {ParsedCookies} from './utils/index.js';
6
- import {ParsedHeaders} from './parsers/index.js';
7
3
  import {ServiceContainer} from '@e22m4u/js-service';
4
+ import {IncomingMessage, ServerResponse} from 'http';
5
+ import {ParsedQuery, ParsedHeaders} from './parsers/index.js';
8
6
 
9
7
  /**
10
8
  * Parsed params.
@@ -20,17 +18,22 @@ export declare class RequestContext {
20
18
  /**
21
19
  * Container.
22
20
  */
23
- cont: ServiceContainer;
21
+ get container(): ServiceContainer;
24
22
 
25
23
  /**
26
24
  * Request.
27
25
  */
28
- req: IncomingMessage;
26
+ get request(): IncomingMessage;
29
27
 
30
28
  /**
31
29
  * Response.
32
30
  */
33
- res: ServerResponse;
31
+ get response(): ServerResponse;
32
+
33
+ /**
34
+ * Route.
35
+ */
36
+ get route(): Route;
34
37
 
35
38
  /**
36
39
  * Query.
@@ -60,7 +63,7 @@ export declare class RequestContext {
60
63
  /**
61
64
  * Route meta.
62
65
  */
63
- meta: RouteMeta;
66
+ get meta(): RouteMeta;
64
67
 
65
68
  /**
66
69
  * Method.
@@ -88,5 +91,6 @@ export declare class RequestContext {
88
91
  container: ServiceContainer,
89
92
  request: IncomingMessage,
90
93
  response: ServerResponse,
94
+ route: Route,
91
95
  );
92
96
  }
@@ -1,9 +1,12 @@
1
+ import {Route} from './route.js';
1
2
  import {Errorf} from '@e22m4u/js-format';
2
- import {isReadableStream} from './utils/index.js';
3
- import {isWritableStream} from './utils/index.js';
4
- import {ServiceContainer} from '@e22m4u/js-service';
5
- import {getRequestPathname} from './utils/index.js';
6
- import {isServiceContainer} from '@e22m4u/js-service';
3
+ import {ServiceContainer, isServiceContainer} from '@e22m4u/js-service';
4
+
5
+ import {
6
+ isReadableStream,
7
+ isWritableStream,
8
+ getRequestPathname,
9
+ } from './utils/index.js';
7
10
 
8
11
  /**
9
12
  * Request context.
@@ -12,23 +15,66 @@ export class RequestContext {
12
15
  /**
13
16
  * Service container.
14
17
  *
15
- * @type {import('@e22m4u/js-service').ServiceContainer}
18
+ * @type {ServiceContainer}
19
+ */
20
+ _container;
21
+
22
+ /**
23
+ * Getter of service container.
24
+ *
25
+ * @type {ServiceContainer}
16
26
  */
17
- cont;
27
+ get container() {
28
+ return this._container;
29
+ }
18
30
 
19
31
  /**
20
32
  * Request.
21
33
  *
22
34
  * @type {import('http').IncomingMessage}
23
35
  */
24
- req;
36
+ _request;
37
+
38
+ /**
39
+ * Getter of request.
40
+ *
41
+ * @type {import('http').IncomingMessage}
42
+ */
43
+ get request() {
44
+ return this._request;
45
+ }
25
46
 
26
47
  /**
27
48
  * Response.
28
49
  *
29
50
  * @type {import('http').ServerResponse}
30
51
  */
31
- res;
52
+ _response;
53
+
54
+ /**
55
+ * Getter of response.
56
+ *
57
+ * @type {import('http').ServerResponse}
58
+ */
59
+ get response() {
60
+ return this._response;
61
+ }
62
+
63
+ /**
64
+ * Route
65
+ *
66
+ * @type {Route}
67
+ */
68
+ _route;
69
+
70
+ /**
71
+ * Getter of route.
72
+ *
73
+ * @type {Route}
74
+ */
75
+ get route() {
76
+ return this._route;
77
+ }
32
78
 
33
79
  /**
34
80
  * Query.
@@ -68,9 +114,11 @@ export class RequestContext {
68
114
  /**
69
115
  * Route meta.
70
116
  *
71
- * @type {object}
117
+ * @type {import('./route.js').RouteMeta}
72
118
  */
73
- meta = {};
119
+ get meta() {
120
+ return this.route.meta;
121
+ }
74
122
 
75
123
  /**
76
124
  * Method.
@@ -78,7 +126,7 @@ export class RequestContext {
78
126
  * @returns {string}
79
127
  */
80
128
  get method() {
81
- return this.req.method.toUpperCase();
129
+ return this.request.method.toUpperCase();
82
130
  }
83
131
 
84
132
  /**
@@ -87,7 +135,7 @@ export class RequestContext {
87
135
  * @returns {string}
88
136
  */
89
137
  get path() {
90
- return this.req.url;
138
+ return this.request.url;
91
139
  }
92
140
 
93
141
  /**
@@ -105,7 +153,7 @@ export class RequestContext {
105
153
  */
106
154
  get pathname() {
107
155
  if (this._pathname != null) return this._pathname;
108
- this._pathname = getRequestPathname(this.req);
156
+ this._pathname = getRequestPathname(this.request);
109
157
  return this._pathname;
110
158
  }
111
159
 
@@ -115,15 +163,16 @@ export class RequestContext {
115
163
  * @param {ServiceContainer} container
116
164
  * @param {import('http').IncomingMessage} request
117
165
  * @param {import('http').ServerResponse} response
166
+ * @param {Route} route
118
167
  */
119
- constructor(container, request, response) {
168
+ constructor(container, request, response, route) {
120
169
  if (!isServiceContainer(container))
121
170
  throw new Errorf(
122
171
  'The parameter "container" of RequestContext.constructor ' +
123
172
  'should be an instance of ServiceContainer, but %v was given.',
124
173
  container,
125
174
  );
126
- this.cont = container;
175
+ this._container = container;
127
176
  if (
128
177
  !request ||
129
178
  typeof request !== 'object' ||
@@ -136,7 +185,7 @@ export class RequestContext {
136
185
  request,
137
186
  );
138
187
  }
139
- this.req = request;
188
+ this._request = request;
140
189
  if (
141
190
  !response ||
142
191
  typeof response !== 'object' ||
@@ -149,6 +198,14 @@ export class RequestContext {
149
198
  response,
150
199
  );
151
200
  }
152
- this.res = response;
201
+ this._response = response;
202
+ if (!(route instanceof Route)) {
203
+ throw new Errorf(
204
+ 'The parameter "route" of RequestContext.constructor ' +
205
+ 'should be an instance of Route, but %v was given.',
206
+ route,
207
+ );
208
+ }
209
+ this._route = route;
153
210
  }
154
211
  }
@@ -1,16 +1,21 @@
1
- import {expect} from './chai.js';
1
+ import {expect} from 'chai';
2
2
  import {format} from '@e22m4u/js-format';
3
- import {createRequestMock} from './utils/index.js';
4
3
  import {RequestContext} from './request-context.js';
5
4
  import {ServiceContainer} from '@e22m4u/js-service';
6
- import {createResponseMock} from './utils/index.js';
5
+
6
+ import {
7
+ createRouteMock,
8
+ createRequestMock,
9
+ createResponseMock,
10
+ } from './utils/index.js';
7
11
 
8
12
  describe('RequestContext', function () {
9
13
  describe('constructor', function () {
10
14
  it('requires the parameter "container" to be the ServiceContainer', function () {
11
15
  const req = createRequestMock();
12
16
  const res = createResponseMock();
13
- const throwable = v => () => new RequestContext(v, req, res);
17
+ const route = createRouteMock();
18
+ const throwable = v => () => new RequestContext(v, req, res, route);
14
19
  const error = v =>
15
20
  format(
16
21
  'The parameter "container" of RequestContext.constructor ' +
@@ -32,8 +37,9 @@ describe('RequestContext', function () {
32
37
 
33
38
  it('requires the parameter "request" to be the ServiceContainer', function () {
34
39
  const res = createResponseMock();
40
+ const route = createRouteMock();
35
41
  const cont = new ServiceContainer();
36
- const throwable = v => () => new RequestContext(cont, v, res);
42
+ const throwable = v => () => new RequestContext(cont, v, res, route);
37
43
  const error = v =>
38
44
  format(
39
45
  'The parameter "request" of RequestContext.constructor ' +
@@ -55,8 +61,9 @@ describe('RequestContext', function () {
55
61
 
56
62
  it('requires the parameter "response" to be the ServiceContainer', function () {
57
63
  const req = createRequestMock();
64
+ const route = createRouteMock();
58
65
  const cont = new ServiceContainer();
59
- const throwable = v => () => new RequestContext(cont, req, v);
66
+ const throwable = v => () => new RequestContext(cont, req, v, route);
60
67
  const error = v =>
61
68
  format(
62
69
  'The parameter "response" of RequestContext.constructor ' +
@@ -76,22 +83,39 @@ describe('RequestContext', function () {
76
83
  throwable(createResponseMock())();
77
84
  });
78
85
 
79
- it('sets properties from given arguments', function () {
86
+ it('requires the parameter "route" to be the Route', function () {
80
87
  const req = createRequestMock();
81
88
  const res = createResponseMock();
82
89
  const cont = new ServiceContainer();
83
- const ctx = new RequestContext(cont, req, res);
84
- expect(ctx.cont).to.be.eq(cont);
85
- expect(ctx.req).to.be.eq(req);
86
- expect(ctx.res).to.be.eq(res);
90
+ const throwable = v => () => new RequestContext(cont, req, res, v);
91
+ const error = v =>
92
+ format(
93
+ 'The parameter "route" of RequestContext.constructor ' +
94
+ 'should be an instance of Route, but %s was given.',
95
+ v,
96
+ );
97
+ expect(throwable('str')).to.throw(error('"str"'));
98
+ expect(throwable('')).to.throw(error('""'));
99
+ expect(throwable(10)).to.throw(error('10'));
100
+ expect(throwable(0)).to.throw(error('0'));
101
+ expect(throwable(true)).to.throw(error('true'));
102
+ expect(throwable(false)).to.throw(error('false'));
103
+ expect(throwable(null)).to.throw(error('null'));
104
+ expect(throwable({})).to.throw(error('Object'));
105
+ expect(throwable([])).to.throw(error('Array'));
106
+ expect(throwable(undefined)).to.throw(error('undefined'));
107
+ throwable(createRouteMock())();
87
108
  });
88
109
 
89
- it('sets an empty object to the "meta" property', function () {
110
+ it('sets properties from given arguments', function () {
90
111
  const req = createRequestMock();
91
112
  const res = createResponseMock();
113
+ const route = createRouteMock();
92
114
  const cont = new ServiceContainer();
93
- const ctx = new RequestContext(cont, req, res);
94
- expect(ctx.meta).to.be.eql({});
115
+ const ctx = new RequestContext(cont, req, res, route);
116
+ expect(ctx.container).to.be.eq(cont);
117
+ expect(ctx.request).to.be.eq(req);
118
+ expect(ctx.response).to.be.eq(res);
95
119
  });
96
120
  });
97
121
 
@@ -99,8 +123,9 @@ describe('RequestContext', function () {
99
123
  it('returns the method name in upper case', function () {
100
124
  const req = createRequestMock({method: 'post'});
101
125
  const res = createResponseMock();
126
+ const route = createRouteMock();
102
127
  const cont = new ServiceContainer();
103
- const ctx = new RequestContext(cont, req, res);
128
+ const ctx = new RequestContext(cont, req, res, route);
104
129
  expect(ctx.method).to.be.eq('POST');
105
130
  });
106
131
  });
@@ -109,8 +134,9 @@ describe('RequestContext', function () {
109
134
  it('returns the request pathname with the query string', function () {
110
135
  const req = createRequestMock({path: '/pathname?foo=bar'});
111
136
  const res = createResponseMock();
137
+ const route = createRouteMock();
112
138
  const cont = new ServiceContainer();
113
- const ctx = new RequestContext(cont, req, res);
139
+ const ctx = new RequestContext(cont, req, res, route);
114
140
  expect(req.url).to.be.eq('/pathname?foo=bar');
115
141
  expect(ctx.path).to.be.eq('/pathname?foo=bar');
116
142
  });
@@ -120,8 +146,9 @@ describe('RequestContext', function () {
120
146
  it('returns the request pathname without the query string', function () {
121
147
  const req = createRequestMock({path: '/pathname?foo=bar'});
122
148
  const res = createResponseMock();
149
+ const route = createRouteMock();
123
150
  const cont = new ServiceContainer();
124
- const ctx = new RequestContext(cont, req, res);
151
+ const ctx = new RequestContext(cont, req, res, route);
125
152
  expect(req.url).to.be.eq('/pathname?foo=bar');
126
153
  expect(ctx.pathname).to.be.eq('/pathname');
127
154
  });
@@ -129,8 +156,9 @@ describe('RequestContext', function () {
129
156
  it('sets the cache to the "_pathname" property and uses is for next accesses', function () {
130
157
  const req = createRequestMock({path: '/pathname'});
131
158
  const res = createResponseMock();
159
+ const route = createRouteMock();
132
160
  const cont = new ServiceContainer();
133
- const ctx = new RequestContext(cont, req, res);
161
+ const ctx = new RequestContext(cont, req, res, route);
134
162
  expect(ctx._pathname).to.be.undefined;
135
163
  expect(ctx.pathname).to.be.eq('/pathname');
136
164
  expect(ctx._pathname).to.be.eq('/pathname');
@@ -33,7 +33,7 @@ export declare class RouteRegistry extends DebuggableService {
33
33
  /**
34
34
  * Match route by request.
35
35
  *
36
- * @param req
36
+ * @param request
37
37
  */
38
- matchRouteByRequest(req: IncomingMessage): ResolvedRoute | undefined;
38
+ matchRouteByRequest(request: IncomingMessage): ResolvedRoute | undefined;
39
39
  }