hono 1.1.1 → 1.2.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 (91) hide show
  1. package/README.md +126 -117
  2. package/dist/compose.d.ts +2 -2
  3. package/dist/compose.js +20 -8
  4. package/dist/compose.test.d.ts +1 -0
  5. package/dist/compose.test.js +511 -0
  6. package/dist/context.d.ts +8 -1
  7. package/dist/context.js +27 -37
  8. package/dist/context.test.d.ts +1 -0
  9. package/dist/context.test.js +127 -0
  10. package/dist/hono.d.ts +44 -21
  11. package/dist/hono.js +74 -43
  12. package/dist/hono.test.d.ts +1 -0
  13. package/dist/hono.test.js +592 -0
  14. package/dist/index.d.ts +2 -2
  15. package/dist/index.js +2 -1
  16. package/dist/middleware/basic-auth/index.js +2 -2
  17. package/dist/middleware/basic-auth/index.test.d.ts +1 -0
  18. package/dist/middleware/basic-auth/index.test.js +119 -0
  19. package/dist/middleware/body-parse/index.test.d.ts +1 -0
  20. package/dist/middleware/body-parse/index.test.js +59 -0
  21. package/dist/middleware/cookie/index.d.ts +1 -1
  22. package/dist/middleware/cookie/index.test.d.ts +1 -0
  23. package/dist/middleware/cookie/index.test.js +54 -0
  24. package/dist/middleware/cors/index.test.d.ts +1 -0
  25. package/dist/middleware/cors/index.test.js +59 -0
  26. package/dist/middleware/etag/index.test.d.ts +1 -0
  27. package/dist/middleware/etag/index.test.js +45 -0
  28. package/dist/middleware/graphql-server/index.js +1 -1
  29. package/dist/middleware/graphql-server/index.test.d.ts +1 -0
  30. package/dist/middleware/graphql-server/index.test.js +480 -0
  31. package/dist/middleware/graphql-server/parse-body.test.d.ts +1 -0
  32. package/dist/middleware/graphql-server/parse-body.test.js +57 -0
  33. package/dist/middleware/jwt/index.js +9 -11
  34. package/dist/middleware/jwt/index.test.d.ts +1 -0
  35. package/dist/middleware/jwt/index.test.js +51 -0
  36. package/dist/middleware/logger/index.test.d.ts +1 -0
  37. package/dist/middleware/logger/index.test.js +49 -0
  38. package/dist/middleware/mustache/index.test.d.ts +1 -0
  39. package/dist/middleware/mustache/index.test.js +49 -0
  40. package/dist/middleware/powered-by/index.test.d.ts +1 -0
  41. package/dist/middleware/powered-by/index.test.js +15 -0
  42. package/dist/middleware/pretty-json/index.test.d.ts +1 -0
  43. package/dist/middleware/pretty-json/index.test.js +28 -0
  44. package/dist/middleware/serve-static/index.test.d.ts +1 -0
  45. package/dist/middleware/serve-static/index.test.js +58 -0
  46. package/dist/router/reg-exp-router/index.d.ts +1 -1
  47. package/dist/router/reg-exp-router/index.js +1 -1
  48. package/dist/router/reg-exp-router/node.d.ts +3 -0
  49. package/dist/router/reg-exp-router/node.js +13 -7
  50. package/dist/router/reg-exp-router/router.d.ts +21 -2
  51. package/dist/router/reg-exp-router/router.js +301 -81
  52. package/dist/router/reg-exp-router/router.test.d.ts +1 -0
  53. package/dist/router/reg-exp-router/router.test.js +212 -0
  54. package/dist/router/reg-exp-router/trie.d.ts +7 -3
  55. package/dist/router/reg-exp-router/trie.js +3 -3
  56. package/dist/router/trie-router/index.d.ts +1 -1
  57. package/dist/router/trie-router/index.js +1 -1
  58. package/dist/router/trie-router/node.d.ts +4 -3
  59. package/dist/router/trie-router/node.js +123 -55
  60. package/dist/router/trie-router/node.test.d.ts +1 -0
  61. package/dist/router/trie-router/node.test.js +351 -0
  62. package/dist/router/trie-router/router.d.ts +2 -2
  63. package/dist/router/trie-router/router.js +1 -1
  64. package/dist/router/trie-router/router.test.d.ts +1 -0
  65. package/dist/router/trie-router/router.test.js +98 -0
  66. package/dist/router.d.ts +4 -3
  67. package/dist/router.js +5 -4
  68. package/dist/utils/body.js +2 -2
  69. package/dist/utils/body.test.d.ts +1 -0
  70. package/dist/utils/body.test.js +45 -0
  71. package/dist/utils/buffer.js +1 -1
  72. package/dist/utils/buffer.test.d.ts +1 -0
  73. package/dist/utils/buffer.test.js +36 -0
  74. package/dist/utils/cloudflare.test.d.ts +1 -0
  75. package/dist/utils/cloudflare.test.js +42 -0
  76. package/dist/utils/crypto.test.d.ts +1 -0
  77. package/dist/utils/crypto.test.js +15 -0
  78. package/dist/utils/encode.test.d.ts +1 -0
  79. package/dist/utils/encode.test.js +54 -0
  80. package/dist/utils/http-status.test.d.ts +1 -0
  81. package/dist/utils/http-status.test.js +8 -0
  82. package/dist/utils/jwt/jwt.test.d.ts +1 -0
  83. package/dist/utils/jwt/jwt.test.js +171 -0
  84. package/dist/utils/jwt/types.test.d.ts +1 -0
  85. package/dist/utils/jwt/types.test.js +12 -0
  86. package/dist/utils/mime.test.d.ts +1 -0
  87. package/dist/utils/mime.test.js +13 -0
  88. package/dist/utils/url.js +4 -4
  89. package/dist/utils/url.test.d.ts +1 -0
  90. package/dist/utils/url.test.js +87 -0
  91. package/package.json +3 -4
@@ -1 +1 @@
1
- export { TrieRouter } from '../../router/trie-router/router';
1
+ export { TrieRouter } from './router';
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TrieRouter = void 0;
4
- var router_1 = require("../../router/trie-router/router");
4
+ var router_1 = require("./router");
5
5
  Object.defineProperty(exports, "TrieRouter", { enumerable: true, get: function () { return router_1.TrieRouter; } });
@@ -1,12 +1,13 @@
1
1
  import { Result } from '../../router';
2
2
  import type { Pattern } from '../../utils/url';
3
3
  export declare class Node<T> {
4
- method: Record<string, T>;
5
- handler: T;
4
+ methods: Record<string, T>[];
5
+ handlers: T[];
6
6
  children: Record<string, Node<T>>;
7
- middlewares: [];
8
7
  patterns: Pattern[];
9
8
  constructor(method?: string, handler?: T, children?: Record<string, Node<T>>);
10
9
  insert(method: string, path: string, handler: T): Node<T>;
10
+ private getHandlers;
11
+ private next;
11
12
  search(method: string, path: string): Result<T>;
12
13
  }
@@ -3,96 +3,164 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Node = void 0;
4
4
  const router_1 = require("../../router");
5
5
  const url_1 = require("../../utils/url");
6
- const noRoute = () => {
7
- return null;
8
- };
6
+ function findParam(node, name) {
7
+ for (let i = 0, len = node.patterns.length; i < len; i++) {
8
+ if (typeof node.patterns[i] === 'object' && node.patterns[i][1] === name) {
9
+ return true;
10
+ }
11
+ }
12
+ const nodes = Object.values(node.children);
13
+ for (let i = 0, len = nodes.length; i < len; i++) {
14
+ if (findParam(nodes[i], name)) {
15
+ return true;
16
+ }
17
+ }
18
+ return false;
19
+ }
9
20
  class Node {
10
21
  constructor(method, handler, children) {
11
22
  this.children = children || {};
12
- this.method = {};
23
+ this.methods = [];
13
24
  if (method && handler) {
14
- this.method[method] = handler;
25
+ const m = {};
26
+ m[method] = handler;
27
+ this.methods = [m];
15
28
  }
16
- this.middlewares = [];
17
29
  this.patterns = [];
18
30
  }
19
31
  insert(method, path, handler) {
20
32
  // eslint-disable-next-line @typescript-eslint/no-this-alias
21
33
  let curNode = this;
22
34
  const parts = (0, url_1.splitPath)(path);
35
+ const parentPatterns = [];
36
+ const errorMessage = (name) => {
37
+ return `Duplicate param name, use another name instead of '${name}' - ${method} ${path} <--- '${name}'`;
38
+ };
23
39
  for (let i = 0, len = parts.length; i < len; i++) {
24
40
  const p = parts[i];
25
41
  if (Object.keys(curNode.children).includes(p)) {
42
+ parentPatterns.push(...curNode.patterns);
26
43
  curNode = curNode.children[p];
27
44
  continue;
28
45
  }
29
46
  curNode.children[p] = new Node();
30
47
  const pattern = (0, url_1.getPattern)(p);
31
48
  if (pattern) {
49
+ if (typeof pattern === 'object') {
50
+ for (let j = 0, len = parentPatterns.length; j < len; j++) {
51
+ if (typeof parentPatterns[j] === 'object' && parentPatterns[j][1] === pattern[1]) {
52
+ throw new Error(errorMessage(pattern[1]));
53
+ }
54
+ }
55
+ if (Object.values(curNode.children).some((n) => findParam(n, pattern[1]))) {
56
+ throw new Error(errorMessage(pattern[1]));
57
+ }
58
+ }
32
59
  curNode.patterns.push(pattern);
60
+ parentPatterns.push(...curNode.patterns);
33
61
  }
62
+ parentPatterns.push(...curNode.patterns);
34
63
  curNode = curNode.children[p];
35
64
  }
36
- curNode.method[method] = handler;
65
+ if (!curNode.methods.length) {
66
+ curNode.methods = [];
67
+ }
68
+ const m = {};
69
+ m[method] = handler;
70
+ curNode.methods.push(m);
37
71
  return curNode;
38
72
  }
39
- search(method, path) {
40
- // eslint-disable-next-line @typescript-eslint/no-this-alias
41
- let curNode = this;
42
- const params = {};
43
- const parts = (0, url_1.splitPath)(path);
44
- for (let i = 0, len = parts.length; i < len; i++) {
45
- const p = parts[i];
46
- // '*' => match any path
47
- // /api/* => default wildcard match
48
- if (curNode.children['*'] && !curNode.children[p]) {
49
- const astNode = curNode.children['*'];
50
- if (Object.keys(astNode.children).length === 0) {
51
- curNode = astNode;
52
- break;
53
- }
73
+ getHandlers(node, method) {
74
+ const handlers = [];
75
+ node.methods.map((m) => {
76
+ let handler = m[method];
77
+ if (handler !== undefined) {
78
+ handlers.push(handler);
79
+ return;
54
80
  }
55
- const nextNode = curNode.children[p];
56
- if (nextNode) {
57
- curNode = nextNode;
58
- // '/hello/*' => match '/hello'
59
- if (!(i == len - 1 && nextNode.children['*'])) {
60
- continue;
81
+ handler = m[router_1.METHOD_NAME_ALL];
82
+ if (handler !== undefined) {
83
+ handlers.push(handler);
84
+ return;
85
+ }
86
+ });
87
+ return handlers;
88
+ }
89
+ next(node, part, method, isLast) {
90
+ const handlers = [];
91
+ const nextNodes = [];
92
+ const params = {};
93
+ for (let j = 0, len = node.patterns.length; j < len; j++) {
94
+ const pattern = node.patterns[j];
95
+ // Wildcard
96
+ // '/hello/*/foo' => match /hello/bar/foo
97
+ if (pattern === '*') {
98
+ const astNode = node.children['*'];
99
+ if (astNode) {
100
+ handlers.push(...this.getHandlers(astNode, method));
101
+ nextNodes.push(astNode);
61
102
  }
62
103
  }
63
- let isWildcard = false;
64
- let isParamMatch = false;
65
- for (let j = 0, len = curNode.patterns.length; j < len; j++) {
66
- const pattern = curNode.patterns[j];
67
- // Wildcard
68
- // '/hello/*/foo' => match /hello/bar/foo
69
- if (pattern === '*') {
70
- curNode = curNode.children['*'];
71
- isWildcard = true;
72
- break;
104
+ if (part === '')
105
+ continue;
106
+ // Named match
107
+ // `/posts/:id` => match /posts/123
108
+ const [key, name, matcher] = pattern;
109
+ if (matcher === true || (matcher instanceof RegExp && matcher.test(part))) {
110
+ if (typeof key === 'string') {
111
+ if (isLast === true) {
112
+ handlers.push(...this.getHandlers(node.children[key], method));
113
+ }
114
+ nextNodes.push(node.children[key]);
73
115
  }
74
- // Named match
75
- const [key, name, matcher] = pattern;
76
- if (p !== '' && (matcher === true || matcher.test(p))) {
77
- params[name] = p;
78
- curNode = curNode.children[key];
79
- isParamMatch = true;
80
- break;
116
+ if (typeof name === 'string') {
117
+ params[name] = part;
81
118
  }
82
- return noRoute();
83
- }
84
- if (isWildcard && i === len - 1) {
85
- break;
86
119
  }
87
- if (isWildcard === false && isParamMatch === false) {
88
- return noRoute();
120
+ }
121
+ const nextNode = node.children[part];
122
+ if (nextNode) {
123
+ if (isLast === true) {
124
+ // '/hello/*' => match '/hello'
125
+ if (nextNode.children['*'] !== undefined) {
126
+ handlers.push(...this.getHandlers(nextNode.children['*'], method));
127
+ }
128
+ handlers.push(...this.getHandlers(nextNode, method));
89
129
  }
130
+ nextNodes.push(nextNode);
90
131
  }
91
- const handler = curNode.method[router_1.METHOD_NAME_OF_ALL] || curNode.method[method];
92
- if (!handler) {
93
- return noRoute();
132
+ const next = {
133
+ nodes: nextNodes,
134
+ handlers: handlers,
135
+ params: params,
136
+ };
137
+ return next;
138
+ }
139
+ search(method, path) {
140
+ const handlers = [];
141
+ let params = {};
142
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
143
+ const curNode = this;
144
+ let curNodes = [curNode];
145
+ const parts = (0, url_1.splitPath)(path);
146
+ for (let i = 0, len = parts.length; i < len; i++) {
147
+ const p = parts[i];
148
+ const isLast = i === len - 1;
149
+ const tempNodes = [];
150
+ for (let j = 0, len2 = curNodes.length; j < len2; j++) {
151
+ const res = this.next(curNodes[j], p, method, isLast);
152
+ if (res.nodes.length === 0) {
153
+ continue;
154
+ }
155
+ handlers.push(...res.handlers);
156
+ params = Object.assign(params, res.params);
157
+ tempNodes.push(...res.nodes);
158
+ }
159
+ curNodes = tempNodes;
94
160
  }
95
- return new router_1.Result(handler, params);
161
+ if (handlers.length <= 0)
162
+ return null;
163
+ return new router_1.Result(handlers, params);
96
164
  }
97
165
  }
98
166
  exports.Node = Node;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const node_1 = require("./node");
4
+ describe('Root Node', () => {
5
+ const node = new node_1.Node();
6
+ node.insert('get', '/', 'get root');
7
+ it('get /', () => {
8
+ const res = node.search('get', '/');
9
+ expect(res).not.toBeNull();
10
+ expect(res.handlers).toEqual(['get root']);
11
+ expect(node.search('get', '/hello')).toBeNull();
12
+ });
13
+ });
14
+ describe('Root Node is not defined', () => {
15
+ const node = new node_1.Node();
16
+ node.insert('get', '/hello', 'get hello');
17
+ it('get /', () => {
18
+ expect(node.search('get', '/')).toBeNull();
19
+ });
20
+ });
21
+ describe('Get with *', () => {
22
+ const node = new node_1.Node();
23
+ node.insert('get', '*', 'get all');
24
+ it('get /', () => {
25
+ expect(node.search('get', '/')).not.toBeNull();
26
+ expect(node.search('get', '/hello')).not.toBeNull();
27
+ });
28
+ });
29
+ describe('Basic Usage', () => {
30
+ const node = new node_1.Node();
31
+ node.insert('get', '/hello', 'get hello');
32
+ node.insert('post', '/hello', 'post hello');
33
+ node.insert('get', '/hello/foo', 'get hello foo');
34
+ it('get, post /hello', () => {
35
+ expect(node.search('get', '/')).toBeNull();
36
+ expect(node.search('post', '/')).toBeNull();
37
+ expect(node.search('get', '/hello').handlers).toEqual(['get hello']);
38
+ expect(node.search('post', '/hello').handlers).toEqual(['post hello']);
39
+ expect(node.search('put', '/hello')).toBeNull();
40
+ });
41
+ it('get /nothing', () => {
42
+ expect(node.search('get', '/nothing')).toBeNull();
43
+ });
44
+ it('/hello/foo, /hello/bar', () => {
45
+ expect(node.search('get', '/hello/foo').handlers).toEqual(['get hello foo']);
46
+ expect(node.search('post', '/hello/foo')).toBeNull();
47
+ expect(node.search('get', '/hello/bar')).toBeNull();
48
+ });
49
+ it('/hello/foo/bar', () => {
50
+ expect(node.search('get', '/hello/foo/bar')).toBeNull();
51
+ });
52
+ });
53
+ describe('Name path', () => {
54
+ const node = new node_1.Node();
55
+ node.insert('get', '/entry/:id', 'get entry');
56
+ node.insert('get', '/entry/:id/comment/:comment_id', 'get comment');
57
+ node.insert('get', '/map/:location/events', 'get events');
58
+ it('get /entry/123', () => {
59
+ const res = node.search('get', '/entry/123');
60
+ expect(res).not.toBeNull();
61
+ expect(res.handlers).toEqual(['get entry']);
62
+ expect(res.params).not.toBeNull();
63
+ expect(res.params['id']).toBe('123');
64
+ expect(res.params['id']).not.toBe('1234');
65
+ });
66
+ it('get /entry/456/comment', () => {
67
+ const res = node.search('get', '/entry/456/comment');
68
+ expect(res).toBeNull();
69
+ });
70
+ it('get /entry/789/comment/123', () => {
71
+ const res = node.search('get', '/entry/789/comment/123');
72
+ expect(res).not.toBeNull();
73
+ expect(res.handlers).toEqual(['get comment']);
74
+ expect(res.params['id']).toBe('789');
75
+ expect(res.params['comment_id']).toBe('123');
76
+ });
77
+ it('get /map/:location/events', () => {
78
+ const res = node.search('get', '/map/yokohama/events');
79
+ expect(res).not.toBeNull();
80
+ expect(res.handlers).toEqual(['get events']);
81
+ expect(res.params['location']).toBe('yokohama');
82
+ });
83
+ });
84
+ describe('Name path - Multiple route', () => {
85
+ const node = new node_1.Node();
86
+ node.insert('get', '/:type/:id', 'common');
87
+ node.insert('get', '/posts/:id', 'specialized');
88
+ it('get /posts/123', () => {
89
+ const res = node.search('get', '/posts/123');
90
+ expect(res).not.toBeNull();
91
+ expect(res.handlers).toEqual(['common', 'specialized']);
92
+ expect(res.params['id']).toBe('123');
93
+ });
94
+ });
95
+ describe('Wildcard', () => {
96
+ const node = new node_1.Node();
97
+ node.insert('get', '/wildcard-abc/*/wildcard-efg', 'wildcard');
98
+ it('/wildcard-abc/xxxxxx/wildcard-efg', () => {
99
+ const res = node.search('get', '/wildcard-abc/xxxxxx/wildcard-efg');
100
+ expect(res).not.toBeNull();
101
+ expect(res.handlers).toEqual(['wildcard']);
102
+ });
103
+ node.insert('get', '/wildcard-abc/*/wildcard-efg/hijk', 'wildcard');
104
+ it('/wildcard-abc/xxxxxx/wildcard-efg/hijk', () => {
105
+ const res = node.search('get', '/wildcard-abc/xxxxxx/wildcard-efg/hijk');
106
+ expect(res).not.toBeNull();
107
+ expect(res.handlers).toEqual(['wildcard']);
108
+ });
109
+ });
110
+ describe('Regexp', () => {
111
+ const node = new node_1.Node();
112
+ node.insert('get', '/regex-abc/:id{[0-9]+}/comment/:comment_id{[a-z]+}', 'regexp');
113
+ it('/regexp-abc/123/comment/abc', () => {
114
+ const res = node.search('get', '/regex-abc/123/comment/abc');
115
+ expect(res).not.toBeNull();
116
+ expect(res.handlers).toEqual(['regexp']);
117
+ expect(res.params['id']).toBe('123');
118
+ expect(res.params['comment_id']).toBe('abc');
119
+ });
120
+ it('/regexp-abc/abc', () => {
121
+ const res = node.search('get', '/regex-abc/abc');
122
+ expect(res).toBeNull();
123
+ });
124
+ it('/regexp-abc/123/comment/123', () => {
125
+ const res = node.search('get', '/regex-abc/123/comment/123');
126
+ expect(res).toBeNull();
127
+ });
128
+ });
129
+ describe('All', () => {
130
+ const node = new node_1.Node();
131
+ node.insert('ALL', '/all-methods', 'all methods'); // ALL
132
+ it('/all-methods', () => {
133
+ let res = node.search('get', '/all-methods');
134
+ expect(res).not.toBeNull();
135
+ expect(res.handlers).toEqual(['all methods']);
136
+ res = node.search('put', '/all-methods');
137
+ expect(res).not.toBeNull();
138
+ expect(res.handlers).toEqual(['all methods']);
139
+ });
140
+ });
141
+ describe('Special Wildcard', () => {
142
+ const node = new node_1.Node();
143
+ node.insert('ALL', '*', 'match all');
144
+ it('/foo', () => {
145
+ const res = node.search('get', '/foo');
146
+ expect(res).not.toBeNull();
147
+ expect(res.handlers).toEqual(['match all']);
148
+ });
149
+ it('/hello', () => {
150
+ const res = node.search('get', '/hello');
151
+ expect(res).not.toBeNull();
152
+ expect(res.handlers).toEqual(['match all']);
153
+ });
154
+ it('/hello/foo', () => {
155
+ const res = node.search('get', '/hello/foo');
156
+ expect(res).not.toBeNull();
157
+ expect(res.handlers).toEqual(['match all']);
158
+ });
159
+ });
160
+ describe('Special Wildcard deeply', () => {
161
+ const node = new node_1.Node();
162
+ node.insert('ALL', '/hello/*', 'match hello');
163
+ it('/hello', () => {
164
+ const res = node.search('get', '/hello');
165
+ expect(res).not.toBeNull();
166
+ expect(res.handlers).toEqual(['match hello']);
167
+ });
168
+ it('/hello/foo', () => {
169
+ const res = node.search('get', '/hello/foo');
170
+ expect(res).not.toBeNull();
171
+ expect(res.handlers).toEqual(['match hello']);
172
+ });
173
+ });
174
+ describe('Default with wildcard', () => {
175
+ const node = new node_1.Node();
176
+ node.insert('ALL', '/api/abc', 'match api');
177
+ node.insert('ALL', '/api/*', 'fallback');
178
+ it('/api/abc', () => {
179
+ const res = node.search('get', '/api/abc');
180
+ expect(res).not.toBeNull();
181
+ expect(res.handlers).toEqual(['fallback', 'match api']);
182
+ });
183
+ it('/api/def', () => {
184
+ const res = node.search('get', '/api/def');
185
+ expect(res).not.toBeNull();
186
+ expect(res.handlers).toEqual(['fallback']);
187
+ });
188
+ });
189
+ describe('Multi match', () => {
190
+ describe('Basic', () => {
191
+ const node = new node_1.Node();
192
+ node.insert('get', '*', 'GET *');
193
+ node.insert('get', '/abc/*', 'GET /abc/*');
194
+ node.insert('get', '/abc/*/edf', 'GET /abc/*/edf');
195
+ node.insert('get', '/abc/edf', 'GET /abc/edf');
196
+ node.insert('get', '/abc/*/ghi/jkl', 'GET /abc/*/ghi/jkl');
197
+ it('get /abc/edf', () => {
198
+ const res = node.search('get', '/abc/edf');
199
+ expect(res).not.toBeNull();
200
+ expect(res.handlers).toEqual(['GET *', 'GET /abc/*', 'GET /abc/edf']);
201
+ });
202
+ it('get /abc/xxx/edf', () => {
203
+ const res = node.search('get', '/abc/xxx/edf');
204
+ expect(res).not.toBeNull();
205
+ expect(res.handlers).toEqual(['GET *', 'GET /abc/*', 'GET /abc/*/edf']);
206
+ });
207
+ it('get /', () => {
208
+ const res = node.search('get', '/');
209
+ expect(res).not.toBeNull();
210
+ expect(res.handlers).toEqual(['GET *']);
211
+ });
212
+ it('post /', () => {
213
+ const res = node.search('post', '/');
214
+ expect(res).toBeNull();
215
+ });
216
+ it('get /abc/edf/ghi', () => {
217
+ const res = node.search('get', '/abc/edf/ghi');
218
+ expect(res).not.toBeNull();
219
+ expect(res.handlers).toEqual(['GET *', 'GET /abc/*']);
220
+ });
221
+ });
222
+ describe('Blog', () => {
223
+ const node = new node_1.Node();
224
+ node.insert('get', '*', 'middleware a');
225
+ node.insert('ALL', '*', 'middleware b');
226
+ node.insert('get', '/entry', 'get entries');
227
+ node.insert('post', '/entry/*', 'middleware c');
228
+ node.insert('post', '/entry', 'post entry');
229
+ node.insert('get', '/entry/:id', 'get entry');
230
+ node.insert('get', '/entry/:id/comment/:comment_id', 'get comment');
231
+ it('get /entry/123', async () => {
232
+ const res = node.search('get', '/entry/123');
233
+ expect(res).not.toBeNull();
234
+ expect(res.handlers).toEqual(['middleware a', 'middleware b', 'get entry']);
235
+ expect(res.params['id']).toBe('123');
236
+ });
237
+ it('get /entry/123/comment/456', async () => {
238
+ const res = node.search('get', '/entry/123/comment/456');
239
+ expect(res).not.toBeNull();
240
+ expect(res.handlers).toEqual(['middleware a', 'middleware b', 'get comment']);
241
+ expect(res.params['id']).toBe('123');
242
+ expect(res.params['comment_id']).toBe('456');
243
+ });
244
+ it('post /entry', async () => {
245
+ const res = node.search('post', '/entry');
246
+ expect(res).not.toBeNull();
247
+ expect(res.handlers).toEqual(['middleware b', 'middleware c', 'post entry']);
248
+ });
249
+ it('delete /entry', async () => {
250
+ const res = node.search('delete', '/entry');
251
+ expect(res).not.toBeNull();
252
+ expect(res.handlers).toEqual(['middleware b']);
253
+ });
254
+ });
255
+ describe('ALL', () => {
256
+ const node = new node_1.Node();
257
+ node.insert('ALL', '*', 'ALL *');
258
+ node.insert('ALL', '/abc/*', 'ALL /abc/*');
259
+ node.insert('ALL', '/abc/*/def', 'ALL /abc/*/def');
260
+ it('get /', () => {
261
+ const res = node.search('get', '/');
262
+ expect(res).not.toBeNull();
263
+ expect(res.handlers).toEqual(['ALL *']);
264
+ });
265
+ it('post /abc', () => {
266
+ const res = node.search('post', '/abc');
267
+ expect(res).not.toBeNull();
268
+ expect(res.handlers).toEqual(['ALL *', 'ALL /abc/*']);
269
+ });
270
+ it('delete /abc/xxx/def', () => {
271
+ const res = node.search('post', '/abc/xxx/def');
272
+ expect(res).not.toBeNull();
273
+ expect(res.handlers).toEqual(['ALL *', 'ALL /abc/*', 'ALL /abc/*/def']);
274
+ });
275
+ });
276
+ describe('Regexp', () => {
277
+ const node = new node_1.Node();
278
+ node.insert('get', '/regex-abc/:id{[0-9]+}/*', 'middleware a');
279
+ node.insert('get', '/regex-abc/:id{[0-9]+}/def', 'regexp');
280
+ it('/regexp-abc/123/def', () => {
281
+ const res = node.search('get', '/regex-abc/123/def');
282
+ expect(res).not.toBeNull();
283
+ expect(res.handlers).toEqual(['middleware a', 'regexp']);
284
+ expect(res.params['id']).toBe('123');
285
+ });
286
+ it('/regexp-abc/123', () => {
287
+ const res = node.search('get', '/regex-abc/123/ghi');
288
+ expect(res).not.toBeNull();
289
+ expect(res.handlers).toEqual(['middleware a']);
290
+ });
291
+ });
292
+ describe('Trailing slash', () => {
293
+ const node = new node_1.Node();
294
+ node.insert('get', '/book', 'GET /book');
295
+ node.insert('get', '/book/:id', 'GET /book/:id');
296
+ it('get /book', () => {
297
+ const res = node.search('get', '/book');
298
+ expect(res).not.toBeNull();
299
+ });
300
+ it('get /book/', () => {
301
+ const res = node.search('get', '/book/');
302
+ expect(res).toBeNull();
303
+ });
304
+ });
305
+ describe('Same path', () => {
306
+ const node = new node_1.Node();
307
+ node.insert('get', '/hey', 'Middleware A');
308
+ node.insert('get', '/hey', 'Middleware B');
309
+ it('get /hey', () => {
310
+ const res = node.search('get', '/hey');
311
+ expect(res).not.toBeNull();
312
+ expect(res.handlers).toEqual(['Middleware A', 'Middleware B']);
313
+ });
314
+ });
315
+ });
316
+ describe('Duplicate param name', () => {
317
+ it('self', () => {
318
+ const node = new node_1.Node();
319
+ expect(() => {
320
+ node.insert('get', '/:id/:id', 'foo');
321
+ }).toThrowError(/Duplicate param name/);
322
+ });
323
+ it('parent', () => {
324
+ const node = new node_1.Node();
325
+ node.insert('get', '/:id/:action', 'foo');
326
+ expect(() => {
327
+ node.insert('get', '/posts/:id', 'bar');
328
+ }).toThrowError(/Duplicate param name/);
329
+ });
330
+ it('child', () => {
331
+ const node = new node_1.Node();
332
+ node.insert('get', '/posts/:id', 'foo');
333
+ expect(() => {
334
+ node.insert('get', '/:id/:action', 'bar');
335
+ }).toThrowError(/Duplicate param name/);
336
+ });
337
+ it('hierarchy', () => {
338
+ const node = new node_1.Node();
339
+ node.insert('get', '/posts/:id/comments/:comment_id', 'foo');
340
+ expect(() => {
341
+ node.insert('get', '/posts/:id', 'bar');
342
+ }).not.toThrowError();
343
+ });
344
+ it('regular expression', () => {
345
+ const node = new node_1.Node();
346
+ node.insert('get', '/:id/:action{create|update}', 'foo');
347
+ expect(() => {
348
+ node.insert('get', '/:id/:action{delete}', 'bar');
349
+ }).not.toThrowError();
350
+ });
351
+ });
@@ -1,9 +1,9 @@
1
1
  import { Router } from '../../router';
2
2
  import type { Result } from '../../router';
3
- import { Node } from '../../router/trie-router/node';
3
+ import { Node } from './node';
4
4
  export declare class TrieRouter<T> extends Router<T> {
5
5
  node: Node<T>;
6
6
  constructor();
7
7
  add(method: string, path: string, handler: T): void;
8
- match(method: string, path: string): Result<T> | null;
8
+ match(method: string, path: string): Result<T>;
9
9
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TrieRouter = void 0;
4
4
  const router_1 = require("../../router");
5
- const node_1 = require("../../router/trie-router/node");
5
+ const node_1 = require("./node");
6
6
  class TrieRouter extends router_1.Router {
7
7
  constructor() {
8
8
  super();
@@ -0,0 +1 @@
1
+ export {};