tspace-spear 1.2.1-beta.1 → 1.2.2
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/README.md +41 -11
- package/dist/lib/core/decorators/context.d.ts +91 -0
- package/dist/lib/core/decorators/context.js +86 -0
- package/dist/lib/core/decorators/context.js.map +1 -1
- package/dist/lib/core/decorators/controller.d.ts +34 -0
- package/dist/lib/core/decorators/controller.js +33 -0
- package/dist/lib/core/decorators/controller.js.map +1 -1
- package/dist/lib/core/decorators/headers.d.ts +31 -0
- package/dist/lib/core/decorators/headers.js +29 -0
- package/dist/lib/core/decorators/headers.js.map +1 -1
- package/dist/lib/core/decorators/index.d.ts +9 -0
- package/dist/lib/core/decorators/methods.d.ts +82 -0
- package/dist/lib/core/decorators/methods.js +78 -1
- package/dist/lib/core/decorators/methods.js.map +1 -1
- package/dist/lib/core/decorators/middleware.d.ts +39 -0
- package/dist/lib/core/decorators/middleware.js +37 -0
- package/dist/lib/core/decorators/middleware.js.map +1 -1
- package/dist/lib/core/decorators/statusCode.d.ts +26 -0
- package/dist/lib/core/decorators/statusCode.js +24 -0
- package/dist/lib/core/decorators/statusCode.js.map +1 -1
- package/dist/lib/core/decorators/swagger.d.ts +36 -0
- package/dist/lib/core/decorators/swagger.js +35 -1
- package/dist/lib/core/decorators/swagger.js.map +1 -1
- package/dist/lib/core/server/index.d.ts +292 -0
- package/dist/lib/core/server/index.js +363 -359
- package/dist/lib/core/server/index.js.map +1 -1
- package/dist/lib/core/server/parser-factory.d.ts +23 -0
- package/dist/lib/core/server/parser-factory.js.map +1 -1
- package/dist/lib/core/server/router.d.ts +99 -0
- package/dist/lib/core/server/router.js +34 -0
- package/dist/lib/core/server/router.js.map +1 -1
- package/dist/lib/core/types/index.d.ts +228 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/tests/benchmark.test.d.ts +1 -0
- package/dist/tests/benchmark.test.js +2 -11
- package/dist/tests/benchmark.test.js.map +1 -1
- package/package.json +12 -10
- package/dist/lib/core/server/radix-router.js +0 -65
- package/dist/lib/core/server/radix-router.js.map +0 -1
|
@@ -15,18 +15,30 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
37
|
};
|
|
28
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
39
|
exports.Spear = exports.Application = void 0;
|
|
40
|
+
const http_1 = __importStar(require("http"));
|
|
41
|
+
const find_my_way_1 = __importDefault(require("find-my-way"));
|
|
30
42
|
const cluster_1 = __importDefault(require("cluster"));
|
|
31
43
|
const os_1 = __importDefault(require("os"));
|
|
32
44
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -34,8 +46,6 @@ const path_1 = __importDefault(require("path"));
|
|
|
34
46
|
const url_1 = require("url");
|
|
35
47
|
const on_finished_1 = __importDefault(require("on-finished"));
|
|
36
48
|
const ws_1 = __importDefault(require("ws"));
|
|
37
|
-
const http_1 = __importStar(require("http"));
|
|
38
|
-
const find_my_way_1 = __importDefault(require("find-my-way"));
|
|
39
49
|
const parser_factory_1 = require("./parser-factory");
|
|
40
50
|
/**
|
|
41
51
|
*
|
|
@@ -76,10 +86,10 @@ class Spear {
|
|
|
76
86
|
version: "1.0.0"
|
|
77
87
|
}
|
|
78
88
|
};
|
|
89
|
+
_swaggerSpecs = [];
|
|
79
90
|
_wss;
|
|
80
91
|
_ws;
|
|
81
92
|
_wsOptions;
|
|
82
|
-
_swaggerAdditional = [];
|
|
83
93
|
_errorHandler = null;
|
|
84
94
|
_globalMiddlewares = [];
|
|
85
95
|
_formatResponse = null;
|
|
@@ -97,7 +107,6 @@ class Spear {
|
|
|
97
107
|
this.useLogger();
|
|
98
108
|
if (cluster)
|
|
99
109
|
this.useCluster(cluster);
|
|
100
|
-
this._cluster = cluster;
|
|
101
110
|
this._controllers = controllers;
|
|
102
111
|
this._middlewares = middlewares;
|
|
103
112
|
this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
|
|
@@ -260,11 +269,11 @@ class Spear {
|
|
|
260
269
|
}
|
|
261
270
|
this._globalMiddlewares.push((ctx, next) => {
|
|
262
271
|
const { req } = ctx;
|
|
263
|
-
const contentType = req?.headers['content-type'];
|
|
264
|
-
const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
|
|
265
272
|
if (req.method === 'GET') {
|
|
266
273
|
return next();
|
|
267
274
|
}
|
|
275
|
+
const contentType = req?.headers['content-type'];
|
|
276
|
+
const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
|
|
268
277
|
if (!isFileUpload)
|
|
269
278
|
return next();
|
|
270
279
|
if (req?.files != null)
|
|
@@ -379,7 +388,7 @@ class Spear {
|
|
|
379
388
|
const origin = req.headers?.origin ?? null;
|
|
380
389
|
if (origin == null)
|
|
381
390
|
return;
|
|
382
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
|
|
391
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS');
|
|
383
392
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
384
393
|
if (Array.isArray(origins) && origins.length) {
|
|
385
394
|
for (const o of origins) {
|
|
@@ -404,27 +413,6 @@ class Spear {
|
|
|
404
413
|
});
|
|
405
414
|
return this;
|
|
406
415
|
}
|
|
407
|
-
/**
|
|
408
|
-
* The 'enableCors' is used to enable the cors origins on the server.
|
|
409
|
-
*
|
|
410
|
-
* @params {Object}
|
|
411
|
-
* @property {(string | RegExp)[]} origins
|
|
412
|
-
* @property {boolean} credentials
|
|
413
|
-
* @returns
|
|
414
|
-
*/
|
|
415
|
-
enableCors({ origins, credentials } = {}) {
|
|
416
|
-
return this.cors({ origins, credentials });
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* The 'formaT.Response' method is used to format the response
|
|
420
|
-
*
|
|
421
|
-
* @param {function} format
|
|
422
|
-
* @returns
|
|
423
|
-
*/
|
|
424
|
-
formatResponse(format) {
|
|
425
|
-
this._formatResponse = format;
|
|
426
|
-
return this;
|
|
427
|
-
}
|
|
428
416
|
/**
|
|
429
417
|
* The 'response' method is used to format the response
|
|
430
418
|
*
|
|
@@ -435,18 +423,6 @@ class Spear {
|
|
|
435
423
|
this._formatResponse = format;
|
|
436
424
|
return this;
|
|
437
425
|
}
|
|
438
|
-
/**
|
|
439
|
-
* The 'errorHandler' method is middleware that is specifically designed to handle errors.
|
|
440
|
-
*
|
|
441
|
-
* that occur during the processing of requests
|
|
442
|
-
*
|
|
443
|
-
* @param {function} error
|
|
444
|
-
* @returns
|
|
445
|
-
*/
|
|
446
|
-
errorHandler(error) {
|
|
447
|
-
this._errorHandler = error;
|
|
448
|
-
return this;
|
|
449
|
-
}
|
|
450
426
|
/**
|
|
451
427
|
* The 'catch' method is middleware that is specifically designed to handle errors.
|
|
452
428
|
*
|
|
@@ -459,34 +435,10 @@ class Spear {
|
|
|
459
435
|
this._errorHandler = error;
|
|
460
436
|
return this;
|
|
461
437
|
}
|
|
462
|
-
/**
|
|
463
|
-
* The 'notFoundHandler' method is middleware that is specifically designed to handle errors notfound that occur during the processing of requests
|
|
464
|
-
*
|
|
465
|
-
* @param {function} notfound
|
|
466
|
-
* @returns
|
|
467
|
-
*/
|
|
468
|
-
notFoundHandler(fn) {
|
|
469
|
-
const handler = ({ req, res }) => {
|
|
470
|
-
return fn({
|
|
471
|
-
req,
|
|
472
|
-
res: this._customizeResponse(req, res),
|
|
473
|
-
headers: {},
|
|
474
|
-
query: {},
|
|
475
|
-
files: {},
|
|
476
|
-
body: {},
|
|
477
|
-
params: {},
|
|
478
|
-
cookies: {}
|
|
479
|
-
});
|
|
480
|
-
};
|
|
481
|
-
this._onListeners.push(() => {
|
|
482
|
-
return this.all('*', ...this._globalMiddlewares, handler);
|
|
483
|
-
});
|
|
484
|
-
return this;
|
|
485
|
-
}
|
|
486
438
|
/**
|
|
487
439
|
* The 'notfound' method is middleware that is specifically designed to handle errors notfound that occur during the processing of requests
|
|
488
440
|
*
|
|
489
|
-
* @param {function}
|
|
441
|
+
* @param {function} fn
|
|
490
442
|
* @returns
|
|
491
443
|
*/
|
|
492
444
|
notfound(fn) {
|
|
@@ -583,7 +535,7 @@ class Spear {
|
|
|
583
535
|
return this;
|
|
584
536
|
}
|
|
585
537
|
/**
|
|
586
|
-
* The '
|
|
538
|
+
* The 'head' method is used to add the request handler to the router for 'HEAD' methods.
|
|
587
539
|
*
|
|
588
540
|
* @param {string} path
|
|
589
541
|
* @callback {...Function[]} handlers of the middlewares
|
|
@@ -591,14 +543,29 @@ class Spear {
|
|
|
591
543
|
* @property {function} next - go to next function
|
|
592
544
|
* @returns {this}
|
|
593
545
|
*/
|
|
594
|
-
|
|
546
|
+
head(path, ...handlers) {
|
|
595
547
|
this._onListeners.push(() => {
|
|
596
|
-
return this._router.
|
|
548
|
+
return this._router.head(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
597
549
|
});
|
|
598
550
|
return this;
|
|
599
551
|
}
|
|
600
552
|
/**
|
|
601
|
-
* The '
|
|
553
|
+
* The 'head' method is used to add the request handler to the router for 'HEAD' methods.
|
|
554
|
+
*
|
|
555
|
+
* @param {string} path
|
|
556
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
557
|
+
* @property {object} ctx - context { req , res , query , params , cookies , files , body}
|
|
558
|
+
* @property {function} next - go to next function
|
|
559
|
+
* @returns {this}
|
|
560
|
+
*/
|
|
561
|
+
options(path, ...handlers) {
|
|
562
|
+
this._onListeners.push(() => {
|
|
563
|
+
return this._router.options(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
564
|
+
});
|
|
565
|
+
return this;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* The 'any' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' 'OPTIONS' methods.
|
|
602
569
|
*
|
|
603
570
|
* @param {string} path
|
|
604
571
|
* @callback {...Function[]} handlers of the middlewares
|
|
@@ -612,6 +579,21 @@ class Spear {
|
|
|
612
579
|
});
|
|
613
580
|
return this;
|
|
614
581
|
}
|
|
582
|
+
/**
|
|
583
|
+
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' 'HEAD' 'OPTIONS' methods.
|
|
584
|
+
*
|
|
585
|
+
* @param {string} path
|
|
586
|
+
* @callback {...Function[]} handlers of the middlewares
|
|
587
|
+
* @property {object} ctx - context { req , res , query , params , cookies , files , body}
|
|
588
|
+
* @property {function} next - go to next function
|
|
589
|
+
* @returns {this}
|
|
590
|
+
*/
|
|
591
|
+
all(path, ...handlers) {
|
|
592
|
+
this._onListeners.push(() => {
|
|
593
|
+
return this._router.all(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
594
|
+
});
|
|
595
|
+
return this;
|
|
596
|
+
}
|
|
615
597
|
_clusterMode({ server, port, hostname, callback }) {
|
|
616
598
|
if (cluster_1.default.isPrimary) {
|
|
617
599
|
const numCPUs = os_1.default.cpus().length;
|
|
@@ -688,8 +670,8 @@ class Spear {
|
|
|
688
670
|
for (const { method, path, handler } of Array.from(routers)) {
|
|
689
671
|
const find = Array.from(swaggers).find(s => s.handler === handler);
|
|
690
672
|
if (find != null) {
|
|
691
|
-
this.
|
|
692
|
-
...this.
|
|
673
|
+
this._swaggerSpecs = [
|
|
674
|
+
...this._swaggerSpecs,
|
|
693
675
|
{
|
|
694
676
|
...find,
|
|
695
677
|
path: this._normalizePath(this._globalPrefix, prefixPath, path),
|
|
@@ -712,8 +694,8 @@ class Spear {
|
|
|
712
694
|
for (const { method, path, handler } of Array.from(routers)) {
|
|
713
695
|
const find = Array.from(swaggers).find(s => s.handler === handler);
|
|
714
696
|
if (find != null) {
|
|
715
|
-
this.
|
|
716
|
-
...this.
|
|
697
|
+
this._swaggerSpecs = [
|
|
698
|
+
...this._swaggerSpecs,
|
|
717
699
|
{
|
|
718
700
|
...find,
|
|
719
701
|
path: this._normalizePath(this._globalPrefix, prefixPath, path),
|
|
@@ -743,7 +725,7 @@ class Spear {
|
|
|
743
725
|
}
|
|
744
726
|
const middleware = maybeMiddleware;
|
|
745
727
|
if (typeof middleware !== "function") {
|
|
746
|
-
console.log(`\x1b[31m[
|
|
728
|
+
console.log(`\x1b[31m[MiddlewareLoader ERROR]\x1b[0m \x1b[36m${file}\x1b[0m must export a middleware`);
|
|
747
729
|
continue;
|
|
748
730
|
}
|
|
749
731
|
this.use(middleware);
|
|
@@ -758,296 +740,276 @@ class Spear {
|
|
|
758
740
|
}
|
|
759
741
|
_customizeResponse(req, res) {
|
|
760
742
|
const response = res;
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
// return res.end(results)
|
|
768
|
-
// }
|
|
769
|
-
// if(!res.headersSent) {
|
|
770
|
-
// res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
771
|
-
// }
|
|
772
|
-
// if(results == null) {
|
|
773
|
-
// if(this._formatResponse != null) {
|
|
774
|
-
// return res.end(JSON.stringify(this._formatResponse(null, res.statusCode),null,2))
|
|
775
|
-
// }
|
|
776
|
-
// return res.end()
|
|
777
|
-
// }
|
|
778
|
-
// if(this._formatResponse != null) {
|
|
779
|
-
// return res.end(JSON.stringify(
|
|
780
|
-
// this._formatResponse({
|
|
781
|
-
// ...results
|
|
782
|
-
// }, res.statusCode) ,null, 2)
|
|
783
|
-
// )
|
|
784
|
-
// }
|
|
785
|
-
// return res.end(JSON.stringify({
|
|
786
|
-
// ...results,
|
|
787
|
-
// },null,2))
|
|
788
|
-
// }
|
|
789
|
-
// response.send = (results : string) => {
|
|
790
|
-
// if (res.writableEnded) return;
|
|
791
|
-
// res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' })
|
|
792
|
-
// return res.end(results)
|
|
793
|
-
// }
|
|
794
|
-
// response.html = (results : string) => {
|
|
795
|
-
// if (res.writableEnded) return;
|
|
796
|
-
// res.writeHead(res.statusCode, {'Content-Type': 'text/html'})
|
|
797
|
-
// return res.end(results)
|
|
798
|
-
// }
|
|
799
|
-
// response.error = (err ) => {
|
|
800
|
-
// let code =
|
|
801
|
-
// +err.response?.data?.code ||
|
|
802
|
-
// +err.code ||
|
|
803
|
-
// +err.status ||
|
|
804
|
-
// +err.statusCode ||
|
|
805
|
-
// +err.response?.data?.statusCode ||
|
|
806
|
-
// 500;
|
|
807
|
-
// code = (code == null || typeof code !== 'number') ? 500 : Number.isNaN(code) ? 500 : code < 400 ? 500 : code
|
|
808
|
-
// const message =
|
|
809
|
-
// err.response?.data?.errorMessage ||
|
|
810
|
-
// err.response?.data?.message ||
|
|
811
|
-
// err.message ||
|
|
812
|
-
// `The url '${req.url}' resulted in a server error. Please investigate.`
|
|
813
|
-
// ;
|
|
814
|
-
// response.status(code as any)
|
|
815
|
-
// if(this._formatResponse != null) {
|
|
816
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, code) ,null,2))
|
|
817
|
-
// }
|
|
818
|
-
// return res.end(JSON.stringify({
|
|
819
|
-
// message : message
|
|
820
|
-
// },null,2))
|
|
821
|
-
// }
|
|
822
|
-
// response.ok = (results ?: Record<string,any> ) => {
|
|
823
|
-
// return response.json(results == null ? {} : results)
|
|
824
|
-
// }
|
|
825
|
-
// response.created = (results ?: Record<string,any>) => {
|
|
826
|
-
// response.status(201)
|
|
827
|
-
// return response.json(results == null ? {} : results)
|
|
828
|
-
// }
|
|
829
|
-
// response.accepted = (results ?: Record<string,any>) => {
|
|
830
|
-
// response.status(202)
|
|
831
|
-
// return response.json(results == null ? {} : results)
|
|
832
|
-
// }
|
|
833
|
-
// response.noContent = () => {
|
|
834
|
-
// response.status(204)
|
|
835
|
-
// return res.end()
|
|
836
|
-
// }
|
|
837
|
-
// response.badRequest = (message ?: string) => {
|
|
838
|
-
// if (res.writableEnded) return;
|
|
839
|
-
// response.status(400)
|
|
840
|
-
// message = message ?? `The url '${req.url}' resulted in a bad request. Please review the data and try again.`
|
|
841
|
-
// if(this._formatResponse != null) {
|
|
842
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, 400) ,null,2))
|
|
843
|
-
// }
|
|
844
|
-
// return res.end(JSON.stringify({
|
|
845
|
-
// message : message
|
|
846
|
-
// },null,2))
|
|
847
|
-
// }
|
|
848
|
-
// response.unauthorized = (message ?: string) => {
|
|
849
|
-
// response.status(401)
|
|
850
|
-
// message = message ?? `The url '${req.url}' is unauthorized. Please verify.`
|
|
851
|
-
// if(this._formatResponse != null) {
|
|
852
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, 401) ,null,2))
|
|
853
|
-
// }
|
|
854
|
-
// return res.end(JSON.stringify({
|
|
855
|
-
// message
|
|
856
|
-
// },null,2))
|
|
857
|
-
// }
|
|
858
|
-
// response.paymentRequired = (message ?: string) => {
|
|
859
|
-
// response.status(402)
|
|
860
|
-
// message = message ?? `The url '${req.url}' requires payment. Please proceed with payment.`
|
|
861
|
-
// if(this._formatResponse != null) {
|
|
862
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, 402) ,null,2))
|
|
863
|
-
// }
|
|
864
|
-
// return res.end(JSON.stringify({
|
|
865
|
-
// message
|
|
866
|
-
// },null,2))
|
|
867
|
-
// }
|
|
868
|
-
// response.forbidden = (message ?: string) => {
|
|
869
|
-
// response.status(403)
|
|
870
|
-
// message = message ?? `The url '${req.url}' is forbidden. Please check the permissions or access rights.`
|
|
871
|
-
// if(this._formatResponse != null) {
|
|
872
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, 403) ,null,2))
|
|
873
|
-
// }
|
|
874
|
-
// return res.end(JSON.stringify({
|
|
875
|
-
// message
|
|
876
|
-
// },null,2))
|
|
877
|
-
// }
|
|
878
|
-
// response.notFound = (message ?: string) => {
|
|
879
|
-
// response.status(404)
|
|
880
|
-
// message = message ?? `The url '${req.url}' was not found. Please re-check the your url again.`
|
|
881
|
-
// if(this._formatResponse != null) {
|
|
882
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, 404) ,null,2))
|
|
883
|
-
// }
|
|
884
|
-
// return res.end(JSON.stringify({
|
|
885
|
-
// message
|
|
886
|
-
// },null,2))
|
|
887
|
-
// }
|
|
888
|
-
// response.tooManyRequests = (message ?: string) => {
|
|
889
|
-
// response.status(429)
|
|
890
|
-
// message = message ?? `The url '${req.url}' is too many request. Please wait and try agian.`
|
|
891
|
-
// if(this._formatResponse != null) {
|
|
892
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, 404) ,null,2))
|
|
893
|
-
// }
|
|
894
|
-
// return res.end(JSON.stringify({
|
|
895
|
-
// message
|
|
896
|
-
// },null,2))
|
|
897
|
-
// }
|
|
898
|
-
// response.serverError = (message ?: string) => {
|
|
899
|
-
// response.status(500)
|
|
900
|
-
// message = message ?? `The url '${req.url}' resulted in a server error. Please investigate.`
|
|
901
|
-
// if(this._formatResponse != null) {
|
|
902
|
-
// return res.end(JSON.stringify(this._formatResponse({ message }, 500) ,null,2))
|
|
903
|
-
// }
|
|
904
|
-
// return res.end(JSON.stringify({
|
|
905
|
-
// message
|
|
906
|
-
// },null,2))
|
|
907
|
-
// }
|
|
908
|
-
// response.status = (code : number) => {
|
|
909
|
-
// res.writeHead(code, { 'Content-Type': 'application/json' })
|
|
910
|
-
// return res as unknown as {
|
|
911
|
-
// json : (data?: { [key: string]: any }) => void;
|
|
912
|
-
// send : (message : string) => void;
|
|
913
|
-
// }
|
|
914
|
-
// }
|
|
915
|
-
// response.setCookies = (cookies : Record<string,string | {
|
|
916
|
-
// value : string
|
|
917
|
-
// sameSite ?: 'Strict' | 'Lax' | 'None'
|
|
918
|
-
// domain ?: string
|
|
919
|
-
// secure ?: boolean
|
|
920
|
-
// httpOnly ?: boolean
|
|
921
|
-
// expires ?: Date
|
|
922
|
-
// }> ) => {
|
|
923
|
-
// for(const [key,v] of Object.entries(cookies)) {
|
|
924
|
-
// if(typeof v === 'string') {
|
|
925
|
-
// res.setHeader('Set-Cookie', `${key}=${v}`);
|
|
926
|
-
// continue
|
|
927
|
-
// }
|
|
928
|
-
// if(v.value === '' || v.value == null) continue
|
|
929
|
-
// let str = `${key}=${v.value}`
|
|
930
|
-
// if(v.sameSite != null) {
|
|
931
|
-
// str += ` ;SameSite=${v.sameSite}`
|
|
932
|
-
// }
|
|
933
|
-
// if(v.domain != null) {
|
|
934
|
-
// str += ` ;Domain=${v.domain}`
|
|
935
|
-
// }
|
|
936
|
-
// if(v.httpOnly != null) {
|
|
937
|
-
// str += ` ;HttpOnly`
|
|
938
|
-
// }
|
|
939
|
-
// if(v.secure != null) {
|
|
940
|
-
// str += ` ;Secure`
|
|
941
|
-
// }
|
|
942
|
-
// if(v.expires != null) {
|
|
943
|
-
// str += ` ;Expires=${v.expires.toUTCString()}`
|
|
944
|
-
// }
|
|
945
|
-
// res.setHeader('Set-Cookie', str);
|
|
946
|
-
// }
|
|
947
|
-
// }
|
|
948
|
-
return response;
|
|
949
|
-
}
|
|
950
|
-
_nextFunction(ctx) {
|
|
951
|
-
const NEXT_MESSAGE = "The 'next' function does not have any subsequent function.";
|
|
952
|
-
return (err) => {
|
|
953
|
-
if (err != null) {
|
|
954
|
-
if (this._errorHandler != null) {
|
|
955
|
-
return this._errorHandler(err, ctx);
|
|
743
|
+
response.json = (results) => {
|
|
744
|
+
if (res.writableEnded)
|
|
745
|
+
return;
|
|
746
|
+
if (typeof results === 'string') {
|
|
747
|
+
if (!res.headersSent) {
|
|
748
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
956
749
|
}
|
|
957
|
-
|
|
750
|
+
return res.end(results);
|
|
751
|
+
}
|
|
752
|
+
if (!res.headersSent) {
|
|
753
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
754
|
+
}
|
|
755
|
+
if (results == null) {
|
|
958
756
|
if (this._formatResponse != null) {
|
|
959
|
-
return
|
|
960
|
-
message: err?.message,
|
|
961
|
-
}, ctx.res.statusCode), null, 2));
|
|
757
|
+
return res.end(JSON.stringify(this._formatResponse(null, res.statusCode), null, 2));
|
|
962
758
|
}
|
|
963
|
-
return
|
|
964
|
-
message: err?.message,
|
|
965
|
-
}, null, 2));
|
|
759
|
+
return res.end();
|
|
966
760
|
}
|
|
967
|
-
if (this.
|
|
968
|
-
return this.
|
|
761
|
+
if (this._formatResponse != null) {
|
|
762
|
+
return res.end(JSON.stringify(this._formatResponse({
|
|
763
|
+
...results
|
|
764
|
+
}, res.statusCode), null, 2));
|
|
969
765
|
}
|
|
970
|
-
|
|
766
|
+
return res.end(JSON.stringify({
|
|
767
|
+
...results,
|
|
768
|
+
}, null, 2));
|
|
769
|
+
};
|
|
770
|
+
response.send = (results) => {
|
|
771
|
+
if (res.writableEnded)
|
|
772
|
+
return;
|
|
773
|
+
res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
|
|
774
|
+
return res.end(results);
|
|
775
|
+
};
|
|
776
|
+
response.html = (results) => {
|
|
777
|
+
if (res.writableEnded)
|
|
778
|
+
return;
|
|
779
|
+
res.writeHead(res.statusCode, { 'Content-Type': 'text/html' });
|
|
780
|
+
return res.end(results);
|
|
781
|
+
};
|
|
782
|
+
response.error = (err) => {
|
|
783
|
+
const statusCandidates = [
|
|
784
|
+
err?.response?.data?.code,
|
|
785
|
+
err?.code,
|
|
786
|
+
err?.status,
|
|
787
|
+
err?.statusCode,
|
|
788
|
+
err?.response?.data?.statusCode
|
|
789
|
+
];
|
|
790
|
+
let code = statusCandidates
|
|
791
|
+
.map(v => Number(v))
|
|
792
|
+
.find(v => Number.isFinite(v) && v >= 400) ?? 500;
|
|
793
|
+
const message = err?.response?.data?.errorMessage ??
|
|
794
|
+
err?.response?.data?.message ??
|
|
795
|
+
err?.message ??
|
|
796
|
+
`The request '${req.url}' resulted in a server error.`;
|
|
797
|
+
response.status(code);
|
|
798
|
+
const payload = { message };
|
|
799
|
+
if (this._formatResponse) {
|
|
800
|
+
return res.end(JSON.stringify(this._formatResponse(payload, code)));
|
|
801
|
+
}
|
|
802
|
+
return res.end(JSON.stringify(payload));
|
|
803
|
+
};
|
|
804
|
+
response.ok = (results) => {
|
|
805
|
+
return response.json(results == null ? {} : results);
|
|
806
|
+
};
|
|
807
|
+
response.created = (results) => {
|
|
808
|
+
response.status(201);
|
|
809
|
+
return response.json(results == null ? {} : results);
|
|
810
|
+
};
|
|
811
|
+
response.accepted = (results) => {
|
|
812
|
+
response.status(202);
|
|
813
|
+
return response.json(results == null ? {} : results);
|
|
814
|
+
};
|
|
815
|
+
response.noContent = () => {
|
|
816
|
+
response.status(204);
|
|
817
|
+
return res.end();
|
|
818
|
+
};
|
|
819
|
+
response.badRequest = (message) => {
|
|
820
|
+
if (res.writableEnded)
|
|
821
|
+
return;
|
|
822
|
+
response.status(400);
|
|
823
|
+
message = message ?? `The request '${req.url}' resulted in a bad request. Please review the data and try again.`;
|
|
971
824
|
if (this._formatResponse != null) {
|
|
972
|
-
return
|
|
973
|
-
message: NEXT_MESSAGE
|
|
974
|
-
}, ctx.res.statusCode), null, 2));
|
|
825
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 400), null, 2));
|
|
975
826
|
}
|
|
976
|
-
return
|
|
977
|
-
message:
|
|
827
|
+
return res.end(JSON.stringify({
|
|
828
|
+
message: message
|
|
978
829
|
}, null, 2));
|
|
979
830
|
};
|
|
831
|
+
response.unauthorized = (message) => {
|
|
832
|
+
response.status(401);
|
|
833
|
+
message = message ?? `The request '${req.url}' is unauthorized. Please verify.`;
|
|
834
|
+
if (this._formatResponse != null) {
|
|
835
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 401), null, 2));
|
|
836
|
+
}
|
|
837
|
+
return res.end(JSON.stringify({
|
|
838
|
+
message
|
|
839
|
+
}, null, 2));
|
|
840
|
+
};
|
|
841
|
+
response.paymentRequired = (message) => {
|
|
842
|
+
response.status(402);
|
|
843
|
+
message = message ?? `The request '${req.url}' requires payment. Please proceed with payment.`;
|
|
844
|
+
if (this._formatResponse != null) {
|
|
845
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 402), null, 2));
|
|
846
|
+
}
|
|
847
|
+
return res.end(JSON.stringify({
|
|
848
|
+
message
|
|
849
|
+
}, null, 2));
|
|
850
|
+
};
|
|
851
|
+
response.forbidden = (message) => {
|
|
852
|
+
response.status(403);
|
|
853
|
+
message = message ?? `The request '${req.url}' is forbidden. Please check the permissions or access rights.`;
|
|
854
|
+
if (this._formatResponse != null) {
|
|
855
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 403), null, 2));
|
|
856
|
+
}
|
|
857
|
+
return res.end(JSON.stringify({
|
|
858
|
+
message
|
|
859
|
+
}, null, 2));
|
|
860
|
+
};
|
|
861
|
+
response.notFound = (message) => {
|
|
862
|
+
response.status(404);
|
|
863
|
+
message = message ?? `The request '${req.url}' was not found. Please re-check the your url again.`;
|
|
864
|
+
if (this._formatResponse != null) {
|
|
865
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 404), null, 2));
|
|
866
|
+
}
|
|
867
|
+
return res.end(JSON.stringify({
|
|
868
|
+
message
|
|
869
|
+
}, null, 2));
|
|
870
|
+
};
|
|
871
|
+
response.unprocessable = (message) => {
|
|
872
|
+
response.status(422);
|
|
873
|
+
message = message ?? `The request to '${req.url}' failed validation.`;
|
|
874
|
+
if (this._formatResponse != null) {
|
|
875
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 422), null, 2));
|
|
876
|
+
}
|
|
877
|
+
return res.end(JSON.stringify({
|
|
878
|
+
message
|
|
879
|
+
}, null, 2));
|
|
880
|
+
};
|
|
881
|
+
response.tooManyRequests = (message) => {
|
|
882
|
+
response.status(429);
|
|
883
|
+
message = message ?? `The request '${req.url}' is too many request. Please wait and try agian.`;
|
|
884
|
+
if (this._formatResponse != null) {
|
|
885
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 429), null, 2));
|
|
886
|
+
}
|
|
887
|
+
return res.end(JSON.stringify({
|
|
888
|
+
message
|
|
889
|
+
}, null, 2));
|
|
890
|
+
};
|
|
891
|
+
response.serverError = (message) => {
|
|
892
|
+
response.status(500);
|
|
893
|
+
message = message ?? `The request '${req.url}' resulted in a server error. Please investigate.`;
|
|
894
|
+
if (this._formatResponse != null) {
|
|
895
|
+
return res.end(JSON.stringify(this._formatResponse({ message }, 500), null, 2));
|
|
896
|
+
}
|
|
897
|
+
return res.end(JSON.stringify({
|
|
898
|
+
message
|
|
899
|
+
}, null, 2));
|
|
900
|
+
};
|
|
901
|
+
response.status = (code) => {
|
|
902
|
+
res.writeHead(code, { 'Content-Type': 'application/json' });
|
|
903
|
+
return res;
|
|
904
|
+
};
|
|
905
|
+
response.setCookies = (cookies) => {
|
|
906
|
+
for (const [key, v] of Object.entries(cookies)) {
|
|
907
|
+
if (typeof v === 'string') {
|
|
908
|
+
res.setHeader('Set-Cookie', `${key}=${v}`);
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
if (v.value === '' || v.value == null)
|
|
912
|
+
continue;
|
|
913
|
+
let str = `${key}=${v.value}`;
|
|
914
|
+
if (v.sameSite != null) {
|
|
915
|
+
str += ` ;SameSite=${v.sameSite}`;
|
|
916
|
+
}
|
|
917
|
+
if (v.domain != null) {
|
|
918
|
+
str += ` ;Domain=${v.domain}`;
|
|
919
|
+
}
|
|
920
|
+
if (v.httpOnly != null) {
|
|
921
|
+
str += ` ;HttpOnly`;
|
|
922
|
+
}
|
|
923
|
+
if (v.secure != null) {
|
|
924
|
+
str += ` ;Secure`;
|
|
925
|
+
}
|
|
926
|
+
if (v.expires != null) {
|
|
927
|
+
str += ` ;Expires=${v.expires.toUTCString()}`;
|
|
928
|
+
}
|
|
929
|
+
res.setHeader('Set-Cookie', str);
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
return response;
|
|
980
933
|
}
|
|
981
|
-
_wrapHandlers
|
|
934
|
+
_wrapHandlers(...handlers) {
|
|
982
935
|
return (req, res, params) => {
|
|
983
936
|
const nextHandler = (index = 0) => {
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
.
|
|
937
|
+
try {
|
|
938
|
+
const response = this._customizeResponse(req, res);
|
|
939
|
+
const request = req;
|
|
940
|
+
request.params = params;
|
|
941
|
+
const body = request.body;
|
|
942
|
+
const files = request.files;
|
|
943
|
+
const cookies = request.cookies;
|
|
944
|
+
const headers = request.headers;
|
|
945
|
+
const url = new url_1.URL(req.url, "http://localhost");
|
|
946
|
+
const query = Object.fromEntries(url.searchParams);
|
|
947
|
+
const RecordOrEmptyRecord = (data) => {
|
|
948
|
+
if (data == null)
|
|
949
|
+
return {};
|
|
950
|
+
return Object.keys(data).length ? data : {};
|
|
951
|
+
};
|
|
952
|
+
const ctx = {
|
|
953
|
+
req: request,
|
|
954
|
+
res: response,
|
|
955
|
+
headers: RecordOrEmptyRecord(headers),
|
|
956
|
+
params: RecordOrEmptyRecord(params),
|
|
957
|
+
query: RecordOrEmptyRecord(query),
|
|
958
|
+
body: RecordOrEmptyRecord(body),
|
|
959
|
+
files: RecordOrEmptyRecord(files),
|
|
960
|
+
cookies: RecordOrEmptyRecord(cookies)
|
|
961
|
+
};
|
|
962
|
+
if (index === handlers.length - 1) {
|
|
963
|
+
return this._wrapResponse(handlers[index]
|
|
964
|
+
.bind(handlers[index]))(ctx, this._nextFunction(ctx));
|
|
965
|
+
}
|
|
966
|
+
return handlers[index](ctx, () => {
|
|
967
|
+
return nextHandler(index + 1);
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
catch (err) {
|
|
971
|
+
const ctx = {
|
|
972
|
+
req,
|
|
973
|
+
res: this._customizeResponse(req, res),
|
|
974
|
+
params: Object.keys(params).length ? params : {},
|
|
975
|
+
headers: {},
|
|
976
|
+
query: {},
|
|
977
|
+
body: {},
|
|
978
|
+
files: {},
|
|
979
|
+
cookies: {}
|
|
980
|
+
};
|
|
981
|
+
return this._nextFunction(ctx)(err);
|
|
1011
982
|
}
|
|
1012
|
-
return handlers[index](ctx, () => {
|
|
1013
|
-
return nextHandler(index + 1);
|
|
1014
|
-
});
|
|
1015
983
|
};
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
return nextHandler();
|
|
1020
|
-
}
|
|
1021
|
-
catch (err) {
|
|
1022
|
-
const ctx = {
|
|
1023
|
-
req,
|
|
1024
|
-
res: this._customizeResponse(req, res),
|
|
1025
|
-
params: Object.keys(params).length ? params : {},
|
|
1026
|
-
headers: {},
|
|
1027
|
-
query: {},
|
|
1028
|
-
body: {},
|
|
1029
|
-
files: {},
|
|
1030
|
-
cookies: {}
|
|
1031
|
-
};
|
|
1032
|
-
return this._nextFunction(ctx)(err);
|
|
1033
|
-
}
|
|
984
|
+
if (res.writableEnded)
|
|
985
|
+
return;
|
|
986
|
+
return nextHandler();
|
|
1034
987
|
};
|
|
1035
|
-
}
|
|
988
|
+
}
|
|
1036
989
|
_wrapResponse(handler) {
|
|
1037
990
|
return (ctx, next) => {
|
|
1038
991
|
Promise.resolve(handler(ctx, next))
|
|
1039
992
|
.then(result => {
|
|
1040
993
|
if (ctx.res.writableEnded)
|
|
1041
994
|
return;
|
|
1042
|
-
if (result instanceof http_1.ServerResponse)
|
|
995
|
+
if (result instanceof http_1.ServerResponse) {
|
|
996
|
+
if (result?.end) {
|
|
997
|
+
result.end();
|
|
998
|
+
}
|
|
1043
999
|
return;
|
|
1044
|
-
|
|
1000
|
+
}
|
|
1001
|
+
if (result == null) {
|
|
1002
|
+
if (!ctx.res.headersSent) {
|
|
1003
|
+
ctx.res.writeHead(204, { 'Content-Type': 'text/plain' });
|
|
1004
|
+
}
|
|
1005
|
+
ctx.res.end();
|
|
1045
1006
|
return;
|
|
1007
|
+
}
|
|
1046
1008
|
if (typeof result === 'string') {
|
|
1047
1009
|
if (!ctx.res.headersSent) {
|
|
1048
1010
|
ctx.res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
1049
1011
|
}
|
|
1050
|
-
ctx.res.end(result);
|
|
1012
|
+
ctx.res.end(result ?? '');
|
|
1051
1013
|
return;
|
|
1052
1014
|
}
|
|
1053
1015
|
if (this._formatResponse != null) {
|
|
@@ -1062,26 +1024,58 @@ class Spear {
|
|
|
1062
1024
|
if (!ctx.res.headersSent) {
|
|
1063
1025
|
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1064
1026
|
}
|
|
1065
|
-
ctx.res.end(JSON.stringify(formattedResult
|
|
1027
|
+
ctx.res.end(JSON.stringify(formattedResult));
|
|
1066
1028
|
return;
|
|
1067
1029
|
}
|
|
1068
1030
|
if (!ctx.res.headersSent) {
|
|
1069
1031
|
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1070
1032
|
}
|
|
1071
|
-
ctx.res.end(
|
|
1033
|
+
ctx.res.end(JSON.stringify(result));
|
|
1072
1034
|
return;
|
|
1073
1035
|
})
|
|
1074
1036
|
.catch(err => {
|
|
1075
|
-
|
|
1076
|
-
return;
|
|
1077
|
-
if (!ctx.res.headersSent) {
|
|
1078
|
-
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1079
|
-
}
|
|
1080
|
-
ctx.res.end(JSON.stringify({ message: err?.message || 'Internal Server Error' }));
|
|
1081
|
-
return;
|
|
1037
|
+
return this._nextFunction(ctx)(err);
|
|
1082
1038
|
});
|
|
1083
1039
|
};
|
|
1084
1040
|
}
|
|
1041
|
+
_nextFunction(ctx) {
|
|
1042
|
+
const NEXT_MESSAGE = "The 'next' function does not have any subsequent function.";
|
|
1043
|
+
return (err) => {
|
|
1044
|
+
if (err != null) {
|
|
1045
|
+
if (this._errorHandler != null) {
|
|
1046
|
+
const callback = this._errorHandler(err, ctx);
|
|
1047
|
+
if (callback == null || !(callback instanceof http_1.ServerResponse)) {
|
|
1048
|
+
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1049
|
+
return ctx.res.end(JSON.stringify({
|
|
1050
|
+
message: err?.message
|
|
1051
|
+
}, null, 2));
|
|
1052
|
+
}
|
|
1053
|
+
return callback;
|
|
1054
|
+
}
|
|
1055
|
+
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1056
|
+
if (this._formatResponse != null) {
|
|
1057
|
+
return ctx.res.end(JSON.stringify(this._formatResponse({
|
|
1058
|
+
message: err?.message,
|
|
1059
|
+
}, ctx.res.statusCode), null, 2));
|
|
1060
|
+
}
|
|
1061
|
+
return ctx.res.end(JSON.stringify({
|
|
1062
|
+
message: err?.message
|
|
1063
|
+
}, null, 2));
|
|
1064
|
+
}
|
|
1065
|
+
if (this._errorHandler != null) {
|
|
1066
|
+
return this._errorHandler(new Error(NEXT_MESSAGE), ctx);
|
|
1067
|
+
}
|
|
1068
|
+
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
1069
|
+
if (this._formatResponse != null) {
|
|
1070
|
+
return ctx.res.end(JSON.stringify(this._formatResponse({
|
|
1071
|
+
message: NEXT_MESSAGE
|
|
1072
|
+
}, ctx.res.statusCode), null, 2));
|
|
1073
|
+
}
|
|
1074
|
+
return ctx.res.end(JSON.stringify({
|
|
1075
|
+
message: NEXT_MESSAGE
|
|
1076
|
+
}, null, 2));
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1085
1079
|
async _createServer() {
|
|
1086
1080
|
await this._registerMiddlewares();
|
|
1087
1081
|
await this._registerControllers();
|
|
@@ -1090,10 +1084,10 @@ class Spear {
|
|
|
1090
1084
|
const server = http_1.default.createServer({ maxHeaderSize: 1024 * 1024 }, cors
|
|
1091
1085
|
? (req, res) => {
|
|
1092
1086
|
cors(req, res);
|
|
1093
|
-
lookup(req, res);
|
|
1087
|
+
return lookup(req, res);
|
|
1094
1088
|
}
|
|
1095
1089
|
: (req, res) => {
|
|
1096
|
-
lookup(req, res);
|
|
1090
|
+
return lookup(req, res);
|
|
1097
1091
|
});
|
|
1098
1092
|
if (this._ws) {
|
|
1099
1093
|
this._wss = new ws_1.default.Server({ server, ...this._wsOptions });
|
|
@@ -1126,18 +1120,28 @@ class Spear {
|
|
|
1126
1120
|
.replace(/\/+/g, '/')
|
|
1127
1121
|
.replace(/\/+$/, '');
|
|
1128
1122
|
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
|
1129
|
-
return /\/api\/api/.test(normalizedPath)
|
|
1123
|
+
return /\/api\/api/.test(normalizedPath)
|
|
1124
|
+
? normalizedPath.replace(/\/api\/api\//, "/api/")
|
|
1125
|
+
: normalizedPath;
|
|
1130
1126
|
}
|
|
1131
1127
|
_swaggerHandler() {
|
|
1132
1128
|
const routes = this.routers
|
|
1133
|
-
.routes
|
|
1129
|
+
.routes
|
|
1130
|
+
.filter(r => {
|
|
1131
|
+
return [
|
|
1132
|
+
"GET", "POST",
|
|
1133
|
+
"PUT", "PATCH",
|
|
1134
|
+
"DELETE",
|
|
1135
|
+
"HEAD", "OPTIONS"
|
|
1136
|
+
].includes(r.method);
|
|
1137
|
+
});
|
|
1134
1138
|
const { path, html, staticSwaggerHandler, staticUrl } = this._parser.swagger({
|
|
1135
1139
|
...this._swagger,
|
|
1136
|
-
specs: this.
|
|
1140
|
+
specs: this._swaggerSpecs,
|
|
1137
1141
|
routes
|
|
1138
1142
|
});
|
|
1139
1143
|
this._router.get(staticUrl, staticSwaggerHandler);
|
|
1140
|
-
this._router.get(
|
|
1144
|
+
this._router.get(path, (_, res) => {
|
|
1141
1145
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
1142
1146
|
res.write(html);
|
|
1143
1147
|
return res.end();
|