slower 2.1.3 → 2.1.6
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/slower.js +230 -62
package/package.json
CHANGED
package/src/slower.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const http = require('node:http');
|
|
3
3
|
const https = require('node:https');
|
|
4
4
|
const path = require('node:path');
|
|
5
|
+
const fs = require('node:fs');
|
|
5
6
|
const { createReadStream } = require('node:fs');
|
|
6
7
|
const { pipeline } = require('node:stream/promises');
|
|
7
8
|
|
|
@@ -33,20 +34,24 @@ class SlowerRouter {
|
|
|
33
34
|
this.layers = new Map();
|
|
34
35
|
|
|
35
36
|
// Create basic route shortcuts
|
|
36
|
-
// get(), post(), put(), delete()
|
|
37
|
-
// They can be used with either 1 or
|
|
37
|
+
// get(), post(), put(), delete(), ...
|
|
38
|
+
// They can be used with either 1 or more params
|
|
38
39
|
/**
|
|
39
|
-
* app.get({path}, {handler})
|
|
40
|
+
* app.get({path}, {handler}) -> apply handlers for a specific route
|
|
41
|
+
* app.get({path}, {handler}, {handler}, ...) -> apply handlers for a specific route
|
|
40
42
|
* or
|
|
41
|
-
* app.get({handler})
|
|
43
|
+
* app.get({handler}) -> apply handlers for any route for a specific method
|
|
44
|
+
* app.get({handler}, {handler}, ...) -> apply handlers for any route for a specific method
|
|
42
45
|
*
|
|
43
46
|
*/
|
|
44
47
|
for (let verb of HTTP_VERBS) {
|
|
45
48
|
this.layers.set(verb, new Map());
|
|
46
|
-
this[verb] = function (path,
|
|
49
|
+
this[verb] = function (path, ...callbacks) {
|
|
47
50
|
if (typeof path === 'function')
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
this.#setRoute(verb, MATCH_ANY, path);
|
|
52
|
+
for (let callback of callbacks)
|
|
53
|
+
this.#setRoute(verb, path, callback);
|
|
54
|
+
return this;
|
|
50
55
|
};
|
|
51
56
|
}
|
|
52
57
|
|
|
@@ -67,8 +72,9 @@ class SlowerRouter {
|
|
|
67
72
|
// Get all routes that match the URL and join with middlewares to cycle
|
|
68
73
|
let foundRoutes = utils.getMatchingRoute(req.url, req.method, self.layers);
|
|
69
74
|
let layers = foundRoutes;
|
|
70
|
-
//
|
|
71
|
-
|
|
75
|
+
// Add an Error:404 special layer to the end of the layers list
|
|
76
|
+
// This prevents accidental requests hanging
|
|
77
|
+
layers.push(utils.noLayersFoundFallback);
|
|
72
78
|
|
|
73
79
|
// Set properties on request and response objects
|
|
74
80
|
req = await setupRequest(req);
|
|
@@ -109,7 +115,7 @@ class SlowerRouter {
|
|
|
109
115
|
* Create a middleware for all HTTP methods, for a specific path
|
|
110
116
|
* @overload
|
|
111
117
|
* @param {String} path
|
|
112
|
-
* @param {Function}
|
|
118
|
+
* @param {...Function} handlers
|
|
113
119
|
* @returns {SlowerRouter}
|
|
114
120
|
* @example Applies a middleware for all methods, for a specific path
|
|
115
121
|
* app.all('/img/:id', (req, res, next) => {console.log(...); next()})
|
|
@@ -119,7 +125,7 @@ class SlowerRouter {
|
|
|
119
125
|
* @info This is the same as using "app[method]({callback})", without a path. Like: app.get(() => {});
|
|
120
126
|
* @overload
|
|
121
127
|
* @param {string} verb (one of the HTTP verbs)
|
|
122
|
-
* @param {Function}
|
|
128
|
+
* @param {...Function} handlers
|
|
123
129
|
* @returns {SlowerRouter}
|
|
124
130
|
* @example Applies a middleware for all GET requests
|
|
125
131
|
* app.all('get', (req, res, next) => {console.log(...); next()})
|
|
@@ -127,28 +133,39 @@ class SlowerRouter {
|
|
|
127
133
|
/**
|
|
128
134
|
* Create a global middleware (all paths and all HTTP methods)
|
|
129
135
|
* @overload
|
|
130
|
-
* @param {Function}
|
|
136
|
+
* @param {...Function} handlers
|
|
131
137
|
* @returns {SlowerRouter}
|
|
132
138
|
* @example Applies a middleware for all HTTP requests (of any method)
|
|
133
139
|
* app.all((req, res, next) => {console.log(...); next()})
|
|
134
140
|
*/
|
|
135
|
-
all (path,
|
|
136
|
-
|
|
141
|
+
all (path, ...handlers) {
|
|
142
|
+
|
|
143
|
+
// function signature: app.all({METHOD}, ...{HANDLERS})
|
|
137
144
|
// example: app.all('post', () => {});
|
|
138
145
|
if (typeof path === 'string' && HTTP_VERBS.includes(path.toLowerCase()))
|
|
139
|
-
|
|
146
|
+
for (let handler of handlers)
|
|
147
|
+
this.#setRoute(path, MATCH_ANY, handler);
|
|
148
|
+
|
|
140
149
|
|
|
141
|
-
// function signature: app.all({PATH}, {
|
|
150
|
+
// function signature: app.all({PATH}, ...{HANDLERS})
|
|
142
151
|
// example: app.all('/api', () => {});
|
|
143
152
|
else if (typeof path === 'string')
|
|
144
|
-
for (let
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
for (let handler of handlers)
|
|
154
|
+
for (let verb of HTTP_VERBS)
|
|
155
|
+
this.#setRoute(verb, path, handler);
|
|
156
|
+
|
|
157
|
+
// function signature: app.all(...{HANDLERS})
|
|
147
158
|
// example: app.all(() => {});
|
|
148
159
|
else if (typeof path === 'function')
|
|
149
|
-
for (let verb of HTTP_VERBS)
|
|
160
|
+
for (let verb of HTTP_VERBS) {
|
|
161
|
+
this.#setRoute(verb, MATCH_ANY, path);
|
|
162
|
+
for (let handler of handlers)
|
|
163
|
+
this.#setRoute(verb, MATCH_ANY, handler);
|
|
164
|
+
}
|
|
150
165
|
|
|
166
|
+
|
|
151
167
|
else throw new Error('<SlowerRouter>.use :: "handler" parameter must be of type Function');
|
|
168
|
+
|
|
152
169
|
return this;
|
|
153
170
|
}
|
|
154
171
|
// Just a more comprehensive call to app.all for defining middlewares
|
|
@@ -171,6 +188,9 @@ class SlowerRouter {
|
|
|
171
188
|
*/
|
|
172
189
|
static (directoryPath, mountPath = '') {
|
|
173
190
|
const absoluteDir = path.resolve(directoryPath);
|
|
191
|
+
if (!fs.existsSync(absoluteDir))
|
|
192
|
+
throw new Error(`Invalid directory provided for [SlowerRouter].static(): [${directoryPath}]`);
|
|
193
|
+
|
|
174
194
|
for (const file of utils.getFiles(absoluteDir)) {
|
|
175
195
|
// Get only the file name from the absolute file path 'c:\u\a.txt' -> 'a.txt'
|
|
176
196
|
let fileAsURLPath = file.replaceAll(/\\/g, '/').split('/').slice(-1)[0];
|
|
@@ -238,21 +258,47 @@ class SlowerRouter {
|
|
|
238
258
|
|
|
239
259
|
|
|
240
260
|
/**
|
|
241
|
-
* Used as the class for
|
|
242
|
-
*
|
|
243
|
-
* only method acessors (.get(), .post(), .put(), ...)
|
|
244
|
-
* and .all() and .use()
|
|
245
|
-
*
|
|
246
|
-
* .static() is not allowed
|
|
261
|
+
* Used as the class for modular routers
|
|
262
|
+
* used in "slower.Router()"
|
|
247
263
|
*/
|
|
248
|
-
class
|
|
249
|
-
constructor (
|
|
250
|
-
this.
|
|
251
|
-
this.layers =
|
|
264
|
+
class SlowerSubRouter {
|
|
265
|
+
constructor () {
|
|
266
|
+
this.METHODS = HTTP_VERBS;
|
|
267
|
+
this.layers = new Array();
|
|
268
|
+
|
|
269
|
+
// OLD version: (Do not delete until new version is properly tested)
|
|
270
|
+
// Create basic route shortcuts
|
|
271
|
+
// get(), post(), put(), delete()
|
|
272
|
+
// for (let verb of HTTP_VERBS) {
|
|
273
|
+
// this[verb] = function (path, callback) {
|
|
274
|
+
// return this.#setRoute(verb, path, callback);
|
|
275
|
+
// };
|
|
276
|
+
// }
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
// Create basic route shortcuts
|
|
280
|
+
// get(), post(), put(), delete(), ...
|
|
281
|
+
// They can be used with either 1 or more params
|
|
282
|
+
/**
|
|
283
|
+
* app.get({path}, {handler}) -> apply handlers for a specific route
|
|
284
|
+
* app.get({path}, {handler}, {handler}, ...) -> apply handlers for a specific route
|
|
285
|
+
* or
|
|
286
|
+
* app.get({handler}) -> apply handlers for any route for a specific method
|
|
287
|
+
* app.get({handler}, {handler}, ...) -> apply handlers for any route for a specific method
|
|
288
|
+
*
|
|
289
|
+
*/
|
|
290
|
+
for (let verb of HTTP_VERBS) {
|
|
291
|
+
this[verb] = function (path, ...callbacks) {
|
|
292
|
+
if (typeof path === 'function')
|
|
293
|
+
this.#setRoute(verb, MATCH_ANY, path);
|
|
294
|
+
for (let callback of callbacks)
|
|
295
|
+
this.#setRoute(verb, path, callback);
|
|
296
|
+
return this;
|
|
297
|
+
};
|
|
298
|
+
}
|
|
252
299
|
}
|
|
253
300
|
|
|
254
|
-
#setRoute (method, handler) {
|
|
255
|
-
const path = this.path;
|
|
301
|
+
#setRoute (method, path, handler) {
|
|
256
302
|
if (typeof method !== 'string')
|
|
257
303
|
throw new Error('<SlowerSubRouter>.route :: "method" parameter must be of type String');
|
|
258
304
|
if (typeof path !== 'string' && path?.constructor?.name !== 'RegExp')
|
|
@@ -263,66 +309,188 @@ class SlowerMicroRouter {
|
|
|
263
309
|
return this;
|
|
264
310
|
}
|
|
265
311
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
312
|
+
// Add middleware
|
|
313
|
+
/**
|
|
314
|
+
* Create a middleware for all HTTP methods, for a specific path
|
|
315
|
+
* @overload
|
|
316
|
+
* @param {String} path
|
|
317
|
+
* @param {...Function} handlers
|
|
318
|
+
* @returns {SlowerRouter}
|
|
319
|
+
* @example Applies a middleware for all methods, for a specific path
|
|
320
|
+
* app.all('/img/:id', (req, res, next) => {console.log(...); next()})
|
|
321
|
+
*/
|
|
322
|
+
/**
|
|
323
|
+
* Create a global middleware for a specific verb (all paths for that method)
|
|
324
|
+
* @info This is the same as using "app[method]({callback})", without a path. Like: app.get(() => {});
|
|
325
|
+
* @overload
|
|
326
|
+
* @param {string} verb (one of the HTTP verbs)
|
|
327
|
+
* @param {...Function} handlers
|
|
328
|
+
* @returns {SlowerRouter}
|
|
329
|
+
* @example Applies a middleware for all GET requests
|
|
330
|
+
* app.all('get', (req, res, next) => {console.log(...); next()})
|
|
331
|
+
*/
|
|
332
|
+
/**
|
|
333
|
+
* Create a global middleware (all paths and all HTTP methods)
|
|
334
|
+
* @overload
|
|
335
|
+
* @param {...Function} handlers
|
|
336
|
+
* @returns {SlowerRouter}
|
|
337
|
+
* @example Applies a middleware for all HTTP requests (of any method)
|
|
338
|
+
* app.all((req, res, next) => {console.log(...); next()})
|
|
339
|
+
*/
|
|
340
|
+
all (path, ...handlers) {
|
|
341
|
+
|
|
342
|
+
// function signature: app.all({METHOD}, ...{HANDLERS})
|
|
343
|
+
// example: app.all('post', () => {});
|
|
344
|
+
if (typeof path === 'string' && HTTP_VERBS.includes(path.toLowerCase()))
|
|
345
|
+
for (let handler of handlers)
|
|
346
|
+
this.#setRoute(path, MATCH_ANY, handler);
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
// function signature: app.all({PATH}, ...{HANDLERS})
|
|
350
|
+
// example: app.all('/api', () => {});
|
|
351
|
+
else if (typeof path === 'string')
|
|
352
|
+
for (let handler of handlers)
|
|
353
|
+
for (let verb of HTTP_VERBS)
|
|
354
|
+
this.#setRoute(verb, path, handler);
|
|
355
|
+
|
|
356
|
+
// function signature: app.all(...{HANDLERS})
|
|
357
|
+
// example: app.all(() => {});
|
|
358
|
+
else if (typeof path === 'function')
|
|
359
|
+
for (let verb of HTTP_VERBS) {
|
|
360
|
+
this.#setRoute(verb, MATCH_ANY, path);
|
|
361
|
+
for (let handler of handlers)
|
|
362
|
+
this.#setRoute(verb, MATCH_ANY, handler);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
else throw new Error('<SlowerSubRouter>.use :: "handler" parameter must be of type Function');
|
|
367
|
+
|
|
273
368
|
return this;
|
|
274
369
|
}
|
|
275
370
|
// Just a more comprehensive call to app.all for defining middlewares
|
|
276
371
|
use (...b) { this.all(...b); return this; };
|
|
372
|
+
|
|
373
|
+
static (directoryPath, mountPath = '') {
|
|
374
|
+
this.layers.push({ static: true, directoryPath, mountPath });
|
|
375
|
+
return this;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Creates a temporary synced mini-router for a specific path
|
|
380
|
+
* Allows to declare multiple handlers for methods of a specific path
|
|
381
|
+
* @param {string} path
|
|
382
|
+
* @returns {SlowerMicroRouter}
|
|
383
|
+
* @example
|
|
384
|
+
* app.route('/books')
|
|
385
|
+
* .get((req, res) => console.log('you retrieved a book with GET'))
|
|
386
|
+
* .post((req, res) => console.log('you added a book with POST'))
|
|
387
|
+
* ;
|
|
388
|
+
*/
|
|
389
|
+
route (path) {
|
|
390
|
+
return new SlowerMicroRouter(path, this.layers);
|
|
391
|
+
}
|
|
277
392
|
}
|
|
278
393
|
|
|
279
394
|
|
|
395
|
+
|
|
280
396
|
/**
|
|
281
|
-
* Used as the class for
|
|
282
|
-
*
|
|
397
|
+
* Used as the class for micro-routing with "app.route"
|
|
398
|
+
*
|
|
399
|
+
* only method acessors (.get(), .post(), .put(), ...)
|
|
400
|
+
* and .all() and .use()
|
|
401
|
+
*
|
|
402
|
+
* .static() is not allowed
|
|
283
403
|
*/
|
|
284
|
-
class
|
|
285
|
-
constructor () {
|
|
286
|
-
this.
|
|
287
|
-
this.layers =
|
|
404
|
+
class SlowerMicroRouter {
|
|
405
|
+
constructor (path, layerPool) {
|
|
406
|
+
this.path = path;
|
|
407
|
+
this.layers = layerPool;
|
|
288
408
|
|
|
289
409
|
// Create basic route shortcuts
|
|
290
410
|
// get(), post(), put(), delete()
|
|
291
411
|
for (let verb of HTTP_VERBS) {
|
|
292
|
-
this[verb] = function (
|
|
293
|
-
|
|
412
|
+
this[verb] = function (...callbacks) {
|
|
413
|
+
for (let callback of callbacks)
|
|
414
|
+
this.#setRoute(verb, callback);
|
|
294
415
|
};
|
|
295
416
|
}
|
|
296
417
|
}
|
|
297
418
|
|
|
298
|
-
#setRoute (method,
|
|
419
|
+
#setRoute (method, handler) {
|
|
420
|
+
const path = this.path;
|
|
299
421
|
if (typeof method !== 'string')
|
|
300
|
-
throw new Error('<
|
|
422
|
+
throw new Error('<SlowerMicroRouter>.route :: "method" parameter must be of type String');
|
|
301
423
|
if (typeof path !== 'string' && path?.constructor?.name !== 'RegExp')
|
|
302
|
-
throw new Error('<
|
|
424
|
+
throw new Error('<SlowerMicroRouter>.route :: "path" parameter must be of type Function, String or RegExp');
|
|
303
425
|
if (typeof handler !== 'function')
|
|
304
|
-
throw new Error('<
|
|
426
|
+
throw new Error('<SlowerMicroRouter>.route :: "handler" parameter must be of type Function');
|
|
305
427
|
this.layers.push({ method, path, handler });
|
|
306
428
|
return this;
|
|
307
429
|
}
|
|
308
430
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
431
|
+
// Add middleware
|
|
432
|
+
/**
|
|
433
|
+
* Create a middleware for all HTTP methods, for a specific path
|
|
434
|
+
* @overload
|
|
435
|
+
* @param {String} path
|
|
436
|
+
* @param {...Function} handlers
|
|
437
|
+
* @returns {SlowerRouter}
|
|
438
|
+
* @example Applies a middleware for all methods, for a specific path
|
|
439
|
+
* app.all('/img/:id', (req, res, next) => {console.log(...); next()})
|
|
440
|
+
*/
|
|
441
|
+
/**
|
|
442
|
+
* Create a global middleware for a specific verb (all paths for that method)
|
|
443
|
+
* @info This is the same as using "app[method]({callback})", without a path. Like: app.get(() => {});
|
|
444
|
+
* @overload
|
|
445
|
+
* @param {string} verb (one of the HTTP verbs)
|
|
446
|
+
* @param {...Function} handlers
|
|
447
|
+
* @returns {SlowerRouter}
|
|
448
|
+
* @example Applies a middleware for all GET requests
|
|
449
|
+
* app.all('get', (req, res, next) => {console.log(...); next()})
|
|
450
|
+
*/
|
|
451
|
+
/**
|
|
452
|
+
* Create a global middleware (all paths and all HTTP methods)
|
|
453
|
+
* @overload
|
|
454
|
+
* @param {...Function} handlers
|
|
455
|
+
* @returns {SlowerRouter}
|
|
456
|
+
* @example Applies a middleware for all HTTP requests (of any method)
|
|
457
|
+
* app.all((req, res, next) => {console.log(...); next()})
|
|
458
|
+
*/
|
|
459
|
+
all (path, ...handlers) {
|
|
460
|
+
|
|
461
|
+
// function signature: app.all({METHOD}, ...{HANDLERS})
|
|
462
|
+
// example: app.all('post', () => {});
|
|
463
|
+
if (typeof path === 'string' && HTTP_VERBS.includes(path.toLowerCase()))
|
|
464
|
+
for (let handler of handlers)
|
|
465
|
+
this.#setRoute(path, MATCH_ANY, handler);
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
// function signature: app.all({PATH}, ...{HANDLERS})
|
|
469
|
+
// example: app.all('/api', () => {});
|
|
470
|
+
else if (typeof path === 'string')
|
|
471
|
+
for (let handler of handlers)
|
|
472
|
+
for (let verb of HTTP_VERBS)
|
|
473
|
+
this.#setRoute(verb, path, handler);
|
|
474
|
+
|
|
475
|
+
// function signature: app.all(...{HANDLERS})
|
|
476
|
+
// example: app.all(() => {});
|
|
477
|
+
else if (typeof path === 'function')
|
|
478
|
+
for (let verb of HTTP_VERBS) {
|
|
479
|
+
this.#setRoute(verb, MATCH_ANY, path);
|
|
480
|
+
for (let handler of handlers)
|
|
481
|
+
this.#setRoute(verb, MATCH_ANY, handler);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
else throw new Error('<SlowerMicroRouter>.use :: "handler" parameter must be of type Function');
|
|
486
|
+
|
|
315
487
|
return this;
|
|
316
488
|
}
|
|
317
489
|
// Just a more comprehensive call to app.all for defining middlewares
|
|
318
490
|
use (...b) { this.all(...b); return this; };
|
|
319
|
-
|
|
320
|
-
static (directoryPath, mountPath = '') {
|
|
321
|
-
this.layers.push({ static: true, directoryPath, mountPath });
|
|
322
|
-
return this;
|
|
323
|
-
}
|
|
324
491
|
}
|
|
325
492
|
|
|
493
|
+
|
|
326
494
|
// Create basic main routing creation
|
|
327
495
|
function slower (options) {
|
|
328
496
|
return new SlowerRouter(options);
|