tspace-spear 1.0.9 → 1.1.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.
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
35
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
27
  };
@@ -62,87 +53,41 @@ const parser_factory_1 = require("./parser-factory");
62
53
  *
63
54
  */
64
55
  class Spear {
65
- constructor({ controllers, middlewares, globalPrefix, logger, cluster } = {}) {
66
- this._router = (0, find_my_way_1.default)();
67
- this._parser = new parser_factory_1.ParserFactory();
68
- this._swagger = {
69
- use: false,
70
- path: '/api/docs',
71
- servers: [
72
- {
73
- url: 'http://localhost:3000'
74
- }
75
- ],
76
- tags: [],
77
- info: {
78
- title: "API Documentation",
79
- description: "This is a sample documentation",
80
- version: "1.0.0"
56
+ _controllers;
57
+ _middlewares;
58
+ _globalPrefix;
59
+ _cluster;
60
+ _router = (0, find_my_way_1.default)();
61
+ _parser = new parser_factory_1.ParserFactory();
62
+ _swagger = {
63
+ use: false,
64
+ path: '/api/docs',
65
+ servers: [
66
+ {
67
+ url: 'http://localhost:3000'
81
68
  }
82
- };
83
- this._swaggerAdditional = [];
84
- this._errorHandler = null;
85
- this._globalMiddlewares = [];
86
- this._formatResponse = null;
87
- this._onListeners = [];
88
- this._fileUploadOptions = {
89
- limit: Infinity,
90
- tempFileDir: 'tmp',
91
- removeTempFile: {
92
- remove: false,
93
- ms: 1000 * 60 * 10
94
- }
95
- };
96
- this._wrapHandlers = (...handlers) => {
97
- return (req, res, params) => {
98
- const runHandler = (index = 0) => {
99
- const response = this._customizeResponse(req, res);
100
- const request = req;
101
- const body = request._bodyParser;
102
- const files = request._filesParser;
103
- const cookies = request._cookiesParser;
104
- const headers = request.headers;
105
- const query = Object.assign({}, (0, url_1.parse)(String(req.url), true).query);
106
- const RecordOrEmptyRecord = (data) => {
107
- if (data == null)
108
- return {};
109
- return Object.keys(data).length ? data : {};
110
- };
111
- const ctx = {
112
- req,
113
- res: response,
114
- headers: RecordOrEmptyRecord(headers),
115
- params: RecordOrEmptyRecord(params),
116
- query: RecordOrEmptyRecord(query),
117
- body: RecordOrEmptyRecord(body),
118
- files: RecordOrEmptyRecord(files),
119
- cookies: RecordOrEmptyRecord(cookies)
120
- };
121
- if (index === handlers.length - 1) {
122
- return this._wrapResponse(handlers[index].bind(handlers[index]))(ctx, this._nextFunction(ctx));
123
- }
124
- return handlers[index](ctx, () => {
125
- return runHandler(index + 1);
126
- });
127
- };
128
- try {
129
- runHandler();
130
- }
131
- catch (err) {
132
- const ctx = {
133
- req,
134
- res: this._customizeResponse(req, res),
135
- params: Object.keys(params).length ? params : {},
136
- headers: {},
137
- query: {},
138
- body: {},
139
- files: {},
140
- cookies: {}
141
- };
142
- return this._nextFunction(ctx)(err);
143
- }
144
- };
145
- };
69
+ ],
70
+ tags: [],
71
+ info: {
72
+ title: "API Documentation",
73
+ description: "This is a sample documentation",
74
+ version: "1.0.0"
75
+ }
76
+ };
77
+ _swaggerAdditional = [];
78
+ _errorHandler = null;
79
+ _globalMiddlewares = [];
80
+ _formatResponse = null;
81
+ _onListeners = [];
82
+ _fileUploadOptions = {
83
+ limit: Infinity,
84
+ tempFileDir: 'tmp',
85
+ removeTempFile: {
86
+ remove: false,
87
+ ms: 1000 * 60 * 10
88
+ }
89
+ };
90
+ constructor({ controllers, middlewares, globalPrefix, logger, cluster } = {}) {
146
91
  if (logger)
147
92
  this.useLogger();
148
93
  this._cluster = cluster;
@@ -150,9 +95,19 @@ class Spear {
150
95
  this._middlewares = middlewares;
151
96
  this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
152
97
  }
98
+ /**
99
+ * The get 'instance' method is used to get the instance of Spear.
100
+ *
101
+ * @returns {this}
102
+ */
153
103
  get instance() {
154
104
  return this;
155
105
  }
106
+ /**
107
+ * The get 'routers' method is used get the all routers.
108
+ *
109
+ * @returns {Instance<findMyWayRouter.HTTPVersion.V1>}
110
+ */
156
111
  get routers() {
157
112
  return this._router;
158
113
  }
@@ -217,38 +172,27 @@ class Spear {
217
172
  return this;
218
173
  }
219
174
  /**
220
- * The 'useFileUpload' method is a middleware used to handler file uploads. It adds a file upload of incoming HTTP requests.
221
- *
222
- * @param {?Object}
223
- * @property {?number} limits
224
- * @property {?string} tempFileDir
225
- * @property {?Object} removeTempFile
226
- * @property {boolean} removeTempFile.remove
227
- * @property {number} removeTempFile.ms
228
- * @returns
229
- */
230
- useFileUpload({ limit, tempFileDir, removeTempFile } = {}) {
231
- if (limit != null) {
232
- this._fileUploadOptions.limit = limit;
233
- }
234
- if (tempFileDir != null) {
235
- this._fileUploadOptions.tempFileDir = tempFileDir;
236
- }
237
- if (removeTempFile != null) {
238
- this._fileUploadOptions.removeTempFile = removeTempFile;
239
- }
175
+ * The 'useBodyParser' method is a middleware used to parse the request body of incoming HTTP requests.
176
+ * @param {object?}
177
+ * @property {array?} except the body parser with some methods
178
+ * @returns {this}
179
+ */
180
+ useBodyParser({ except } = {}) {
240
181
  this._globalMiddlewares.push(({ req }, next) => {
241
- const contentType = req === null || req === void 0 ? void 0 : req.headers['content-type'];
182
+ const contentType = req?.headers['content-type'];
242
183
  const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
243
- const isListMethods = ['POST', 'PATCH', 'PUT', 'DELETE'].includes(String(req.method));
244
- if (!isListMethods || !isFileUpload)
184
+ if (except != null && Array.isArray(except)) {
185
+ if (except.some(v => v.toLocaleLowerCase() === (req.method)?.toLocaleLowerCase())) {
186
+ return next();
187
+ }
188
+ }
189
+ if (isFileUpload)
245
190
  return next();
246
- if ((req === null || req === void 0 ? void 0 : req._filesParser) != null)
191
+ if (req?.body != null)
247
192
  return next();
248
- Promise.resolve(this._parser.files({ req, options: this._fileUploadOptions }))
193
+ Promise.resolve(this._parser.body(req))
249
194
  .then(r => {
250
- req._filesParser = r.files;
251
- req._bodyParser = r.body;
195
+ req.body = r;
252
196
  return next();
253
197
  })
254
198
  .catch(_ => next());
@@ -256,21 +200,40 @@ class Spear {
256
200
  return this;
257
201
  }
258
202
  /**
259
- * The 'useBodyParser' method is a middleware used to parse the request body of incoming HTTP requests.
203
+ * The 'useFileUpload' method is a middleware used to handler file uploads. It adds a file upload of incoming HTTP requests.
260
204
  *
261
- * @returns {this}
205
+ * @param {?Object}
206
+ * @property {?number} limits
207
+ * @property {?string} tempFileDir
208
+ * @property {?Object} removeTempFile
209
+ * @property {boolean} removeTempFile.remove
210
+ * @property {number} removeTempFile.ms
211
+ * @returns
262
212
  */
263
- useBodyParser() {
213
+ useFileUpload({ limit, tempFileDir, removeTempFile } = {}) {
214
+ if (limit != null) {
215
+ this._fileUploadOptions.limit = limit;
216
+ }
217
+ if (tempFileDir != null) {
218
+ this._fileUploadOptions.tempFileDir = tempFileDir;
219
+ }
220
+ if (removeTempFile != null) {
221
+ this._fileUploadOptions.removeTempFile = removeTempFile;
222
+ }
264
223
  this._globalMiddlewares.push(({ req }, next) => {
265
- const contentType = req === null || req === void 0 ? void 0 : req.headers['content-type'];
224
+ const contentType = req?.headers['content-type'];
266
225
  const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
267
- if (isFileUpload)
226
+ if (req.method === 'GET') {
268
227
  return next();
269
- if ((req === null || req === void 0 ? void 0 : req._bodyParser) != null)
228
+ }
229
+ if (!isFileUpload)
270
230
  return next();
271
- Promise.resolve(this._parser.body(req))
231
+ if (req?.files != null)
232
+ return next();
233
+ Promise.resolve(this._parser.files({ req, options: this._fileUploadOptions }))
272
234
  .then(r => {
273
- req._bodyParser = r;
235
+ req.files = r.files;
236
+ req.body = r.body;
274
237
  return next();
275
238
  })
276
239
  .catch(_ => next());
@@ -284,9 +247,9 @@ class Spear {
284
247
  */
285
248
  useCookiesParser() {
286
249
  this._globalMiddlewares.push(({ req }, next) => {
287
- if ((req === null || req === void 0 ? void 0 : req._cookiesParser) != null)
250
+ if (req?.cookies != null)
288
251
  return next();
289
- req._cookiesParser = this._parser.cookies(req);
252
+ req.cookies = this._parser.cookies(req);
290
253
  return next();
291
254
  });
292
255
  return this;
@@ -318,10 +281,10 @@ class Spear {
318
281
  useSwagger({ path, servers, info, tags } = {}) {
319
282
  this._swagger = {
320
283
  use: true,
321
- path: path !== null && path !== void 0 ? path : this._swagger.path,
322
- servers: servers !== null && servers !== void 0 ? servers : this._swagger.servers,
323
- tags: tags !== null && tags !== void 0 ? tags : this._swagger.tags,
324
- info: info !== null && info !== void 0 ? info : this._swagger.info
284
+ path: path ?? this._swagger.path,
285
+ servers: servers ?? this._swagger.servers,
286
+ tags: tags ?? this._swagger.tags,
287
+ info: info ?? this._swagger.info
325
288
  };
326
289
  return this;
327
290
  }
@@ -332,35 +295,32 @@ class Spear {
332
295
  * @param {function} callback
333
296
  * @returns
334
297
  */
335
- listen() {
336
- var arguments_1 = arguments;
337
- return __awaiter(this, arguments, void 0, function* (port = 3000, callback) {
338
- if (arguments_1.length === 1 && typeof port === 'function') {
339
- callback = port;
340
- port = 3000;
341
- }
342
- const server = yield this._createServer();
343
- if (this._cluster != null &&
344
- this._cluster || typeof this._cluster === 'number') {
345
- this._clusterMode(server, Number(port), callback);
346
- return;
347
- }
348
- server.listen(port == null ? 3000 : port, () => {
349
- if (callback)
350
- callback({ server, port });
351
- });
352
- server.on('listening', () => {
353
- this._onListeners.forEach(listener => listener());
354
- if (this._swagger.use) {
355
- this._swaggerHandler();
356
- }
357
- });
358
- server.on('error', (_) => {
359
- port = Math.floor(Math.random() * 8999) + 1000;
360
- server.listen(port);
361
- });
298
+ async listen(port = 3000, callback) {
299
+ if (arguments.length === 1 && typeof port === 'function') {
300
+ callback = port;
301
+ port = 3000;
302
+ }
303
+ const server = await this._createServer();
304
+ if (this._cluster != null &&
305
+ this._cluster || typeof this._cluster === 'number') {
306
+ this._clusterMode(server, Number(port), callback);
362
307
  return;
308
+ }
309
+ server.listen(port == null ? 3000 : port, () => {
310
+ if (callback)
311
+ callback({ server, port });
312
+ });
313
+ server.on('listening', () => {
314
+ this._onListeners.forEach(listener => listener());
315
+ if (this._swagger.use) {
316
+ this._swaggerHandler();
317
+ }
363
318
  });
319
+ server.on('error', (_) => {
320
+ port = Math.floor(Math.random() * 8999) + 1000;
321
+ server.listen(port);
322
+ });
323
+ return;
364
324
  }
365
325
  /**
366
326
  * The 'enableCors' is used to enable the cors origins on the server.
@@ -372,8 +332,7 @@ class Spear {
372
332
  */
373
333
  enableCors({ origins, credentials } = {}) {
374
334
  this._globalMiddlewares.push(({ req, res }, next) => {
375
- var _a;
376
- const origin = (_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin;
335
+ const origin = req.headers?.origin;
377
336
  if (origin == null)
378
337
  return next();
379
338
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
@@ -421,9 +380,9 @@ class Spear {
421
380
  * @param {function} notfound
422
381
  * @returns
423
382
  */
424
- notFoundHandler(notfound) {
383
+ notFoundHandler(fn) {
425
384
  const handler = ({ req, res }) => {
426
- return notfound({
385
+ return fn({
427
386
  req,
428
387
  res: this._customizeResponse(req, res),
429
388
  headers: {},
@@ -435,14 +394,10 @@ class Spear {
435
394
  });
436
395
  };
437
396
  this._onListeners.push(() => {
438
- return this._router.all('*', this._wrapHandlers(...this._globalMiddlewares, handler));
397
+ return this.all('*', ...this._globalMiddlewares, handler);
439
398
  });
440
399
  return this;
441
400
  }
442
- low(path, ...handlers) {
443
- this._router.get(this._normalizePath(this._globalPrefix, path), (req, res) => res.end('hello world!'));
444
- return this;
445
- }
446
401
  /**
447
402
  * The 'get' method is used to add the request handler to the router for the 'GET' method.
448
403
  *
@@ -565,57 +520,33 @@ class Spear {
565
520
  }
566
521
  return;
567
522
  }
568
- _import(dir, pattern) {
569
- return __awaiter(this, void 0, void 0, function* () {
570
- const directories = fs_1.default.readdirSync(dir, { withFileTypes: true });
571
- const files = (yield Promise.all(directories.map((directory) => {
572
- const newDir = path_1.default.resolve(String(dir), directory.name);
573
- if (pattern == null) {
574
- return directory.isDirectory() ? this._import(newDir) : newDir;
575
- }
576
- return directory.isDirectory()
577
- ? this._import(newDir)
578
- : pattern.test(directory.name)
579
- ? newDir
580
- : null;
581
- }))).filter(d => d != null);
582
- return [].concat(...files);
583
- });
584
- }
585
- _registerControllers() {
586
- return __awaiter(this, void 0, void 0, function* () {
587
- var _a, _b, _c, _d, _e, _f;
588
- if (this._controllers == null)
589
- return;
590
- if (!Array.isArray(this._controllers)) {
591
- const controllers = yield this._import(this._controllers.folder, this._controllers.name);
592
- for (const file of controllers) {
593
- const response = yield Promise.resolve(`${file}`).then(s => __importStar(require(s)));
594
- const controller = response === null || response === void 0 ? void 0 : response.default;
595
- const controllerInstance = new controller();
596
- const prefixPath = (_a = Reflect.getMetadata("controllers", controller)) !== null && _a !== void 0 ? _a : '';
597
- const routers = (_b = Reflect.getMetadata("routers", controller)) !== null && _b !== void 0 ? _b : [];
598
- const swaggers = (_c = Reflect.getMetadata("swaggers", controller)) !== null && _c !== void 0 ? _c : [];
599
- if (prefixPath == null)
600
- continue;
601
- for (const { method, path, handler } of Array.from(routers)) {
602
- const find = Array.from(swaggers).find(s => s.handler === handler);
603
- if (find != null) {
604
- this._swaggerAdditional = [
605
- ...this._swaggerAdditional,
606
- Object.assign(Object.assign({}, find), { path: this._normalizePath(this._globalPrefix, prefixPath, path), method })
607
- ];
608
- }
609
- this[method](this._normalizePath(this._globalPrefix, prefixPath, path), this._wrapResponse(controllerInstance[String(handler)].bind(controllerInstance)));
610
- }
611
- }
612
- return;
523
+ async _import(dir, pattern) {
524
+ const directories = fs_1.default.readdirSync(dir, { withFileTypes: true });
525
+ const files = (await Promise.all(directories.map((directory) => {
526
+ const newDir = path_1.default.resolve(String(dir), directory.name);
527
+ if (pattern == null) {
528
+ return directory.isDirectory() ? this._import(newDir) : newDir;
613
529
  }
614
- for (const controller of this._controllers) {
530
+ return directory.isDirectory()
531
+ ? this._import(newDir)
532
+ : pattern.test(directory.name)
533
+ ? newDir
534
+ : null;
535
+ }))).filter(d => d != null);
536
+ return [].concat(...files);
537
+ }
538
+ async _registerControllers() {
539
+ if (this._controllers == null)
540
+ return;
541
+ if (!Array.isArray(this._controllers)) {
542
+ const controllers = await this._import(this._controllers.folder, this._controllers.name);
543
+ for (const file of controllers) {
544
+ const response = await Promise.resolve(`${file}`).then(s => __importStar(require(s)));
545
+ const controller = response?.default;
615
546
  const controllerInstance = new controller();
616
- const prefixPath = (_d = Reflect.getMetadata("controllers", controller)) !== null && _d !== void 0 ? _d : '';
617
- const routers = (_e = Reflect.getMetadata("routers", controller)) !== null && _e !== void 0 ? _e : [];
618
- const swaggers = (_f = Reflect.getMetadata("swaggers", controller)) !== null && _f !== void 0 ? _f : [];
547
+ const prefixPath = Reflect.getMetadata("controllers", controller) ?? '';
548
+ const routers = Reflect.getMetadata("routers", controller) ?? [];
549
+ const swaggers = Reflect.getMetadata("swaggers", controller) ?? [];
619
550
  if (prefixPath == null)
620
551
  continue;
621
552
  for (const { method, path, handler } of Array.from(routers)) {
@@ -623,33 +554,58 @@ class Spear {
623
554
  if (find != null) {
624
555
  this._swaggerAdditional = [
625
556
  ...this._swaggerAdditional,
626
- Object.assign(Object.assign({}, find), { path: this._normalizePath(this._globalPrefix, prefixPath, path), method })
557
+ {
558
+ ...find,
559
+ path: this._normalizePath(this._globalPrefix, prefixPath, path),
560
+ method
561
+ }
627
562
  ];
628
563
  }
629
- this[method](this._normalizePath(this._globalPrefix, prefixPath, path), this._wrapResponse(controllerInstance[String(handler)].bind(controllerInstance)));
564
+ this[method](this._normalizePath(this._globalPrefix, prefixPath, path), controllerInstance[String(handler)].bind(controllerInstance));
630
565
  }
631
566
  }
632
- });
633
- }
634
- _registerMiddlewares() {
635
- return __awaiter(this, void 0, void 0, function* () {
636
- if (this._middlewares == null)
637
- return;
638
- if (!Array.isArray(this._middlewares)) {
639
- const middlewares = yield this._import(this._middlewares.folder, this._middlewares.name);
640
- for (const file of middlewares) {
641
- const response = yield Promise.resolve(`${file}`).then(s => __importStar(require(s)));
642
- const middleware = response === null || response === void 0 ? void 0 : response.default;
643
- this.use(middleware);
567
+ return;
568
+ }
569
+ for (const controller of this._controllers) {
570
+ const controllerInstance = new controller();
571
+ const prefixPath = Reflect.getMetadata("controllers", controller) ?? '';
572
+ const routers = Reflect.getMetadata("routers", controller) ?? [];
573
+ const swaggers = Reflect.getMetadata("swaggers", controller) ?? [];
574
+ if (prefixPath == null)
575
+ continue;
576
+ for (const { method, path, handler } of Array.from(routers)) {
577
+ const find = Array.from(swaggers).find(s => s.handler === handler);
578
+ if (find != null) {
579
+ this._swaggerAdditional = [
580
+ ...this._swaggerAdditional,
581
+ {
582
+ ...find,
583
+ path: this._normalizePath(this._globalPrefix, prefixPath, path),
584
+ method
585
+ }
586
+ ];
644
587
  }
645
- return;
588
+ this[method](this._normalizePath(this._globalPrefix, prefixPath, path), controllerInstance[String(handler)].bind(controllerInstance));
646
589
  }
647
- const middlewares = this._middlewares;
648
- for (const middleware of middlewares) {
590
+ }
591
+ }
592
+ async _registerMiddlewares() {
593
+ if (this._middlewares == null)
594
+ return;
595
+ if (!Array.isArray(this._middlewares)) {
596
+ const middlewares = await this._import(this._middlewares.folder, this._middlewares.name);
597
+ for (const file of middlewares) {
598
+ const response = await Promise.resolve(`${file}`).then(s => __importStar(require(s)));
599
+ const middleware = response?.default;
649
600
  this.use(middleware);
650
601
  }
651
602
  return;
652
- });
603
+ }
604
+ const middlewares = this._middlewares;
605
+ for (const middleware of middlewares) {
606
+ this.use(middleware);
607
+ }
608
+ return;
653
609
  }
654
610
  _customizeResponse(req, res) {
655
611
  const response = res;
@@ -670,9 +626,13 @@ class Spear {
670
626
  return res.end();
671
627
  }
672
628
  if (this._formatResponse != null) {
673
- return res.end(JSON.stringify(this._formatResponse(Object.assign({}, results), res.statusCode), null, 2));
629
+ return res.end(JSON.stringify(this._formatResponse({
630
+ ...results
631
+ }, res.statusCode), null, 2));
674
632
  }
675
- return res.end(JSON.stringify(Object.assign({}, results), null, 2));
633
+ return res.end(JSON.stringify({
634
+ ...results,
635
+ }, null, 2));
676
636
  };
677
637
  response.send = (results) => {
678
638
  res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
@@ -683,16 +643,15 @@ class Spear {
683
643
  return res.end(results);
684
644
  };
685
645
  response.error = (err) => {
686
- var _a, _b, _c, _d, _e, _f, _g, _h;
687
- let code = +((_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code) ||
646
+ let code = +err.response?.data?.code ||
688
647
  +err.code ||
689
648
  +err.status ||
690
649
  +err.statusCode ||
691
- +((_d = (_c = err.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.statusCode) ||
650
+ +err.response?.data?.statusCode ||
692
651
  500;
693
652
  code = (code == null || typeof code !== 'number') ? 500 : Number.isNaN(code) ? 500 : code < 400 ? 500 : code;
694
- const message = ((_f = (_e = err.response) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.errorMessage) ||
695
- ((_h = (_g = err.response) === null || _g === void 0 ? void 0 : _g.data) === null || _h === void 0 ? void 0 : _h.message) ||
653
+ const message = err.response?.data?.errorMessage ||
654
+ err.response?.data?.message ||
696
655
  err.message ||
697
656
  `The url '${req.url}' resulted in a server error. Please investigate.`;
698
657
  response.status(code);
@@ -720,7 +679,7 @@ class Spear {
720
679
  };
721
680
  response.badRequest = (message) => {
722
681
  response.status(400);
723
- message = message !== null && message !== void 0 ? message : `The url '${req.url}' resulted in a bad request. Please review the data and try again.`;
682
+ message = message ?? `The url '${req.url}' resulted in a bad request. Please review the data and try again.`;
724
683
  if (this._formatResponse != null) {
725
684
  return res.end(JSON.stringify(this._formatResponse({ message }, 400), null, 2));
726
685
  }
@@ -730,7 +689,7 @@ class Spear {
730
689
  };
731
690
  response.unauthorized = (message) => {
732
691
  response.status(401);
733
- message = message !== null && message !== void 0 ? message : `The url '${req.url}' is unauthorized. Please verify.`;
692
+ message = message ?? `The url '${req.url}' is unauthorized. Please verify.`;
734
693
  if (this._formatResponse != null) {
735
694
  return res.end(JSON.stringify(this._formatResponse({ message }, 401), null, 2));
736
695
  }
@@ -740,7 +699,7 @@ class Spear {
740
699
  };
741
700
  response.paymentRequired = (message) => {
742
701
  response.status(402);
743
- message = message !== null && message !== void 0 ? message : `The url '${req.url}' requires payment. Please proceed with payment.`;
702
+ message = message ?? `The url '${req.url}' requires payment. Please proceed with payment.`;
744
703
  if (this._formatResponse != null) {
745
704
  return res.end(JSON.stringify(this._formatResponse({ message }, 402), null, 2));
746
705
  }
@@ -750,7 +709,7 @@ class Spear {
750
709
  };
751
710
  response.forbidden = (message) => {
752
711
  response.status(403);
753
- message = message !== null && message !== void 0 ? message : `The url '${req.url}' is forbidden. Please check the permissions or access rights.`;
712
+ message = message ?? `The url '${req.url}' is forbidden. Please check the permissions or access rights.`;
754
713
  if (this._formatResponse != null) {
755
714
  return res.end(JSON.stringify(this._formatResponse({ message }, 403), null, 2));
756
715
  }
@@ -760,7 +719,7 @@ class Spear {
760
719
  };
761
720
  response.notFound = (message) => {
762
721
  response.status(404);
763
- message = message !== null && message !== void 0 ? message : `The url '${req.url}' was not found. Please re-check the your url again`;
722
+ message = message ?? `The url '${req.url}' was not found. Please re-check the your url again`;
764
723
  if (this._formatResponse != null) {
765
724
  return res.end(JSON.stringify(this._formatResponse({ message }, 404), null, 2));
766
725
  }
@@ -770,7 +729,7 @@ class Spear {
770
729
  };
771
730
  response.serverError = (message) => {
772
731
  response.status(500);
773
- message = message !== null && message !== void 0 ? message : `The url '${req.url}' resulted in a server error. Please investigate.`;
732
+ message = message ?? `The url '${req.url}' resulted in a server error. Please investigate.`;
774
733
  if (this._formatResponse != null) {
775
734
  return res.end(JSON.stringify(this._formatResponse({ message }, 500), null, 2));
776
735
  }
@@ -821,11 +780,11 @@ class Spear {
821
780
  ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
822
781
  if (this._formatResponse != null) {
823
782
  return ctx.res.end(JSON.stringify(this._formatResponse({
824
- message: err === null || err === void 0 ? void 0 : err.message,
783
+ message: err?.message,
825
784
  }, ctx.res.statusCode), null, 2));
826
785
  }
827
786
  return ctx.res.end(JSON.stringify({
828
- message: err === null || err === void 0 ? void 0 : err.message,
787
+ message: err?.message,
829
788
  }, null, 2));
830
789
  }
831
790
  if (this._errorHandler != null) {
@@ -842,6 +801,56 @@ class Spear {
842
801
  }, null, 2));
843
802
  };
844
803
  }
804
+ _wrapHandlers = (...handlers) => {
805
+ return (req, res, params) => {
806
+ const runHandler = (index = 0) => {
807
+ const response = this._customizeResponse(req, res);
808
+ const request = req;
809
+ const body = request.body;
810
+ const files = request.files;
811
+ const cookies = request.cookies;
812
+ const headers = request.headers;
813
+ const query = { ...(0, url_1.parse)(String(req.url), true).query };
814
+ const RecordOrEmptyRecord = (data) => {
815
+ if (data == null)
816
+ return {};
817
+ return Object.keys(data).length ? data : {};
818
+ };
819
+ const ctx = {
820
+ req,
821
+ res: response,
822
+ headers: RecordOrEmptyRecord(headers),
823
+ params: RecordOrEmptyRecord(params),
824
+ query: RecordOrEmptyRecord(query),
825
+ body: RecordOrEmptyRecord(body),
826
+ files: RecordOrEmptyRecord(files),
827
+ cookies: RecordOrEmptyRecord(cookies)
828
+ };
829
+ if (index === handlers.length - 1) {
830
+ return this._wrapResponse(handlers[index].bind(handlers[index]))(ctx, this._nextFunction(ctx));
831
+ }
832
+ return handlers[index](ctx, () => {
833
+ return runHandler(index + 1);
834
+ });
835
+ };
836
+ try {
837
+ runHandler();
838
+ }
839
+ catch (err) {
840
+ const ctx = {
841
+ req,
842
+ res: this._customizeResponse(req, res),
843
+ params: Object.keys(params).length ? params : {},
844
+ headers: {},
845
+ query: {},
846
+ body: {},
847
+ files: {},
848
+ cookies: {}
849
+ };
850
+ return this._nextFunction(ctx)(err);
851
+ }
852
+ };
853
+ };
845
854
  _wrapResponse(handler) {
846
855
  return (ctx, next) => {
847
856
  Promise.resolve(handler(ctx, next))
@@ -875,7 +884,8 @@ class Spear {
875
884
  if (!ctx.res.headersSent) {
876
885
  ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
877
886
  }
878
- ctx.res.end(JSON.stringify(result, null, 2));
887
+ ctx.res.end(result == null ? undefined : JSON.stringify(result, null, 2));
888
+ return;
879
889
  })
880
890
  .catch(_ => {
881
891
  if (ctx.res.writableEnded)
@@ -884,22 +894,21 @@ class Spear {
884
894
  ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
885
895
  }
886
896
  ctx.res.end(JSON.stringify({ error: 'Internal Server Error' }));
897
+ return;
887
898
  });
888
899
  };
889
900
  }
890
- _createServer() {
891
- return __awaiter(this, void 0, void 0, function* () {
892
- yield this._registerMiddlewares();
893
- yield this._registerControllers();
894
- const server = http_1.default.createServer((req, res) => {
895
- return this._router.lookup(req, res);
896
- });
897
- server.timeout = 0;
898
- server.keepAliveTimeout = 0;
899
- server.headersTimeout = 0;
900
- server.requestTimeout = 0;
901
- return server;
901
+ async _createServer() {
902
+ await this._registerMiddlewares();
903
+ await this._registerControllers();
904
+ const server = http_1.default.createServer((req, res) => {
905
+ return this._router.lookup(req, res);
902
906
  });
907
+ server.timeout = 0;
908
+ server.keepAliveTimeout = 0;
909
+ server.headersTimeout = 0;
910
+ server.requestTimeout = 0;
911
+ return server;
903
912
  }
904
913
  _normalizePath(...paths) {
905
914
  const path = paths
@@ -912,7 +921,11 @@ class Spear {
912
921
  _swaggerHandler() {
913
922
  const routes = this.routers
914
923
  .routes.filter(r => ["GET", "POST", "PUT", "PATCH", "DELETE"].includes(r.method));
915
- const { path, html, staticSwaggerHandler, staticUrl } = this._parser.swagger(Object.assign(Object.assign({}, this._swagger), { options: this._swaggerAdditional, routes }));
924
+ const { path, html, staticSwaggerHandler, staticUrl } = this._parser.swagger({
925
+ ...this._swagger,
926
+ options: this._swaggerAdditional,
927
+ routes
928
+ });
916
929
  this._router.get(staticUrl, staticSwaggerHandler);
917
930
  this._router.get(String(path), (req, res) => {
918
931
  res.writeHead(200, { 'Content-Type': 'text/html' });