nodester 0.0.1

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/Readme.md +125 -0
  3. package/docs/App.md +13 -0
  4. package/docs/Queries.md +61 -0
  5. package/docs/Readme.md +2 -0
  6. package/docs/Routing.md +34 -0
  7. package/examples/goal/index.js +23 -0
  8. package/examples/rest/index.js +25 -0
  9. package/examples/rest/node_modules/.package-lock.json +40 -0
  10. package/examples/rest/package-lock.json +72 -0
  11. package/examples/rest/package.json +14 -0
  12. package/lib/application/MiddlewareStack.js +125 -0
  13. package/lib/application/http/request.js +462 -0
  14. package/lib/application/http/response.js +1107 -0
  15. package/lib/application/http/utils.js +254 -0
  16. package/lib/application/index.js +292 -0
  17. package/lib/constants/ConstantsEnum.js +13 -0
  18. package/lib/constants/ResponseFormats.js +7 -0
  19. package/lib/controllers/Controller.js +474 -0
  20. package/lib/controllers/JWTController.js +240 -0
  21. package/lib/controllers/ServiceController.js +109 -0
  22. package/lib/controllers/WebController.js +75 -0
  23. package/lib/facades/Facade.js +388 -0
  24. package/lib/facades/FacadeParams.js +11 -0
  25. package/lib/facades/ServiceFacade.js +17 -0
  26. package/lib/facades/jwt.facade.js +273 -0
  27. package/lib/factories/errors/CustomError.js +22 -0
  28. package/lib/factories/errors/index.js +9 -0
  29. package/lib/factories/responses/api.js +90 -0
  30. package/lib/factories/responses/html.js +55 -0
  31. package/lib/logger/console.js +24 -0
  32. package/lib/models/DisabledRefreshToken.js +68 -0
  33. package/lib/models/Extractor.js +320 -0
  34. package/lib/models/define.js +62 -0
  35. package/lib/models/mixins.js +369 -0
  36. package/lib/policies/Role.js +77 -0
  37. package/lib/policies/RoleExtracting.js +97 -0
  38. package/lib/preprocessors/BodyPreprocessor.js +61 -0
  39. package/lib/preprocessors/IncludesPreprocessor.js +55 -0
  40. package/lib/preprocessors/QueryPreprocessor.js +64 -0
  41. package/lib/routers/Default/index.js +143 -0
  42. package/lib/routers/Default/layer.js +50 -0
  43. package/lib/routers/Main/index.js +10 -0
  44. package/lib/routers/Roles/index.js +81 -0
  45. package/lib/services/includes.service.js +79 -0
  46. package/lib/services/jwt.service.js +147 -0
  47. package/lib/tools/sql.tool.js +82 -0
  48. package/lib/utils/dates.util.js +23 -0
  49. package/lib/utils/forms.util.js +22 -0
  50. package/lib/utils/json.util.js +49 -0
  51. package/lib/utils/mappers/Routes/index.js +100 -0
  52. package/lib/utils/mappers/Routes/utils.js +20 -0
  53. package/lib/utils/modelAssociations.util.js +44 -0
  54. package/lib/utils/objects.util.js +69 -0
  55. package/lib/utils/params.util.js +19 -0
  56. package/lib/utils/path.util.js +26 -0
  57. package/lib/utils/queries.util.js +240 -0
  58. package/lib/utils/sanitizations.util.js +111 -0
  59. package/lib/utils/sql.util.js +78 -0
  60. package/lib/utils/strings.util.js +43 -0
  61. package/lib/utils/types.util.js +26 -0
  62. package/package.json +63 -0
  63. package/tests/index.test.js +35 -0
@@ -0,0 +1,462 @@
1
+ /*!
2
+ * /nodester
3
+ * MIT Licensed
4
+ */
5
+ 'use strict';
6
+
7
+ const accepts = require('accepts');
8
+ const isIP = require('net').isIP;
9
+ const typeis = require('type-is');
10
+ const http = require('http');
11
+ const fresh = require('fresh');
12
+ const parseRange = require('range-parser');
13
+ const parse = require('parseurl');
14
+ const proxyaddr = require('proxy-addr');
15
+
16
+
17
+ const req = http.IncomingMessage.prototype;
18
+
19
+ module.exports = req;
20
+
21
+ /**
22
+ * Return request header.
23
+ *
24
+ * The `Referrer` header field is special-cased,
25
+ * both `Referrer` and `Referer` are interchangeable.
26
+ *
27
+ * Examples:
28
+ *
29
+ * req.get('Content-Type');
30
+ * // => "text/plain"
31
+ *
32
+ * req.get('content-type');
33
+ * // => "text/plain"
34
+ *
35
+ * req.get('Something');
36
+ * // => undefined
37
+ *
38
+ * Aliased as `req.header()`.
39
+ *
40
+ * @param {String} name
41
+ * @return {String}
42
+ * @public
43
+ */
44
+ req.get =
45
+ req.header = function header(name) {
46
+ if (!name) {
47
+ throw new TypeError('name argument is required to req.get');
48
+ }
49
+
50
+ if (typeof name !== 'string') {
51
+ throw new TypeError('name must be a string to req.get');
52
+ }
53
+
54
+ const lowerCased = name.toLowerCase();
55
+
56
+ switch (lowerCased) {
57
+ case 'referer':
58
+ case 'referrer':
59
+ return this.headers.referrer || this.headers.referer;
60
+ default:
61
+ return this.headers[lowerCased];
62
+ }
63
+ };
64
+
65
+
66
+ /**
67
+ * To do: update docs.
68
+ *
69
+ * Check if the given `type(s)` is acceptable, returning
70
+ * the best match when true, otherwise `undefined`, in which
71
+ * case you should respond with 406 "Not Acceptable".
72
+ *
73
+ * The `type` value may be a single MIME type string
74
+ * such as "application/json", an extension name
75
+ * such as "json", a comma-delimited list such as "json, html, text/plain",
76
+ * an argument list such as `"json", "html", "text/plain"`,
77
+ * or an array `["json", "html", "text/plain"]`. When a list
78
+ * or array is given, the _best_ match, if any is returned.
79
+ *
80
+ * Examples:
81
+ *
82
+ * // Accept: text/html
83
+ * req.accepts('html');
84
+ * // => "html"
85
+ *
86
+ * // Accept: text/*, application/json
87
+ * req.accepts('html');
88
+ * // => "html"
89
+ * req.accepts('text/html');
90
+ * // => "text/html"
91
+ * req.accepts('json, text');
92
+ * // => "json"
93
+ * req.accepts('application/json');
94
+ * // => "application/json"
95
+ *
96
+ * // Accept: text/*, application/json
97
+ * req.accepts('image/png');
98
+ * req.accepts('png');
99
+ * // => undefined
100
+ *
101
+ * // Accept: text/*;q=.5, application/json
102
+ * req.accepts(['html', 'json']);
103
+ * req.accepts('html', 'json');
104
+ * req.accepts('html, json');
105
+ * // => "json"
106
+ *
107
+ * @param {String|Array} type(s)
108
+ * @return {String|Array|Boolean}
109
+ * @public
110
+ */
111
+ req.accepts = function() {
112
+ const accept = accepts(this);
113
+ return accept.types.apply(accept, arguments);
114
+ };
115
+
116
+
117
+ /**
118
+ * Check if the given `encoding`s are accepted.
119
+ *
120
+ * @param {String} ...encoding
121
+ * @return {String|Array}
122
+ * @public
123
+ */
124
+ req.acceptsEncodings = function() {
125
+ const accept = accepts(this);
126
+ return accept.encodings.apply(accept, arguments);
127
+ };
128
+
129
+
130
+ /**
131
+ * Check if the given `charset`s are acceptable,
132
+ * otherwise you should respond with 406 "Not Acceptable".
133
+ *
134
+ * @param {String} ...charset
135
+ * @return {String|Array}
136
+ * @public
137
+ */
138
+ req.acceptsCharsets = function() {
139
+ const accept = accepts(this);
140
+ return accept.charsets.apply(accept, arguments);
141
+ };
142
+
143
+
144
+ /**
145
+ * Check if the given `lang`s are acceptable,
146
+ * otherwise you should respond with 406 "Not Acceptable".
147
+ *
148
+ * @param {String} ...lang
149
+ * @return {String|Array}
150
+ * @public
151
+ */
152
+ req.acceptsLanguages = function() {
153
+ const accept = accepts(this);
154
+ return accept.languages.apply(accept, arguments);
155
+ };
156
+
157
+
158
+ /**
159
+ * Parse Range header field, capping to the given `size`.
160
+ *
161
+ * Unspecified ranges such as "0-" require knowledge of your resource length. In
162
+ * the case of a byte range this is of course the total number of bytes. If the
163
+ * Range header field is not given `undefined` is returned, `-1` when unsatisfiable,
164
+ * and `-2` when syntactically invalid.
165
+ *
166
+ * When ranges are returned, the array has a "type" property which is the type of
167
+ * range that is required (most commonly, "bytes"). Each array element is an object
168
+ * with a "start" and "end" property for the portion of the range.
169
+ *
170
+ * The "combine" option can be set to `true` and overlapping & adjacent ranges
171
+ * will be combined into a single range.
172
+ *
173
+ * NOTE: remember that ranges are inclusive, so for example "Range: users=0-3"
174
+ * should respond with 4 users when available, not 3.
175
+ *
176
+ * @param {number} size
177
+ * @param {object} [options]
178
+ * @param {boolean} [options.combine=false]
179
+ * @return {number|array}
180
+ * @public
181
+ */
182
+ req.range = function range(size, options) {
183
+ const range = this.get('Range');
184
+ if (!range)
185
+ return;
186
+
187
+ return parseRange(size, range, options);
188
+ };
189
+
190
+
191
+ /**
192
+ * Check if the incoming request contains the "Content-Type"
193
+ * header field, and it contains the given mime `type`.
194
+ *
195
+ * Examples:
196
+ *
197
+ * // With Content-Type: text/html; charset=utf-8
198
+ * req.is('html');
199
+ * req.is('text/html');
200
+ * req.is('text/*');
201
+ * // => true
202
+ *
203
+ * // When Content-Type is application/json
204
+ * req.is('json');
205
+ * req.is('application/json');
206
+ * req.is('application/*');
207
+ * // => true
208
+ *
209
+ * req.is('html');
210
+ * // => false
211
+ *
212
+ * @param {String|Array} types...
213
+ * @return {String|false|null}
214
+ * @public
215
+ */
216
+ req.is = function is(types) {
217
+ let arr = types;
218
+
219
+ // support flattened arguments
220
+ if (!Array.isArray(types)) {
221
+ arr = new Array(arguments.length);
222
+ for (let i = 0; i < arr.length; i++) {
223
+ arr[i] = arguments[i];
224
+ }
225
+ }
226
+
227
+ return typeis(this, arr);
228
+ };
229
+
230
+
231
+ /**
232
+ * Return the protocol string "http" or "https"
233
+ * when requested with TLS. When the "trust proxy"
234
+ * setting trusts the socket address, the
235
+ * "X-Forwarded-Proto" header field will be trusted
236
+ * and used if present.
237
+ *
238
+ * If you're running behind a reverse proxy that
239
+ * supplies https for you this may be enabled.
240
+ *
241
+ * @return {String}
242
+ * @public
243
+ */
244
+
245
+ defineGetter(req, 'protocol', function protocol() {
246
+ const proto = this.connection.encrypted
247
+ ? 'https'
248
+ : 'http';
249
+ const trust = this.app.get('trust proxy fn');
250
+
251
+ if (!trust(this.connection.remoteAddress, 0)) {
252
+ return proto;
253
+ }
254
+
255
+ // Note: X-Forwarded-Proto is normally only ever a
256
+ // single value, but this is to be safe.
257
+ const header = this.get('X-Forwarded-Proto') || proto
258
+ const index = header.indexOf(',')
259
+
260
+ return index !== -1
261
+ ? header.substring(0, index).trim()
262
+ : header.trim()
263
+ });
264
+
265
+
266
+ /**
267
+ * Short-hand for:
268
+ *
269
+ * req.protocol === 'https'
270
+ *
271
+ * @return {Boolean}
272
+ * @public
273
+ */
274
+ defineGetter(req, 'secure', function secure() {
275
+ return this.protocol === 'https';
276
+ });
277
+
278
+
279
+ /**
280
+ * Return the remote address from the trusted proxy.
281
+ *
282
+ * The is the remote address on the socket unless
283
+ * "trust proxy" is set.
284
+ *
285
+ * @return {String}
286
+ * @public
287
+ */
288
+ defineGetter(req, 'ip', function ip() {
289
+ const trust = this.app.get('trust proxy fn');
290
+ return proxyaddr(this, trust);
291
+ });
292
+
293
+
294
+ /**
295
+ * When "trust proxy" is set, trusted proxy addresses + client.
296
+ *
297
+ * For example if the value were "client, proxy1, proxy2"
298
+ * you would receive the array `["client", "proxy1", "proxy2"]`
299
+ * where "proxy2" is the furthest down-stream and "proxy1" and
300
+ * "proxy2" were trusted.
301
+ *
302
+ * @return {Array}
303
+ * @public
304
+ */
305
+ defineGetter(req, 'ips', function ips() {
306
+ const trust = this.app.get('trust proxy fn');
307
+ const addrs = proxyaddr.all(this, trust);
308
+
309
+ // reverse the order (to farthest -> closest)
310
+ // and remove socket address
311
+ addrs.reverse().pop()
312
+
313
+ return addrs
314
+ });
315
+
316
+
317
+ /**
318
+ * Return subdomains as an array.
319
+ *
320
+ * Subdomains are the dot-separated parts of the host before the main domain of
321
+ * the app. By default, the domain of the app is assumed to be the last two
322
+ * parts of the host. This can be changed by setting "subdomain offset".
323
+ *
324
+ * For example, if the domain is "tobi.ferrets.example.com":
325
+ * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
326
+ * If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
327
+ *
328
+ * @return {Array}
329
+ * @public
330
+ */
331
+ defineGetter(req, 'subdomains', function subdomains() {
332
+ const hostname = this.hostname;
333
+
334
+ if (!hostname) return [];
335
+
336
+ const offset = this.app.get('subdomain offset');
337
+ const subdomains = !isIP(hostname)
338
+ ? hostname.split('.').reverse()
339
+ : [hostname];
340
+
341
+ return subdomains.slice(offset);
342
+ });
343
+
344
+
345
+ /**
346
+ * Short-hand for `url.parse(req.url).pathname`.
347
+ *
348
+ * @return {String}
349
+ * @public
350
+ */
351
+ defineGetter(req, 'path', function path() {
352
+ return parse(this).pathname;
353
+ });
354
+
355
+
356
+ /**
357
+ * Parse the "Host" header field to a hostname.
358
+ *
359
+ * When the "trust proxy" setting trusts the socket
360
+ * address, the "X-Forwarded-Host" header field will
361
+ * be trusted.
362
+ *
363
+ * @return {String}
364
+ * @public
365
+ */
366
+ defineGetter(req, 'hostname', function hostname() {
367
+ const trust = this.app.get('trust proxy fn');
368
+ let host = this.get('X-Forwarded-Host');
369
+
370
+ if (!host || !trust(this.connection.remoteAddress, 0)) {
371
+ host = this.get('Host');
372
+ }
373
+ else if (host.indexOf(',') !== -1) {
374
+ // Note: X-Forwarded-Host is normally only ever a
375
+ // single value, but this is to be safe.
376
+ host = host.substring(0, host.indexOf(',')).trimRight()
377
+ }
378
+
379
+ if (!host)
380
+ return;
381
+
382
+ // IPv6 literal support
383
+ const offset = host[0] === '['
384
+ ? host.indexOf(']') + 1
385
+ : 0;
386
+ const index = host.indexOf(':', offset);
387
+
388
+ return index !== -1
389
+ ? host.substring(0, index)
390
+ : host;
391
+ });
392
+
393
+
394
+ /**
395
+ * Check if the request is fresh, aka
396
+ * Last-Modified and/or the ETag
397
+ * still match.
398
+ *
399
+ * @return {Boolean}
400
+ * @public
401
+ */
402
+ defineGetter(req, 'fresh', function() {
403
+ const method = this.method;
404
+ const res = this.res
405
+ const status = res.statusCode
406
+
407
+ // GET or HEAD for weak freshness validation only
408
+ if ('GET' !== method && 'HEAD' !== method)
409
+ return false;
410
+
411
+ // 2xx or 304 as per rfc2616 14.26
412
+ if ((status >= 200 && status < 300) || 304 === status) {
413
+ return fresh(this.headers, {
414
+ 'etag': res.get('ETag'),
415
+ 'last-modified': res.get('Last-Modified')
416
+ })
417
+ }
418
+
419
+ return false;
420
+ });
421
+
422
+
423
+ /**
424
+ * Check if the request is stale, aka
425
+ * "Last-Modified" and / or the "ETag" for the
426
+ * resource has changed.
427
+ *
428
+ * @return {Boolean}
429
+ * @public
430
+ */
431
+ defineGetter(req, 'stale', function stale() {
432
+ return !this.fresh;
433
+ });
434
+
435
+
436
+ /**
437
+ * Check if the request was an _XMLHttpRequest_.
438
+ *
439
+ * @return {Boolean}
440
+ * @public
441
+ */
442
+ defineGetter(req, 'xhr', function xhr() {
443
+ const val = this.get('X-Requested-With') || '';
444
+ return val.toLowerCase() === 'xmlhttprequest';
445
+ });
446
+
447
+
448
+ /**
449
+ * Helper function for creating a getter on an object.
450
+ *
451
+ * @param {Object} obj
452
+ * @param {String} name
453
+ * @param {Function} getter
454
+ * @private
455
+ */
456
+ function defineGetter(obj, name, getter) {
457
+ Object.defineProperty(obj, name, {
458
+ configurable: true,
459
+ enumerable: true,
460
+ get: getter
461
+ });
462
+ }