slower 2.1.8 → 2.1.9

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 CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
- "dependencies": {
3
- "path-to-regexp": "^6.2.2"
4
- },
5
- "name": "slower",
6
- "version": "2.1.8",
7
- "main": "index.js",
8
- "devDependencies": {},
9
- "scripts": {
10
- "test": "echo \"Error: no test specified\" && exit 1"
11
- },
12
- "keywords": [],
13
- "author": "Tomás Luchesi <no.mad.devtech@gmail.com>",
14
- "license": "MIT",
15
- "description": "A package for simple HTTP server routing."
16
- }
2
+ "name": "slower",
3
+ "version": "2.1.9",
4
+ "main": "index.js",
5
+ "devDependencies": {},
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "dependencies": {
10
+ "path-to-regexp": "^6.2.2"
11
+ },
12
+ "keywords": [],
13
+ "author": "Tomás Luchesi <no.mad.devtech@gmail.com>",
14
+ "license": "MIT",
15
+ "description": "A package for simple HTTP server routing."
16
+ }
package/src/decorators.js CHANGED
@@ -11,7 +11,7 @@ const utils = require('./utils');
11
11
  * @exposes .json()
12
12
  * @exposes .file()
13
13
  */
14
- function setupResponse(response) {
14
+ function setupResponse(response, request) {
15
15
  /**
16
16
  * Sets the response status code
17
17
  * @chainable
@@ -67,11 +67,7 @@ function setupResponse(response) {
67
67
  * @info And if no type is specified, binary type is used (application/octet-stream)
68
68
  */
69
69
  response.type = function (mime) {
70
- let mimetype =
71
- MIME_TABLE[mime] ||
72
- mime ||
73
- MIME_TABLE[extension] ||
74
- MIME_TABLE['default'];
70
+ let mimetype = MIME_TABLE[mime] || mime || MIME_TABLE['default'];
75
71
  response.setHeader('Content-type', mimetype);
76
72
  return response;
77
73
  };
@@ -193,7 +189,7 @@ function setupRequest(request) {
193
189
  * @property
194
190
  * Holds the request body data as a buffer
195
191
  */
196
- return new Promise(resolve => {
192
+ return new Promise((resolve, reject) => {
197
193
  // Set classical socket locals
198
194
  request.session = {
199
195
  port: request.socket.localPort,
package/src/slower.js CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  const http = require('node:http');
3
2
  const https = require('node:https');
4
3
  const path = require('node:path');
@@ -20,16 +19,16 @@ class SlowerRouter {
20
19
 
21
20
  // You can create it with HTTPS options here
22
21
  /**
23
- * Use HTTPS server instead of HTTP.
22
+ * Use HTTPS server instead of HTTP.
24
23
  * Pass in all regular HTTPS options as parameters.
25
24
  * 'key' and 'cert' options are required for HTTPS.
26
- * @param {object} options
25
+ * @param {object} options
27
26
  * @returns {http.Server|https.Server}
28
27
  * @example
29
28
  * SlowerRouter({https:true, key:'...', cert:'...'}); // Create HTTPS server
30
29
  * SlowerRouter(); // Create regular HTTP
31
30
  */
32
- constructor (options = {}) {
31
+ constructor(options = {}) {
33
32
  this.METHODS = HTTP_VERBS;
34
33
  this.layers = new Map();
35
34
 
@@ -42,7 +41,7 @@ class SlowerRouter {
42
41
  * or
43
42
  * app.get({handler}) -> apply handlers for any route for a specific method
44
43
  * app.get({handler}, {handler}, ...) -> apply handlers for any route for a specific method
45
- *
44
+ *
46
45
  */
47
46
  for (let verb of HTTP_VERBS) {
48
47
  this.layers.set(verb, new Map());
@@ -55,22 +54,24 @@ class SlowerRouter {
55
54
  };
56
55
  }
57
56
 
58
- if (options.https)
59
- this.#server = https.createServer(options);
60
- else
61
- this.#server = http.createServer(options);
57
+ if (options.https) this.#server = https.createServer(options);
58
+ else this.#server = http.createServer(options);
62
59
 
63
60
  this.#server.on('request', this.#requestHandlerWrapper(this));
64
61
  }
65
-
66
- #requestHandlerWrapper () {
62
+
63
+ #requestHandlerWrapper() {
67
64
  // Save the 'this' scope
68
65
  // Inside the requestHandler function, 'this' corresponds to the http.Server instance
69
66
  const self = this;
70
67
 
71
- return (async function requestHandler (req, res) {
68
+ return async function requestHandler(req, res) {
72
69
  // Get all routes that match the URL and join with middlewares to cycle
73
- let foundRoutes = utils.getMatchingRoute(req.url, req.method, self.layers);
70
+ let foundRoutes = utils.getMatchingRoute(
71
+ req.url,
72
+ req.method,
73
+ self.layers
74
+ );
74
75
  let layers = foundRoutes;
75
76
  // Add an Error:404 special layer to the end of the layers list
76
77
  // This prevents accidental requests hanging
@@ -78,33 +79,46 @@ class SlowerRouter {
78
79
 
79
80
  // Set properties on request and response objects
80
81
  req = await setupRequest(req);
81
- res = await setupResponse(res);
82
+ res = await setupResponse(res, req);
82
83
 
83
84
  // Cycle throught all middlewares and proper routes and call with 'next()' as third argument
84
- ;(async function cycleMatching (routes) {
85
+ (async function cycleMatching(routes) {
85
86
  if (routes.length === 0) return;
86
87
  let route = routes[0];
87
88
  if (route.params) req.params = route.params;
88
89
  if (route.callback) route = route.callback;
89
90
  route(req, res, async () => cycleMatching(routes.slice(1)));
90
91
  })(layers);
91
- });
92
+ };
92
93
  }
93
94
 
94
- listen (...v) { return this.#server.listen(...v); }
95
- close (callback) { return this.#server.close(callback); }
95
+ listen(...v) {
96
+ return this.#server.listen(...v);
97
+ }
98
+ close(callback) {
99
+ return this.#server.close(callback);
100
+ }
96
101
 
97
102
  // Add any type of route
98
- #setRoute (method, path, handler) {
99
- if (typeof method !== 'string')
100
- throw new Error('<SlowerRouter>.route :: "method" parameter must be of type String');
101
- if (typeof path !== 'string' && typeof path !== 'function' && path?.constructor?.name !== 'RegExp')
102
- throw new Error('<SlowerRouter>.route :: "path" parameter must be of type Function, String or RegExp');
103
+ #setRoute(method, path, handler) {
104
+ if (typeof method !== 'string')
105
+ throw new Error(
106
+ '<SlowerRouter>.route :: "method" parameter must be of type String'
107
+ );
108
+ if (
109
+ typeof path !== 'string' &&
110
+ typeof path !== 'function' &&
111
+ path?.constructor?.name !== 'RegExp'
112
+ )
113
+ throw new Error(
114
+ '<SlowerRouter>.route :: "path" parameter must be of type Function, String or RegExp'
115
+ );
103
116
  if (typeof handler !== 'function')
104
- throw new Error('<SlowerRouter>.route :: "handler" parameter must be of type Function');
105
- if (!this.layers.get(method))
106
- this.layers.set(method, new Map());
107
- if (typeof path === 'string' || path?.constructor?.name !== 'RegExp')
117
+ throw new Error(
118
+ '<SlowerRouter>.route :: "handler" parameter must be of type Function'
119
+ );
120
+ if (!this.layers.get(method)) this.layers.set(method, new Map());
121
+ if (typeof path === 'string' || path?.constructor?.name !== 'RegExp')
108
122
  path = match(path, { decode: decodeURIComponent }); // 'path' is a function now
109
123
  this.layers.get(method).set(path, handler);
110
124
  return this;
@@ -114,7 +128,7 @@ class SlowerRouter {
114
128
  /**
115
129
  * Create a middleware for all HTTP methods, for a specific path
116
130
  * @overload
117
- * @param {String} path
131
+ * @param {String} path
118
132
  * @param {...Function} handlers
119
133
  * @returns {SlowerRouter}
120
134
  * @example Applies a middleware for all methods, for a specific path
@@ -123,7 +137,7 @@ class SlowerRouter {
123
137
  /**
124
138
  * Create a global middleware for a specific verb (all paths for that method)
125
139
  * @info This is the same as using "app[method]({callback})", without a path. Like: app.get(() => {});
126
- * @overload
140
+ * @overload
127
141
  * @param {string} verb (one of the HTTP verbs)
128
142
  * @param {...Function} handlers
129
143
  * @returns {SlowerRouter}
@@ -132,44 +146,44 @@ class SlowerRouter {
132
146
  */
133
147
  /**
134
148
  * Create a global middleware (all paths and all HTTP methods)
135
- * @overload
136
- * @param {...Function} handlers
149
+ * @overload
150
+ * @param {...Function} handlers
137
151
  * @returns {SlowerRouter}
138
152
  * @example Applies a middleware for all HTTP requests (of any method)
139
153
  * app.all((req, res, next) => {console.log(...); next()})
140
154
  */
141
- all (path, ...handlers) {
142
-
155
+ all(path, ...handlers) {
143
156
  // function signature: app.all({METHOD}, ...{HANDLERS})
144
157
  // example: app.all('post', () => {});
145
158
  if (typeof path === 'string' && HTTP_VERBS.includes(path.toLowerCase()))
146
159
  for (let handler of handlers)
147
160
  this.#setRoute(path, MATCH_ANY, handler);
148
-
149
-
150
161
  // function signature: app.all({PATH}, ...{HANDLERS})
151
162
  // example: app.all('/api', () => {});
152
163
  else if (typeof path === 'string')
153
164
  for (let handler of handlers)
154
- for (let verb of HTTP_VERBS)
165
+ for (let verb of HTTP_VERBS)
155
166
  this.#setRoute(verb, path, handler);
156
-
157
167
  // function signature: app.all(...{HANDLERS})
158
- // example: app.all(() => {});
168
+ // example: app.all(() => {});
159
169
  else if (typeof path === 'function')
160
170
  for (let verb of HTTP_VERBS) {
161
171
  this.#setRoute(verb, MATCH_ANY, path);
162
172
  for (let handler of handlers)
163
173
  this.#setRoute(verb, MATCH_ANY, handler);
164
174
  }
165
-
166
-
167
- else throw new Error('<SlowerRouter>.use :: "handler" parameter must be of type Function');
175
+ else
176
+ throw new Error(
177
+ '<SlowerRouter>.use :: "handler" parameter must be of type Function'
178
+ );
168
179
 
169
180
  return this;
170
181
  }
171
182
  // Just a more comprehensive call to app.all for defining middlewares
172
- use (...b) { this.all(...b); return this; };
183
+ use(...b) {
184
+ this.all(...b);
185
+ return this;
186
+ }
173
187
 
174
188
  /**
175
189
  * Serve static files from a directory
@@ -179,33 +193,46 @@ class SlowerRouter {
179
193
  * @example
180
194
  * // Using a mounting poing:
181
195
  * app.static('./public', '/files') // Access with 'GET /files/{filename}'
182
- *
196
+ *
183
197
  * // Not using a mounting point:
184
198
  * app.static('./public') // Access with 'GET /public/{filename}'
185
- *
199
+ *
186
200
  * // Using root ('/') as mounting point:
187
201
  * app.static('./public', '/') // Access with 'GET /{filename}'
188
202
  */
189
- static (directoryPath, mountPath = '') {
203
+ static(directoryPath, mountPath = '') {
190
204
  const absoluteDir = path.resolve(directoryPath);
191
205
  if (!fs.existsSync(absoluteDir))
192
- throw new Error(`Invalid directory provided for [SlowerRouter].static(): [${directoryPath}]`);
206
+ throw new Error(
207
+ `Invalid directory provided for [SlowerRouter].static(): [${directoryPath}]`
208
+ );
193
209
 
194
210
  for (const file of utils.getFiles(absoluteDir)) {
195
211
  // Get only the file name from the absolute file path 'c:\u\a.txt' -> 'a.txt'
196
- let fileAsURLPath = file.replaceAll(/\\/g, '/').split('/').slice(-1)[0];
212
+ let fileAsURLPath = file
213
+ .replaceAll(/\\/g, '/')
214
+ .split('/')
215
+ .slice(-1)[0];
197
216
  // If there is a mount path, merge it with the file and remove duplicate bars '//'
198
- if (!mountPath) mountPath = directoryPath.replaceAll(/\\/g, '/').split('/').slice(-1)[0];
199
- fileAsURLPath = ('/' + mountPath + '/' + fileAsURLPath).replaceAll(/\/+/g,'/');
200
-
201
-
202
- async function staticfhandle (req, res, next) {
217
+ if (!mountPath)
218
+ mountPath = directoryPath
219
+ .replaceAll(/\\/g, '/')
220
+ .split('/')
221
+ .slice(-1)[0];
222
+ fileAsURLPath = ('/' + mountPath + '/' + fileAsURLPath).replaceAll(
223
+ /\/+/g,
224
+ '/'
225
+ );
226
+
227
+ async function staticfhandle(req, res /*next*/) {
203
228
  try {
204
229
  const fileStream = createReadStream(file);
205
- res.setHeader('Content-Type', MIME_TABLE[extension] || MIME_TABLE['default']);
230
+ res.setHeader(
231
+ 'Content-Type',
232
+ MIME_TABLE[extension] || MIME_TABLE['default']
233
+ );
206
234
  return await pipeline(fileStream, res);
207
-
208
- } catch (err) {
235
+ } catch {
209
236
  // In case the file does not exist, return a 404 and prevent it from breaking
210
237
  res.status(404).end();
211
238
  }
@@ -216,7 +243,7 @@ class SlowerRouter {
216
243
  // If the file is an html file, also add a path for using it without the '.html' extension
217
244
  // both 'GET /files/somefile.html' and 'GET /files/somefile' would work
218
245
  const extension = utils.getFileExtension(file);
219
- if (extension === 'html')
246
+ if (extension === 'html')
220
247
  this.get(fileAsURLPath.replace('.html', ''), staticfhandle);
221
248
  }
222
249
  return this;
@@ -225,13 +252,14 @@ class SlowerRouter {
225
252
  /**
226
253
  * Import and use another SlowerRouter, mounted at a specific path
227
254
  * @param {string} mountPath Mount the router at a specific path
228
- * @param {SlowerRouter} SlowerRouterInstance
255
+ * @param {SlowerRouter} SlowerRouterInstance
229
256
  */
230
- useRouter (SlowerSubRouterInstance, mountPath = '/') {
231
- const mount = p => mountPath ? (mountPath + '/' + p).replace(/\/{2,}/g, '/') : p;
257
+ useRouter(SlowerSubRouterInstance, mountPath = '/') {
258
+ const mount = p =>
259
+ mountPath ? (mountPath + '/' + p).replace(/\/{2,}/g, '/') : p;
232
260
  const layers = SlowerSubRouterInstance.layers;
233
261
  for (let layer of layers) {
234
- if (!!layer.static) {
262
+ if (layer.static) {
235
263
  this.static(layer.directoryPath, mount(layer.mountPath));
236
264
  continue;
237
265
  }
@@ -243,38 +271,36 @@ class SlowerRouter {
243
271
  /**
244
272
  * Creates a temporary synced mini-router for a specific path
245
273
  * Allows to declare multiple handlers for methods of a specific path
246
- * @param {string} path
274
+ * @param {string} path
247
275
  * @returns {SlowerMicroRouter}
248
- * @example
276
+ * @example
249
277
  * app.route('/books')
250
278
  * .get((req, res) => console.log('you retrieved a book with GET'))
251
279
  * .post((req, res) => console.log('you added a book with POST'))
252
280
  * ;
253
281
  */
254
- route (path) {
282
+ route(path) {
255
283
  return new SlowerMicroRouter(path, this.layers);
256
284
  }
257
285
  }
258
286
 
259
-
260
287
  /**
261
288
  * Used as the class for modular routers
262
289
  * used in "slower.Router()"
263
290
  */
264
291
  class SlowerSubRouter {
265
- constructor () {
292
+ constructor() {
266
293
  this.METHODS = HTTP_VERBS;
267
294
  this.layers = new Array();
268
295
 
269
296
  // 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
-
297
+ // Create basic route shortcuts
298
+ // get(), post(), put(), delete()
299
+ // for (let verb of HTTP_VERBS) {
300
+ // this[verb] = function (path, callback) {
301
+ // return this.#setRoute(verb, path, callback);
302
+ // };
303
+ // }
278
304
 
279
305
  // Create basic route shortcuts
280
306
  // get(), post(), put(), delete(), ...
@@ -285,7 +311,7 @@ class SlowerSubRouter {
285
311
  * or
286
312
  * app.get({handler}) -> apply handlers for any route for a specific method
287
313
  * app.get({handler}, {handler}, ...) -> apply handlers for any route for a specific method
288
- *
314
+ *
289
315
  */
290
316
  for (let verb of HTTP_VERBS) {
291
317
  this[verb] = function (path, ...callbacks) {
@@ -298,13 +324,19 @@ class SlowerSubRouter {
298
324
  }
299
325
  }
300
326
 
301
- #setRoute (method, path, handler) {
302
- if (typeof method !== 'string')
303
- throw new Error('<SlowerSubRouter>.route :: "method" parameter must be of type String');
327
+ #setRoute(method, path, handler) {
328
+ if (typeof method !== 'string')
329
+ throw new Error(
330
+ '<SlowerSubRouter>.route :: "method" parameter must be of type String'
331
+ );
304
332
  if (typeof path !== 'string' && path?.constructor?.name !== 'RegExp')
305
- throw new Error('<SlowerSubRouter>.route :: "path" parameter must be of type Function, String or RegExp');
333
+ throw new Error(
334
+ '<SlowerSubRouter>.route :: "path" parameter must be of type Function, String or RegExp'
335
+ );
306
336
  if (typeof handler !== 'function')
307
- throw new Error('<SlowerSubRouter>.route :: "handler" parameter must be of type Function');
337
+ throw new Error(
338
+ '<SlowerSubRouter>.route :: "handler" parameter must be of type Function'
339
+ );
308
340
  this.layers.push({ method, path, handler });
309
341
  return this;
310
342
  }
@@ -313,8 +345,8 @@ class SlowerSubRouter {
313
345
  /**
314
346
  * Create a middleware for all HTTP methods, for a specific path
315
347
  * @overload
316
- * @param {String} path
317
- * @param {...Function} handlers
348
+ * @param {String} path
349
+ * @param {...Function} handlers
318
350
  * @returns {SlowerRouter}
319
351
  * @example Applies a middleware for all methods, for a specific path
320
352
  * app.all('/img/:id', (req, res, next) => {console.log(...); next()})
@@ -322,7 +354,7 @@ class SlowerSubRouter {
322
354
  /**
323
355
  * Create a global middleware for a specific verb (all paths for that method)
324
356
  * @info This is the same as using "app[method]({callback})", without a path. Like: app.get(() => {});
325
- * @overload
357
+ * @overload
326
358
  * @param {string} verb (one of the HTTP verbs)
327
359
  * @param {...Function} handlers
328
360
  * @returns {SlowerRouter}
@@ -331,46 +363,46 @@ class SlowerSubRouter {
331
363
  */
332
364
  /**
333
365
  * Create a global middleware (all paths and all HTTP methods)
334
- * @overload
366
+ * @overload
335
367
  * @param {...Function} handlers
336
368
  * @returns {SlowerRouter}
337
369
  * @example Applies a middleware for all HTTP requests (of any method)
338
370
  * app.all((req, res, next) => {console.log(...); next()})
339
371
  */
340
- all (path, ...handlers) {
341
-
372
+ all(path, ...handlers) {
342
373
  // function signature: app.all({METHOD}, ...{HANDLERS})
343
374
  // example: app.all('post', () => {});
344
375
  if (typeof path === 'string' && HTTP_VERBS.includes(path.toLowerCase()))
345
376
  for (let handler of handlers)
346
377
  this.#setRoute(path, MATCH_ANY, handler);
347
-
348
-
349
378
  // function signature: app.all({PATH}, ...{HANDLERS})
350
379
  // example: app.all('/api', () => {});
351
380
  else if (typeof path === 'string')
352
381
  for (let handler of handlers)
353
- for (let verb of HTTP_VERBS)
382
+ for (let verb of HTTP_VERBS)
354
383
  this.#setRoute(verb, path, handler);
355
-
356
384
  // function signature: app.all(...{HANDLERS})
357
- // example: app.all(() => {});
385
+ // example: app.all(() => {});
358
386
  else if (typeof path === 'function')
359
387
  for (let verb of HTTP_VERBS) {
360
388
  this.#setRoute(verb, MATCH_ANY, path);
361
389
  for (let handler of handlers)
362
390
  this.#setRoute(verb, MATCH_ANY, handler);
363
391
  }
364
-
365
-
366
- else throw new Error('<SlowerSubRouter>.use :: "handler" parameter must be of type Function');
392
+ else
393
+ throw new Error(
394
+ '<SlowerSubRouter>.use :: "handler" parameter must be of type Function'
395
+ );
367
396
 
368
397
  return this;
369
398
  }
370
399
  // Just a more comprehensive call to app.all for defining middlewares
371
- use (...b) { this.all(...b); return this; };
400
+ use(...b) {
401
+ this.all(...b);
402
+ return this;
403
+ }
372
404
 
373
- static (directoryPath, mountPath = '') {
405
+ static(directoryPath, mountPath = '') {
374
406
  this.layers.push({ static: true, directoryPath, mountPath });
375
407
  return this;
376
408
  }
@@ -378,31 +410,29 @@ class SlowerSubRouter {
378
410
  /**
379
411
  * Creates a temporary synced mini-router for a specific path
380
412
  * Allows to declare multiple handlers for methods of a specific path
381
- * @param {string} path
413
+ * @param {string} path
382
414
  * @returns {SlowerMicroRouter}
383
- * @example
415
+ * @example
384
416
  * app.route('/books')
385
417
  * .get((req, res) => console.log('you retrieved a book with GET'))
386
418
  * .post((req, res) => console.log('you added a book with POST'))
387
419
  * ;
388
420
  */
389
- route (path) {
421
+ route(path) {
390
422
  return new SlowerMicroRouter(path, this.layers);
391
423
  }
392
424
  }
393
425
 
394
-
395
-
396
426
  /**
397
427
  * Used as the class for micro-routing with "app.route"
398
- *
428
+ *
399
429
  * only method acessors (.get(), .post(), .put(), ...)
400
430
  * and .all() and .use()
401
- *
431
+ *
402
432
  * .static() is not allowed
403
433
  */
404
434
  class SlowerMicroRouter {
405
- constructor (path, layerPool) {
435
+ constructor(path, layerPool) {
406
436
  this.path = path;
407
437
  this.layers = layerPool;
408
438
 
@@ -410,21 +440,26 @@ class SlowerMicroRouter {
410
440
  // get(), post(), put(), delete()
411
441
  for (let verb of HTTP_VERBS) {
412
442
  this[verb] = function (...callbacks) {
413
- for (let callback of callbacks)
414
- this.#setRoute(verb, callback);
415
- return this;
443
+ for (let callback of callbacks) this.#setRoute(verb, callback);
444
+ return this;
416
445
  };
417
446
  }
418
447
  }
419
448
 
420
- #setRoute (method, handler) {
449
+ #setRoute(method, handler) {
421
450
  const path = this.path;
422
- if (typeof method !== 'string')
423
- throw new Error('<SlowerMicroRouter>.route :: "method" parameter must be of type String');
451
+ if (typeof method !== 'string')
452
+ throw new Error(
453
+ '<SlowerMicroRouter>.route :: "method" parameter must be of type String'
454
+ );
424
455
  if (typeof path !== 'string' && path?.constructor?.name !== 'RegExp')
425
- throw new Error('<SlowerMicroRouter>.route :: "path" parameter must be of type Function, String or RegExp');
456
+ throw new Error(
457
+ '<SlowerMicroRouter>.route :: "path" parameter must be of type Function, String or RegExp'
458
+ );
426
459
  if (typeof handler !== 'function')
427
- throw new Error('<SlowerMicroRouter>.route :: "handler" parameter must be of type Function');
460
+ throw new Error(
461
+ '<SlowerMicroRouter>.route :: "handler" parameter must be of type Function'
462
+ );
428
463
  this.layers.push({ method, path, handler });
429
464
  return this;
430
465
  }
@@ -433,8 +468,8 @@ class SlowerMicroRouter {
433
468
  /**
434
469
  * Create a middleware for all HTTP methods, for a specific path
435
470
  * @overload
436
- * @param {String} path
437
- * @param {...Function} handlers
471
+ * @param {String} path
472
+ * @param {...Function} handlers
438
473
  * @returns {SlowerRouter}
439
474
  * @example Applies a middleware for all methods, for a specific path
440
475
  * app.all('/img/:id', (req, res, next) => {console.log(...); next()})
@@ -442,63 +477,63 @@ class SlowerMicroRouter {
442
477
  /**
443
478
  * Create a global middleware for a specific verb (all paths for that method)
444
479
  * @info This is the same as using "app[method]({callback})", without a path. Like: app.get(() => {});
445
- * @overload
480
+ * @overload
446
481
  * @param {string} verb (one of the HTTP verbs)
447
- * @param {...Function} handlers
482
+ * @param {...Function} handlers
448
483
  * @returns {SlowerRouter}
449
484
  * @example Applies a middleware for all GET requests
450
485
  * app.all('get', (req, res, next) => {console.log(...); next()})
451
486
  */
452
487
  /**
453
488
  * Create a global middleware (all paths and all HTTP methods)
454
- * @overload
455
- * @param {...Function} handlers
489
+ * @overload
490
+ * @param {...Function} handlers
456
491
  * @returns {SlowerRouter}
457
492
  * @example Applies a middleware for all HTTP requests (of any method)
458
493
  * app.all((req, res, next) => {console.log(...); next()})
459
494
  */
460
- all (path, ...handlers) {
461
-
495
+ all(path, ...handlers) {
462
496
  // function signature: app.all({METHOD}, ...{HANDLERS})
463
497
  // example: app.all('post', () => {});
464
498
  if (typeof path === 'string' && HTTP_VERBS.includes(path.toLowerCase()))
465
499
  for (let handler of handlers)
466
500
  this.#setRoute(path, MATCH_ANY, handler);
467
-
468
-
469
501
  // function signature: app.all({PATH}, ...{HANDLERS})
470
502
  // example: app.all('/api', () => {});
471
503
  else if (typeof path === 'string')
472
504
  for (let handler of handlers)
473
- for (let verb of HTTP_VERBS)
505
+ for (let verb of HTTP_VERBS)
474
506
  this.#setRoute(verb, path, handler);
475
-
476
507
  // function signature: app.all(...{HANDLERS})
477
- // example: app.all(() => {});
508
+ // example: app.all(() => {});
478
509
  else if (typeof path === 'function')
479
510
  for (let verb of HTTP_VERBS) {
480
511
  this.#setRoute(verb, MATCH_ANY, path);
481
512
  for (let handler of handlers)
482
513
  this.#setRoute(verb, MATCH_ANY, handler);
483
514
  }
515
+ else
516
+ throw new Error(
517
+ '<SlowerMicroRouter>.use :: "handler" parameter must be of type Function'
518
+ );
484
519
 
485
-
486
- else throw new Error('<SlowerMicroRouter>.use :: "handler" parameter must be of type Function');
487
-
488
520
  return this;
489
521
  }
490
522
  // Just a more comprehensive call to app.all for defining middlewares
491
- use (...b) { this.all(...b); return this; };
523
+ use(...b) {
524
+ this.all(...b);
525
+ return this;
526
+ }
492
527
  }
493
528
 
494
-
495
529
  // Create basic main routing creation
496
- function slower (options) {
530
+ function slower(options) {
497
531
  return new SlowerRouter(options);
498
532
  }
533
+
499
534
  // Add the subrouter class
500
535
  slower.Router = function () {
501
536
  return new SlowerSubRouter();
502
- }
537
+ };
503
538
 
504
539
  module.exports = slower;
package/src/utils.js CHANGED
@@ -1,17 +1,15 @@
1
-
2
- const { statSync, readdirSync } = require('node:fs')
1
+ const { statSync, readdirSync } = require('node:fs');
3
2
  const { join } = require('node:path');
4
3
  const { parse } = require('node:querystring');
5
4
 
6
5
  function* getFiles(folder) {
7
6
  const files = readdirSync(folder);
8
7
  for (const file of files) {
9
- const absolutePath = join(folder, file)
8
+ const absolutePath = join(folder, file);
10
9
  if (statSync(absolutePath).isDirectory()) {
11
- yield* getFiles(absolutePath)
12
- }
13
- else {
14
- yield absolutePath.replaceAll('..\\','')
10
+ yield* getFiles(absolutePath);
11
+ } else {
12
+ yield absolutePath.replaceAll('..\\', '');
15
13
  }
16
14
  }
17
15
  }
@@ -22,44 +20,48 @@ const getMatchingRoute = (url, method, layers) => {
22
20
  // Get only the layers from the proper HTTP verb
23
21
  let routes = layers.get(method) || new Map();
24
22
  // Iterate through all routes, and get the one that match
25
- for (let [ pathFn, callback ] of routes) {
23
+ for (let [pathFn, callback] of routes) {
26
24
  let params = pathFn(getURLPathBody(url));
27
25
  // Return the matching route
28
- if (!!params) {
26
+ if (params) {
29
27
  // add to list
30
- let built = ({ callback });
28
+ let built = { callback };
31
29
  if (params.params && params.params['0'] === undefined)
32
30
  built['params'] = params.params;
33
31
  list.push(built);
34
32
  }
35
33
  }
36
34
  return list;
37
- }
35
+ };
38
36
 
39
- const normalizeAddress = addr => addr.startsWith('::') ? addr : addr.substring(addr.indexOf(':',2)+1);
37
+ const normalizeAddress = addr =>
38
+ addr.startsWith('::') ? addr : addr.substring(addr.indexOf(':', 2) + 1);
40
39
 
41
- const getFileExtension = (fname) => fname.split('.').filter(Boolean).slice(-1)[0];
40
+ const getFileExtension = fname => fname.split('.').filter(Boolean).slice(-1)[0];
42
41
 
43
42
  // /page?foo=bar&abc=123 -> /page
44
43
  const getURLPathBody = (urlPath = '') => urlPath.split('?')[0] || '';
45
44
 
46
45
  // /page?foo=bar&abc=123 -> { foo: 'bar', abc: '123' }
47
- const getURLQueryString = (urlPath = '') => parse((urlPath.split('?')[1] || '').split('#')[0]);
48
-
49
- const noLayersFoundFallback = (req, res) =>
50
- res.status(404).send(
51
- `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">` +
52
- `<title>Error</title></head><body>` +
53
- `<pre>Cannot ${req.method.toUpperCase()} ${req.url}</pre></body></html>`
54
- )
55
- ;
46
+ const getURLQueryString = (urlPath = '') =>
47
+ parse((urlPath.split('?')[1] || '').split('#')[0]);
56
48
 
57
- module.exports = {
58
- getMatchingRoute,
59
- getFiles,
60
- normalizeAddress,
61
- getFileExtension,
62
- getURLPathBody,
49
+ const noLayersFoundFallback = (req, res) =>
50
+ res
51
+ .status(404)
52
+ .send(
53
+ `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">` +
54
+ `<title>Error</title></head><body>` +
55
+ `<pre>Cannot ${req.method.toUpperCase()} ${
56
+ req.url
57
+ }</pre></body></html>`
58
+ );
59
+ module.exports = {
60
+ getMatchingRoute,
61
+ getFiles,
62
+ normalizeAddress,
63
+ getFileExtension,
64
+ getURLPathBody,
63
65
  getURLQueryString,
64
- noLayersFoundFallback
65
- };
66
+ noLayersFoundFallback,
67
+ };