@ndiinginc/router 4.14.1 → 4.15.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.
- package/package.json +1 -1
- package/src/app.js +21 -17
- package/src/index.js +0 -9
- package/src/middleware/cors.js +1 -0
- package/src/node.js +2 -9
- package/src/router.js +59 -61
package/package.json
CHANGED
package/src/app.js
CHANGED
|
@@ -2,12 +2,9 @@ const http = require("http");
|
|
|
2
2
|
const { Router } = require("./router");
|
|
3
3
|
const { Request } = require("./request");
|
|
4
4
|
const { Response } = require("./response");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
IncomingMessage: Request,
|
|
9
|
-
ServerResponse: Response,
|
|
10
|
-
};
|
|
5
|
+
const { json } = require("./middleware/json");
|
|
6
|
+
const { cors } = require("./middleware/cors");
|
|
7
|
+
const { urlencoded } = require("./middleware/urlencoded");
|
|
11
8
|
|
|
12
9
|
class App extends Router {
|
|
13
10
|
/**
|
|
@@ -28,7 +25,6 @@ class App extends Router {
|
|
|
28
25
|
const promise = handlerPromise().catch((error) => {
|
|
29
26
|
if (!req.controller.signal.aborted) {
|
|
30
27
|
req.controller.abort(error);
|
|
31
|
-
} else {
|
|
32
28
|
}
|
|
33
29
|
});
|
|
34
30
|
try {
|
|
@@ -40,10 +36,10 @@ class App extends Router {
|
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
/**
|
|
43
|
-
* @param {Response} res
|
|
44
39
|
* @param {Error} err
|
|
40
|
+
* @param {Response} res
|
|
45
41
|
*/
|
|
46
|
-
fallback(
|
|
42
|
+
fallback(err, res) {
|
|
47
43
|
if (!res.writableEnded) {
|
|
48
44
|
if (!err) {
|
|
49
45
|
res.statusCode = 404;
|
|
@@ -65,12 +61,12 @@ class App extends Router {
|
|
|
65
61
|
* @param {Response} res
|
|
66
62
|
*/
|
|
67
63
|
async handle(req, res) {
|
|
68
|
-
const { params,
|
|
69
|
-
req.params =
|
|
64
|
+
const { params, handlers, errorHandlers } = this.find(req.method, req.path);
|
|
65
|
+
req.params = this.decodeParams(params);
|
|
70
66
|
let err;
|
|
71
67
|
try {
|
|
72
68
|
const handlerPromise = async () => {
|
|
73
|
-
for (const handler of handlers) {
|
|
69
|
+
for (const handler of Object.values(handlers)) {
|
|
74
70
|
if (res.writableEnded) break;
|
|
75
71
|
await handler(req, res);
|
|
76
72
|
}
|
|
@@ -83,7 +79,7 @@ class App extends Router {
|
|
|
83
79
|
} catch (error) {
|
|
84
80
|
err = error;
|
|
85
81
|
try {
|
|
86
|
-
for (const handler of errorHandlers) {
|
|
82
|
+
for (const handler of Object.values(errorHandlers)) {
|
|
87
83
|
if (res.writableEnded) break;
|
|
88
84
|
await handler(err, req, res);
|
|
89
85
|
}
|
|
@@ -91,7 +87,7 @@ class App extends Router {
|
|
|
91
87
|
err = new Error(error.message, { cause: err });
|
|
92
88
|
}
|
|
93
89
|
}
|
|
94
|
-
this.fallback(
|
|
90
|
+
this.fallback(err, res);
|
|
95
91
|
}
|
|
96
92
|
|
|
97
93
|
/**
|
|
@@ -99,13 +95,21 @@ class App extends Router {
|
|
|
99
95
|
* @returns {import('http').Server}
|
|
100
96
|
*/
|
|
101
97
|
listen(...args) {
|
|
102
|
-
const
|
|
103
|
-
|
|
98
|
+
const server = http.createServer(
|
|
99
|
+
{
|
|
100
|
+
IncomingMessage: Request,
|
|
101
|
+
ServerResponse: Response,
|
|
102
|
+
},
|
|
103
|
+
(req, res) => this.handle(req, res),
|
|
104
|
+
);
|
|
104
105
|
server.listen(...args);
|
|
105
106
|
return server;
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
App.
|
|
110
|
+
App.Router = Router;
|
|
111
|
+
App.json = json;
|
|
112
|
+
App.cors = cors;
|
|
113
|
+
App.urlencoded = urlencoded;
|
|
110
114
|
|
|
111
115
|
exports.App = App;
|
package/src/index.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
require("./polyfill");
|
|
2
2
|
const { App } = require("./app");
|
|
3
|
-
const { Router } = require("./router");
|
|
4
|
-
const { json } = require("./middleware/json");
|
|
5
|
-
const { cors } = require("./middleware/cors");
|
|
6
|
-
const { urlencoded } = require("./middleware/urlencoded");
|
|
7
|
-
|
|
8
|
-
App.Router = Router;
|
|
9
|
-
App.json = json;
|
|
10
|
-
App.cors = cors;
|
|
11
|
-
App.urlencoded = urlencoded;
|
|
12
3
|
|
|
13
4
|
module.exports = App;
|
package/src/middleware/cors.js
CHANGED
package/src/node.js
CHANGED
|
@@ -8,13 +8,10 @@ class Node {
|
|
|
8
8
|
/**@type {String}*/
|
|
9
9
|
this.name = segment.slice(1);
|
|
10
10
|
}
|
|
11
|
-
|
|
12
11
|
/**@type {Map<string,Node>}*/
|
|
13
12
|
this.children = new Map();
|
|
14
|
-
|
|
15
13
|
/**@type {Map<string,Node>}*/
|
|
16
14
|
this.params = new Map();
|
|
17
|
-
|
|
18
15
|
/**@type {Node}*/
|
|
19
16
|
this.wildcard = null;
|
|
20
17
|
/**@type {Map<string,Function[]>}*/
|
|
@@ -31,13 +28,9 @@ class Node {
|
|
|
31
28
|
return this.wildcard;
|
|
32
29
|
}
|
|
33
30
|
if (segment.startsWith(":")) {
|
|
34
|
-
return this.params.getOrInsertComputed(segment, (segment) =>
|
|
35
|
-
return new Node(segment);
|
|
36
|
-
});
|
|
31
|
+
return this.params.getOrInsertComputed(segment, (segment) => new Node(segment));
|
|
37
32
|
}
|
|
38
|
-
return this.children.getOrInsertComputed(segment, (segment) =>
|
|
39
|
-
return new Node(segment);
|
|
40
|
-
});
|
|
33
|
+
return this.children.getOrInsertComputed(segment, (segment) => new Node(segment));
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
/**
|
package/src/router.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
const { decodeParam } = require("./util");
|
|
2
2
|
const { Node } = require("./node");
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @callback Callback
|
|
6
|
+
* @param {import('./request').Request} req
|
|
7
|
+
* @param {import('./response').Response} res
|
|
8
|
+
*/
|
|
9
|
+
|
|
4
10
|
/**
|
|
5
11
|
* @typedef {Object} Options
|
|
6
12
|
* @property {Number} [requestTimeout=0]
|
|
@@ -12,7 +18,6 @@ class Router {
|
|
|
12
18
|
*/
|
|
13
19
|
constructor(options = {}) {
|
|
14
20
|
this.requestTimeout = options.requestTimeout ?? 0;
|
|
15
|
-
|
|
16
21
|
this.root = new Node();
|
|
17
22
|
this.seq = 0;
|
|
18
23
|
}
|
|
@@ -55,17 +60,15 @@ class Router {
|
|
|
55
60
|
|
|
56
61
|
/**
|
|
57
62
|
* @param {String} method
|
|
58
|
-
* @param {String|
|
|
59
|
-
* @param {
|
|
63
|
+
* @param {String|Callback} path
|
|
64
|
+
* @param {Callback[]} handlers
|
|
60
65
|
*/
|
|
61
66
|
add(method, path, ...handlers) {
|
|
62
67
|
if (typeof path === "function") {
|
|
63
68
|
handlers = [path, ...handlers];
|
|
64
69
|
path = null;
|
|
65
70
|
}
|
|
66
|
-
|
|
67
71
|
let node = this.root;
|
|
68
|
-
let params = [];
|
|
69
72
|
if (path) {
|
|
70
73
|
let i = 0;
|
|
71
74
|
while (i < path.length) {
|
|
@@ -74,7 +77,6 @@ class Router {
|
|
|
74
77
|
while (j < path.length && path[j] !== "/") j++;
|
|
75
78
|
let segment = path.slice(i, j);
|
|
76
79
|
node = node.add(segment);
|
|
77
|
-
params.push(segment.slice(1));
|
|
78
80
|
i = j;
|
|
79
81
|
} else if (path[i] === "*") {
|
|
80
82
|
let j = i + 1;
|
|
@@ -101,8 +103,8 @@ class Router {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
/**
|
|
104
|
-
* @param {String|
|
|
105
|
-
* @param {
|
|
106
|
+
* @param {String|Callback} path
|
|
107
|
+
* @param {Callback[]} handlers
|
|
106
108
|
* @returns {this}
|
|
107
109
|
*/
|
|
108
110
|
use(path, ...handlers) {
|
|
@@ -111,8 +113,8 @@ class Router {
|
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
/**
|
|
114
|
-
* @param {String|
|
|
115
|
-
* @param {
|
|
116
|
+
* @param {String|Callback} path
|
|
117
|
+
* @param {Callback[]} handlers
|
|
116
118
|
* @returns {this}
|
|
117
119
|
*/
|
|
118
120
|
get(path, ...handlers) {
|
|
@@ -121,8 +123,8 @@ class Router {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
/**
|
|
124
|
-
* @param {String|
|
|
125
|
-
* @param {
|
|
126
|
+
* @param {String|Callback} path
|
|
127
|
+
* @param {Callback[]} handlers
|
|
126
128
|
* @returns {this}
|
|
127
129
|
*/
|
|
128
130
|
query(path, ...handlers) {
|
|
@@ -131,8 +133,8 @@ class Router {
|
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
/**
|
|
134
|
-
* @param {String|
|
|
135
|
-
* @param {
|
|
136
|
+
* @param {String|Callback} path
|
|
137
|
+
* @param {Callback[]} handlers
|
|
136
138
|
* @returns {this}
|
|
137
139
|
*/
|
|
138
140
|
head(path, ...handlers) {
|
|
@@ -141,8 +143,8 @@ class Router {
|
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
/**
|
|
144
|
-
* @param {String|
|
|
145
|
-
* @param {
|
|
146
|
+
* @param {String|Callback} path
|
|
147
|
+
* @param {Callback[]} handlers
|
|
146
148
|
* @returns {this}
|
|
147
149
|
*/
|
|
148
150
|
options(path, ...handlers) {
|
|
@@ -151,8 +153,8 @@ class Router {
|
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
/**
|
|
154
|
-
* @param {String|
|
|
155
|
-
* @param {
|
|
156
|
+
* @param {String|Callback} path
|
|
157
|
+
* @param {Callback[]} handlers
|
|
156
158
|
* @returns {this}
|
|
157
159
|
*/
|
|
158
160
|
trace(path, ...handlers) {
|
|
@@ -161,8 +163,8 @@ class Router {
|
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
/**
|
|
164
|
-
* @param {String|
|
|
165
|
-
* @param {
|
|
166
|
+
* @param {String|Callback} path
|
|
167
|
+
* @param {Callback[]} handlers
|
|
166
168
|
* @returns {this}
|
|
167
169
|
*/
|
|
168
170
|
put(path, ...handlers) {
|
|
@@ -171,8 +173,8 @@ class Router {
|
|
|
171
173
|
}
|
|
172
174
|
|
|
173
175
|
/**
|
|
174
|
-
* @param {String|
|
|
175
|
-
* @param {
|
|
176
|
+
* @param {String|Callback} path
|
|
177
|
+
* @param {Callback[]} handlers
|
|
176
178
|
* @returns {this}
|
|
177
179
|
*/
|
|
178
180
|
delete(path, ...handlers) {
|
|
@@ -181,8 +183,8 @@ class Router {
|
|
|
181
183
|
}
|
|
182
184
|
|
|
183
185
|
/**
|
|
184
|
-
* @param {String|
|
|
185
|
-
* @param {
|
|
186
|
+
* @param {String|Callback} path
|
|
187
|
+
* @param {Callback[]} handlers
|
|
186
188
|
* @returns {this}
|
|
187
189
|
*/
|
|
188
190
|
post(path, ...handlers) {
|
|
@@ -191,8 +193,8 @@ class Router {
|
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
/**
|
|
194
|
-
* @param {String|
|
|
195
|
-
* @param {
|
|
196
|
+
* @param {String|Callback} path
|
|
197
|
+
* @param {Callback[]} handlers
|
|
196
198
|
* @returns {this}
|
|
197
199
|
*/
|
|
198
200
|
patch(path, ...handlers) {
|
|
@@ -201,8 +203,8 @@ class Router {
|
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
/**
|
|
204
|
-
* @param {String|
|
|
205
|
-
* @param {
|
|
206
|
+
* @param {String|Callback} path
|
|
207
|
+
* @param {Callback[]} handlers
|
|
206
208
|
* @returns {this}
|
|
207
209
|
*/
|
|
208
210
|
connect(path, ...handlers) {
|
|
@@ -226,8 +228,8 @@ class Router {
|
|
|
226
228
|
return { nodes, params, matched: true };
|
|
227
229
|
}
|
|
228
230
|
if (nodes.length > state.nodes.length) {
|
|
229
|
-
state.nodes=nodes.slice()
|
|
230
|
-
params={...params}
|
|
231
|
+
state.nodes = nodes.slice();
|
|
232
|
+
params = { ...params };
|
|
231
233
|
}
|
|
232
234
|
nodes.pop();
|
|
233
235
|
return { nodes: state.nodes, params: state.params, matched: false };
|
|
@@ -238,83 +240,79 @@ class Router {
|
|
|
238
240
|
if (res.matched) return res;
|
|
239
241
|
}
|
|
240
242
|
}
|
|
241
|
-
for (const [
|
|
243
|
+
for (const [, child] of node.params) {
|
|
242
244
|
const slashIdx = path.indexOf("/");
|
|
243
245
|
const value = slashIdx === -1 ? path : path.slice(0, slashIdx);
|
|
244
246
|
const rest = slashIdx === -1 ? "" : path.slice(slashIdx);
|
|
245
247
|
if (value.length > 0) {
|
|
246
|
-
const next = { ...params, [child.name]:
|
|
248
|
+
const next = { ...params, [child.name]: value };
|
|
247
249
|
const result = this.search(method, rest, child, nodes, next, state);
|
|
248
250
|
if (result.matched) return result;
|
|
249
251
|
}
|
|
250
252
|
}
|
|
251
253
|
if (node.wildcard && (node.wildcard.handlers.get(method) || node.wildcard.handlers.get("ALL"))) {
|
|
252
254
|
nodes.push(node.wildcard);
|
|
253
|
-
return {
|
|
254
|
-
nodes,
|
|
255
|
-
params: { ...params, wildcard: path },
|
|
256
|
-
matched: true,
|
|
257
|
-
};
|
|
255
|
+
return { nodes, params: { ...params, wildcard: path }, matched: true };
|
|
258
256
|
}
|
|
259
257
|
if (nodes.length > state.nodes.length) {
|
|
260
|
-
state.nodes=nodes.slice()
|
|
261
|
-
params={...params}
|
|
258
|
+
state.nodes = nodes.slice();
|
|
259
|
+
params = { ...params };
|
|
262
260
|
}
|
|
263
261
|
nodes.pop();
|
|
264
262
|
return { nodes: state.nodes, params: state.params, matched: false };
|
|
265
263
|
}
|
|
266
264
|
|
|
267
265
|
/**
|
|
268
|
-
* @param {Node}
|
|
266
|
+
* @param {Node} node
|
|
269
267
|
* @param {String} method
|
|
270
268
|
* @param {Object} handlers
|
|
271
269
|
*/
|
|
272
|
-
collectHandler(
|
|
273
|
-
if (
|
|
274
|
-
for (const
|
|
275
|
-
handlers[
|
|
270
|
+
collectHandler(node, method, handlers) {
|
|
271
|
+
if (node.handlers.has(method)) {
|
|
272
|
+
for (const { seq, handler } of node.handlers.get(method)) {
|
|
273
|
+
handlers[seq] = handler;
|
|
276
274
|
}
|
|
277
275
|
}
|
|
278
276
|
}
|
|
279
277
|
|
|
280
278
|
/**
|
|
281
|
-
* @param {Node}
|
|
279
|
+
* @param {Node} node
|
|
282
280
|
* @param {Object} handlers
|
|
283
281
|
* @param {Object} errorHandlers
|
|
284
282
|
*/
|
|
285
|
-
collectMiddleware(
|
|
286
|
-
this.collectHandler(
|
|
287
|
-
this.collectHandler(
|
|
283
|
+
collectMiddleware(node, handlers, errorHandlers) {
|
|
284
|
+
this.collectHandler(node, "ALL", handlers);
|
|
285
|
+
this.collectHandler(node, "CATCH", errorHandlers);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
decodeParams(obj) {
|
|
289
|
+
const params = Object.create(null);
|
|
290
|
+
for (const key of Object.keys(obj)) {
|
|
291
|
+
params[key] = decodeParam(obj[key]);
|
|
292
|
+
}
|
|
293
|
+
return params;
|
|
288
294
|
}
|
|
289
295
|
|
|
290
296
|
/**
|
|
291
297
|
* @param {String} method
|
|
292
298
|
* @param {String} path
|
|
293
|
-
* @returns {{
|
|
299
|
+
* @returns {{params: Object;handlers: any[];errorHandlers: any[];}}
|
|
294
300
|
*/
|
|
295
301
|
find(method, path) {
|
|
296
302
|
let res = this.search(method, path);
|
|
297
|
-
|
|
298
303
|
if (!res.matched && path.length > 1) {
|
|
299
304
|
const alt = path.endsWith("/") ? path.slice(0, -1) : path + "/";
|
|
300
305
|
res = this.search(method, alt);
|
|
301
306
|
}
|
|
302
307
|
const handlers = {};
|
|
303
308
|
const errorHandlers = {};
|
|
304
|
-
for (const
|
|
305
|
-
this.collectMiddleware(
|
|
309
|
+
for (const node of res.nodes) {
|
|
310
|
+
this.collectMiddleware(node, handlers, errorHandlers);
|
|
306
311
|
}
|
|
307
312
|
if (res.matched) {
|
|
308
|
-
this.collectHandler(res.nodes.
|
|
313
|
+
this.collectHandler(res.nodes[res.nodes.length - 1], method, handlers);
|
|
309
314
|
}
|
|
310
|
-
return {
|
|
311
|
-
matched: res.matched,
|
|
312
|
-
params: res.params,
|
|
313
|
-
paramsLength: Object.keys(res.params).length,
|
|
314
|
-
handlers: Object.values(handlers),
|
|
315
|
-
errorHandlers: Object.values(errorHandlers),
|
|
316
|
-
};
|
|
315
|
+
return { params: res.params, handlers, errorHandlers };
|
|
317
316
|
}
|
|
318
|
-
|
|
319
317
|
}
|
|
320
318
|
exports.Router = Router;
|