tspace-spear 1.0.0 → 1.0.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/License +1 -1
- package/README.md +364 -47
- package/build/lib/core/decorators/context.js +11 -10
- package/build/lib/core/decorators/context.js.map +1 -0
- package/build/lib/core/decorators/controller.js +1 -0
- package/build/lib/core/decorators/controller.js.map +1 -0
- package/build/lib/core/decorators/headers.js +1 -0
- package/build/lib/core/decorators/headers.js.map +1 -0
- package/build/lib/core/decorators/index.d.ts +1 -0
- package/build/lib/core/decorators/index.js +2 -0
- package/build/lib/core/decorators/index.js.map +1 -0
- package/build/lib/core/decorators/methods.js +1 -0
- package/build/lib/core/decorators/methods.js.map +1 -0
- package/build/lib/core/decorators/middleware.d.ts +1 -1
- package/build/lib/core/decorators/middleware.js +1 -0
- package/build/lib/core/decorators/middleware.js.map +1 -0
- package/build/lib/core/decorators/statusCode.js +1 -0
- package/build/lib/core/decorators/statusCode.js.map +1 -0
- package/build/lib/core/decorators/swagger.d.ts +2 -0
- package/build/lib/core/decorators/swagger.js +15 -0
- package/build/lib/core/decorators/swagger.js.map +1 -0
- package/build/lib/core/server/index.d.ts +90 -44
- package/build/lib/core/server/index.js +314 -286
- package/build/lib/core/server/index.js.map +1 -0
- package/build/lib/core/server/parser-factory.d.ts +26 -0
- package/build/lib/core/server/parser-factory.js +428 -0
- package/build/lib/core/server/parser-factory.js.map +1 -0
- package/build/lib/core/server/q.bak.d.ts +0 -0
- package/build/lib/core/server/q.bak.js +965 -0
- package/build/lib/core/server/q.bak.js.map +1 -0
- package/build/lib/core/server/router.d.ts +63 -2
- package/build/lib/core/server/router.js +63 -1
- package/build/lib/core/server/router.js.map +1 -0
- package/build/lib/{types → core/types}/index.d.ts +85 -9
- package/build/lib/{types → core/types}/index.js +1 -0
- package/build/lib/core/types/index.js.map +1 -0
- package/build/lib/index.d.ts +4 -13
- package/build/lib/index.js +7 -23
- package/build/lib/index.js.map +1 -0
- package/build/tests/benchmark.test.d.ts +1 -0
- package/build/tests/benchmark.test.js +135 -0
- package/build/tests/benchmark.test.js.map +1 -0
- package/package.json +30 -19
|
@@ -35,22 +35,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.Application = void 0;
|
|
38
|
+
exports.Spear = exports.Application = void 0;
|
|
39
|
+
const cluster_1 = __importDefault(require("cluster"));
|
|
40
|
+
const os_1 = __importDefault(require("os"));
|
|
39
41
|
const fs_1 = __importDefault(require("fs"));
|
|
40
42
|
const path_1 = __importDefault(require("path"));
|
|
41
|
-
const find_my_way_1 = __importDefault(require("find-my-way"));
|
|
42
|
-
const formidable_1 = __importDefault(require("formidable"));
|
|
43
43
|
const url_1 = require("url");
|
|
44
44
|
const on_finished_1 = __importDefault(require("on-finished"));
|
|
45
|
-
const string_decoder_1 = require("string_decoder");
|
|
46
45
|
const http_1 = __importStar(require("http"));
|
|
46
|
+
const find_my_way_1 = __importDefault(require("find-my-way"));
|
|
47
|
+
const parser_factory_1 = require("./parser-factory");
|
|
47
48
|
/**
|
|
48
49
|
*
|
|
49
|
-
* The '
|
|
50
|
+
* The 'Spear' class is used to create a server and handle HTTP requests.
|
|
50
51
|
*
|
|
51
|
-
* @returns {
|
|
52
|
+
* @returns {Spear} application
|
|
52
53
|
* @example
|
|
53
|
-
* new
|
|
54
|
+
* new Spear()
|
|
54
55
|
* .get('/' , () => 'Hello world!')
|
|
55
56
|
* .get('/json' , () => {
|
|
56
57
|
* return {
|
|
@@ -60,128 +61,62 @@ const http_1 = __importStar(require("http"));
|
|
|
60
61
|
* .listen(3000 , () => console.log('server listening on port : 3000'))
|
|
61
62
|
*
|
|
62
63
|
*/
|
|
63
|
-
class
|
|
64
|
-
constructor({ controllers, middlewares, globalPrefix, logger } = {}) {
|
|
64
|
+
class Spear {
|
|
65
|
+
constructor({ controllers, middlewares, globalPrefix, logger, cluster } = {}) {
|
|
65
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"
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
this._swaggerAdditional = [];
|
|
66
84
|
this._errorHandler = null;
|
|
67
85
|
this._globalMiddlewares = [];
|
|
68
86
|
this._formatResponse = null;
|
|
69
87
|
this._onListeners = [];
|
|
70
88
|
this._fileUploadOptions = {
|
|
71
|
-
|
|
72
|
-
useTempFiles: false,
|
|
89
|
+
limit: Infinity,
|
|
73
90
|
tempFileDir: 'tmp',
|
|
74
91
|
removeTempFile: {
|
|
75
|
-
remove:
|
|
92
|
+
remove: false,
|
|
76
93
|
ms: 1000 * 60 * 10
|
|
77
94
|
}
|
|
78
95
|
};
|
|
79
|
-
this._filesParser = (req) => __awaiter(this, void 0, void 0, function* () {
|
|
80
|
-
try {
|
|
81
|
-
const temp = this._fileUploadOptions.tempFileDir;
|
|
82
|
-
if (!fs_1.default.existsSync(temp)) {
|
|
83
|
-
try {
|
|
84
|
-
fs_1.default.mkdirSync(temp, { recursive: true });
|
|
85
|
-
}
|
|
86
|
-
catch (err) { }
|
|
87
|
-
}
|
|
88
|
-
const form = (0, formidable_1.default)({ uploadDir: temp });
|
|
89
|
-
const [dataBody, dataFiles] = yield form.parse(req);
|
|
90
|
-
const files = {};
|
|
91
|
-
const body = {};
|
|
92
|
-
const removeTemp = (fileTemp) => {
|
|
93
|
-
if (!this._fileUploadOptions.removeTempFile.remove)
|
|
94
|
-
return;
|
|
95
|
-
const remove = () => fs_1.default.unlinkSync(fileTemp);
|
|
96
|
-
setTimeout(remove, this._fileUploadOptions.removeTempFile.ms);
|
|
97
|
-
};
|
|
98
|
-
for (const key in dataFiles) {
|
|
99
|
-
const v = dataFiles[key];
|
|
100
|
-
if (v == null)
|
|
101
|
-
continue;
|
|
102
|
-
const file = v[0];
|
|
103
|
-
if (file.size > this._fileUploadOptions.limits) {
|
|
104
|
-
fs_1.default.unlinkSync(file.filepath);
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
files[key] = {
|
|
108
|
-
size: file.size,
|
|
109
|
-
tempFilePath: file.filepath,
|
|
110
|
-
tempFileName: file.newFilename,
|
|
111
|
-
mimetype: file.mimetype,
|
|
112
|
-
name: file.originalFilename
|
|
113
|
-
};
|
|
114
|
-
removeTemp(file.filepath);
|
|
115
|
-
}
|
|
116
|
-
for (const key in dataBody) {
|
|
117
|
-
const v = dataBody[key];
|
|
118
|
-
if (v == null)
|
|
119
|
-
continue;
|
|
120
|
-
body[key] = v[0];
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
body,
|
|
124
|
-
files
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
catch (e) {
|
|
128
|
-
return {
|
|
129
|
-
body: {},
|
|
130
|
-
files: {}
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
this._bodyParser = (req) => {
|
|
135
|
-
if ((req === null || req === void 0 ? void 0 : req._writeParserEnd) === true)
|
|
136
|
-
return req._bodyParser;
|
|
137
|
-
return new Promise((resolve, reject) => {
|
|
138
|
-
const decoder = new string_decoder_1.StringDecoder('utf-8');
|
|
139
|
-
let payload = '';
|
|
140
|
-
req.on('data', (data) => {
|
|
141
|
-
payload += decoder.write(data);
|
|
142
|
-
});
|
|
143
|
-
req.on('end', () => {
|
|
144
|
-
try {
|
|
145
|
-
payload += decoder.end();
|
|
146
|
-
req._writeParserEnd = true;
|
|
147
|
-
req._bodyParser = JSON.parse(payload);
|
|
148
|
-
return resolve(JSON.parse(payload));
|
|
149
|
-
}
|
|
150
|
-
catch (e) {
|
|
151
|
-
req._writeParserEnd = true;
|
|
152
|
-
req._bodyParser = {};
|
|
153
|
-
return resolve({});
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
req.on('error', (err) => {
|
|
157
|
-
req._writeParserEnd = true;
|
|
158
|
-
req._bodyParser = {};
|
|
159
|
-
return reject(err);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
96
|
this._wrapHandlers = (...handlers) => {
|
|
164
97
|
return (req, res, params) => __awaiter(this, void 0, void 0, function* () {
|
|
165
|
-
const runHandler = (
|
|
98
|
+
const runHandler = (...args_1) => __awaiter(this, [...args_1], void 0, function* (index = 0) {
|
|
166
99
|
const response = this._customizeResponse(req, res);
|
|
167
100
|
const request = req;
|
|
168
101
|
const body = request._bodyParser;
|
|
169
102
|
const files = request._filesParser;
|
|
170
103
|
const cookies = request._cookiesParser;
|
|
104
|
+
const headers = request.headers;
|
|
171
105
|
const query = Object.assign({}, (0, url_1.parse)(String(req.url), true).query);
|
|
172
|
-
const
|
|
106
|
+
const RecordOrEmptyRecord = (data) => {
|
|
173
107
|
if (data == null)
|
|
174
|
-
return
|
|
175
|
-
return Object.keys(data).length ? data :
|
|
108
|
+
return {};
|
|
109
|
+
return Object.keys(data).length ? data : {};
|
|
176
110
|
};
|
|
177
111
|
const ctx = {
|
|
178
112
|
req: request,
|
|
179
113
|
res: response,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
114
|
+
headers: RecordOrEmptyRecord(headers),
|
|
115
|
+
params: RecordOrEmptyRecord(params),
|
|
116
|
+
query: RecordOrEmptyRecord(query),
|
|
117
|
+
body: RecordOrEmptyRecord(body),
|
|
118
|
+
files: RecordOrEmptyRecord(files),
|
|
119
|
+
cookies: RecordOrEmptyRecord(cookies),
|
|
185
120
|
};
|
|
186
121
|
if (index === handlers.length - 1) {
|
|
187
122
|
return this._wrapResponse(handlers[index].bind(handlers[index]))(ctx, this._nextFunction(ctx));
|
|
@@ -195,53 +130,30 @@ class Application {
|
|
|
195
130
|
const ctx = {
|
|
196
131
|
req,
|
|
197
132
|
res: this._customizeResponse(req, res),
|
|
198
|
-
params: Object.keys(params).length ? params :
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
133
|
+
params: Object.keys(params).length ? params : {},
|
|
134
|
+
headers: {},
|
|
135
|
+
query: {},
|
|
136
|
+
body: {},
|
|
137
|
+
files: {},
|
|
138
|
+
cookies: {}
|
|
203
139
|
};
|
|
204
140
|
return this._nextFunction(ctx)(err);
|
|
205
141
|
});
|
|
206
142
|
});
|
|
207
143
|
};
|
|
208
144
|
if (logger)
|
|
209
|
-
this.
|
|
145
|
+
this.useLogger();
|
|
146
|
+
this._cluster = cluster;
|
|
210
147
|
this._controllers = controllers;
|
|
211
148
|
this._middlewares = middlewares;
|
|
212
149
|
this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
|
|
213
150
|
}
|
|
214
|
-
|
|
215
|
-
* The 'enableCors' is used to enable the cors origins on the server.
|
|
216
|
-
*
|
|
217
|
-
* @params {Object}
|
|
218
|
-
* @property {(string | RegExp)[]} origins
|
|
219
|
-
* @property {boolean} credentials
|
|
220
|
-
* @returns
|
|
221
|
-
*/
|
|
222
|
-
enableCors({ origins, credentials } = {}) {
|
|
223
|
-
this._globalMiddlewares.push(({ req, res }, next) => {
|
|
224
|
-
var _a;
|
|
225
|
-
const origin = (_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin;
|
|
226
|
-
if (origin == null)
|
|
227
|
-
return next();
|
|
228
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
229
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
230
|
-
if (origins == null) {
|
|
231
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
232
|
-
}
|
|
233
|
-
if (Array.isArray(origins) && origins.length) {
|
|
234
|
-
if (origins.includes(origin)) {
|
|
235
|
-
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
if (credentials) {
|
|
239
|
-
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
240
|
-
}
|
|
241
|
-
return next();
|
|
242
|
-
});
|
|
151
|
+
get instance() {
|
|
243
152
|
return this;
|
|
244
153
|
}
|
|
154
|
+
get routers() {
|
|
155
|
+
return this._router;
|
|
156
|
+
}
|
|
245
157
|
/**
|
|
246
158
|
* The 'use' method is used to add the middleware into the request pipeline.
|
|
247
159
|
*
|
|
@@ -255,24 +167,51 @@ class Application {
|
|
|
255
167
|
return this;
|
|
256
168
|
}
|
|
257
169
|
/**
|
|
258
|
-
* The '
|
|
170
|
+
* The 'useLogger' method is used to add the middleware view logger response.
|
|
259
171
|
*
|
|
260
|
-
* @
|
|
261
|
-
* @property {
|
|
172
|
+
* @callback {Function} middleware
|
|
173
|
+
* @property {Object} ctx - context { req , res , query , params , cookies , files , body}
|
|
174
|
+
* @property {Function} next - go to next function
|
|
262
175
|
* @returns {this}
|
|
263
176
|
*/
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
177
|
+
useLogger({ methods, exceptPath } = {}) {
|
|
178
|
+
this._globalMiddlewares.push(({ req, res }, next) => {
|
|
179
|
+
const diffTime = (hrtime) => {
|
|
180
|
+
const MS = 1000;
|
|
181
|
+
if (hrtime == null)
|
|
182
|
+
return 0;
|
|
183
|
+
const [start, end] = process.hrtime(hrtime);
|
|
184
|
+
const time = ((start * MS) + (end / 1e6));
|
|
185
|
+
return `${time > MS ? `${(time / MS).toFixed(2)} s` : `${time.toFixed(2)} ms`}`;
|
|
186
|
+
};
|
|
187
|
+
const statusCode = (res) => {
|
|
188
|
+
const statusCode = res.statusCode == null ? 500 : Number(res.statusCode);
|
|
189
|
+
return statusCode < 400
|
|
190
|
+
? `\x1b[32m${statusCode}\x1b[0m`
|
|
191
|
+
: `\x1b[31m${statusCode}\x1b[0m`;
|
|
192
|
+
};
|
|
193
|
+
if (exceptPath instanceof RegExp && !exceptPath.test(String(req.url)))
|
|
194
|
+
return next();
|
|
195
|
+
if (Array.isArray(exceptPath) && !exceptPath.some(v => String(req.url) !== v))
|
|
196
|
+
return next();
|
|
197
|
+
if (methods != null &&
|
|
198
|
+
methods.length &&
|
|
199
|
+
!methods.some(v => v.toLocaleLowerCase() === String(req.method).toLocaleLowerCase())) {
|
|
200
|
+
return next();
|
|
201
|
+
}
|
|
202
|
+
const startTime = process.hrtime();
|
|
203
|
+
(0, on_finished_1.default)(res, () => {
|
|
204
|
+
console.log([
|
|
205
|
+
`[\x1b[1m\x1b[34mINFO\x1b[0m]`,
|
|
206
|
+
`\x1b[34m${new Date().toJSON()}\x1b[0m`,
|
|
207
|
+
`\x1b[33m${req.method}\x1b[0m`,
|
|
208
|
+
`${decodeURIComponent(String(req.url))}`,
|
|
209
|
+
`${statusCode(res)}`,
|
|
210
|
+
`${diffTime(startTime)}`,
|
|
211
|
+
].join(" "));
|
|
212
|
+
});
|
|
213
|
+
return next();
|
|
214
|
+
});
|
|
276
215
|
return this;
|
|
277
216
|
}
|
|
278
217
|
/**
|
|
@@ -281,17 +220,14 @@ class Application {
|
|
|
281
220
|
* @returns {this}
|
|
282
221
|
*/
|
|
283
222
|
useBodyParser() {
|
|
284
|
-
this._globalMiddlewares.push((
|
|
223
|
+
this._globalMiddlewares.push((_a, next_1) => __awaiter(this, [_a, next_1], void 0, function* ({ req, res }, next) {
|
|
285
224
|
const contentType = req === null || req === void 0 ? void 0 : req.headers['content-type'];
|
|
286
225
|
const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
|
|
287
|
-
const isListMethods = ['POST', 'PATCH', 'PUT'].includes(String(req.method));
|
|
288
|
-
if (!isListMethods)
|
|
289
|
-
return next();
|
|
290
226
|
if (isFileUpload)
|
|
291
227
|
return next();
|
|
292
228
|
if ((req === null || req === void 0 ? void 0 : req._bodyParser) != null)
|
|
293
229
|
return next();
|
|
294
|
-
req._bodyParser = yield this.
|
|
230
|
+
req._bodyParser = yield this._parser.body(req);
|
|
295
231
|
return next();
|
|
296
232
|
}));
|
|
297
233
|
return this;
|
|
@@ -305,53 +241,149 @@ class Application {
|
|
|
305
241
|
this._globalMiddlewares.push(({ req }, next) => {
|
|
306
242
|
if ((req === null || req === void 0 ? void 0 : req._cookiesParser) != null)
|
|
307
243
|
return next();
|
|
308
|
-
req._cookiesParser = this.
|
|
244
|
+
req._cookiesParser = this._parser.cookies(req);
|
|
309
245
|
return next();
|
|
310
246
|
});
|
|
311
247
|
return this;
|
|
312
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* The 'useRouter' method is used to add the router in the request context.
|
|
251
|
+
*
|
|
252
|
+
* @parms {Function} router
|
|
253
|
+
* @property {Function} router - get() , post() , put() , patch() , delete()
|
|
254
|
+
* @returns {this}
|
|
255
|
+
*/
|
|
256
|
+
useRouter(router) {
|
|
257
|
+
const routes = router.routes;
|
|
258
|
+
for (const { path, method, handlers } of routes) {
|
|
259
|
+
this[method](this._normalizePath(this._globalPrefix, path), ...handlers);
|
|
260
|
+
}
|
|
261
|
+
return this;
|
|
262
|
+
}
|
|
313
263
|
/**
|
|
314
264
|
* The 'useFileUpload' method is a middleware used to handler file uploads. It adds a file upload of incoming HTTP requests.
|
|
315
265
|
*
|
|
316
266
|
* @param {?Object}
|
|
317
267
|
* @property {?number} limits
|
|
318
|
-
* @property {?boolean} useTempFiles
|
|
319
268
|
* @property {?string} tempFileDir
|
|
320
269
|
* @property {?Object} removeTempFile
|
|
321
270
|
* @property {boolean} removeTempFile.remove
|
|
322
271
|
* @property {number} removeTempFile.ms
|
|
323
272
|
* @returns
|
|
324
273
|
*/
|
|
325
|
-
useFileUpload({
|
|
326
|
-
if (
|
|
327
|
-
this._fileUploadOptions.
|
|
274
|
+
useFileUpload({ limit, tempFileDir, removeTempFile } = {}) {
|
|
275
|
+
if (limit != null) {
|
|
276
|
+
this._fileUploadOptions.limit = limit;
|
|
328
277
|
}
|
|
329
278
|
if (tempFileDir != null) {
|
|
330
279
|
this._fileUploadOptions.tempFileDir = tempFileDir;
|
|
331
280
|
}
|
|
332
|
-
if (useTempFiles != null) {
|
|
333
|
-
this._fileUploadOptions.useTempFiles = useTempFiles;
|
|
334
|
-
}
|
|
335
281
|
if (removeTempFile != null) {
|
|
336
282
|
this._fileUploadOptions.removeTempFile = removeTempFile;
|
|
337
283
|
}
|
|
338
|
-
this._globalMiddlewares.push((
|
|
284
|
+
this._globalMiddlewares.push((_a, next_1) => __awaiter(this, [_a, next_1], void 0, function* ({ req }, next) {
|
|
339
285
|
const contentType = req === null || req === void 0 ? void 0 : req.headers['content-type'];
|
|
340
286
|
const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
|
|
341
|
-
const isListMethods = ['POST', 'PATCH', 'PUT'].includes(String(req.method));
|
|
342
|
-
if (!isListMethods)
|
|
343
|
-
return next();
|
|
344
|
-
if (!isFileUpload)
|
|
287
|
+
const isListMethods = ['POST', 'PATCH', 'PUT', 'DELETE'].includes(String(req.method));
|
|
288
|
+
if (!isListMethods || !isFileUpload)
|
|
345
289
|
return next();
|
|
346
290
|
if ((req === null || req === void 0 ? void 0 : req._filesParser) != null)
|
|
347
291
|
return next();
|
|
348
|
-
const { body, files } = yield this.
|
|
292
|
+
const { body, files } = yield this._parser.files({ req, options: this._fileUploadOptions });
|
|
349
293
|
req._filesParser = files;
|
|
350
294
|
req._bodyParser = body;
|
|
351
295
|
return next();
|
|
352
296
|
}));
|
|
353
297
|
return this;
|
|
354
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* The 'useSwagger' method is a middleware used to create swagger api.
|
|
301
|
+
*
|
|
302
|
+
* @param {?Object}
|
|
303
|
+
* @property {?string} path
|
|
304
|
+
* @property {?array} servers
|
|
305
|
+
* @property {?object} info
|
|
306
|
+
* @property {?array} tags
|
|
307
|
+
* @returns
|
|
308
|
+
*/
|
|
309
|
+
useSwagger({ path, servers, info, tags } = {}) {
|
|
310
|
+
this._swagger = {
|
|
311
|
+
use: true,
|
|
312
|
+
path: path !== null && path !== void 0 ? path : this._swagger.path,
|
|
313
|
+
servers: servers !== null && servers !== void 0 ? servers : this._swagger.servers,
|
|
314
|
+
tags: tags !== null && tags !== void 0 ? tags : this._swagger.tags,
|
|
315
|
+
info: info !== null && info !== void 0 ? info : this._swagger.info
|
|
316
|
+
};
|
|
317
|
+
return this;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* The 'listen' method is used to bind and start a server to a particular port and optionally a hostname.
|
|
321
|
+
*
|
|
322
|
+
* @param {number} port
|
|
323
|
+
* @param {function} callback
|
|
324
|
+
* @returns
|
|
325
|
+
*/
|
|
326
|
+
listen() {
|
|
327
|
+
var arguments_1 = arguments;
|
|
328
|
+
return __awaiter(this, arguments, void 0, function* (port = 3000, callback) {
|
|
329
|
+
if (arguments_1.length === 1 && typeof port === 'function') {
|
|
330
|
+
callback = port;
|
|
331
|
+
port = 3000;
|
|
332
|
+
}
|
|
333
|
+
const server = yield this._createServer();
|
|
334
|
+
if (this._cluster != null &&
|
|
335
|
+
this._cluster || (typeof this._cluster === 'object' && Object.keys(this._cluster).length)) {
|
|
336
|
+
this._clusterMode(server, Number(port), callback);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
server.listen(port == null ? 3000 : port, () => {
|
|
340
|
+
if (callback)
|
|
341
|
+
callback({ server, port });
|
|
342
|
+
});
|
|
343
|
+
server.on('listening', () => {
|
|
344
|
+
this._onListeners.forEach(listener => listener());
|
|
345
|
+
if (this._swagger.use) {
|
|
346
|
+
this._swaggerHandler();
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
server.on('error', (_) => {
|
|
350
|
+
port = Math.floor(Math.random() * 8999) + 1000;
|
|
351
|
+
server.listen(port);
|
|
352
|
+
});
|
|
353
|
+
return;
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* The 'enableCors' is used to enable the cors origins on the server.
|
|
358
|
+
*
|
|
359
|
+
* @params {Object}
|
|
360
|
+
* @property {(string | RegExp)[]} origins
|
|
361
|
+
* @property {boolean} credentials
|
|
362
|
+
* @returns
|
|
363
|
+
*/
|
|
364
|
+
enableCors({ origins, credentials } = {}) {
|
|
365
|
+
this._globalMiddlewares.push(({ req, res }, next) => {
|
|
366
|
+
var _a;
|
|
367
|
+
const origin = (_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin;
|
|
368
|
+
if (origin == null)
|
|
369
|
+
return next();
|
|
370
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
|
|
371
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
372
|
+
if (origins == null) {
|
|
373
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
374
|
+
}
|
|
375
|
+
if (Array.isArray(origins) && origins.length) {
|
|
376
|
+
if (origins.includes(origin)) {
|
|
377
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (credentials) {
|
|
381
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
382
|
+
}
|
|
383
|
+
return next();
|
|
384
|
+
});
|
|
385
|
+
return this;
|
|
386
|
+
}
|
|
355
387
|
/**
|
|
356
388
|
* The 'formatResponse' method is used to format the response
|
|
357
389
|
*
|
|
@@ -363,7 +395,9 @@ class Application {
|
|
|
363
395
|
return this;
|
|
364
396
|
}
|
|
365
397
|
/**
|
|
366
|
-
* The 'errorHandler' method is middleware that is specifically designed to handle errors
|
|
398
|
+
* The 'errorHandler' method is middleware that is specifically designed to handle errors.
|
|
399
|
+
*
|
|
400
|
+
* that occur during the processing of requests
|
|
367
401
|
*
|
|
368
402
|
* @param {function} error
|
|
369
403
|
* @returns
|
|
@@ -383,11 +417,12 @@ class Application {
|
|
|
383
417
|
return notfound({
|
|
384
418
|
req,
|
|
385
419
|
res: this._customizeResponse(req, res),
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
420
|
+
headers: {},
|
|
421
|
+
query: {},
|
|
422
|
+
files: {},
|
|
423
|
+
body: {},
|
|
424
|
+
params: {},
|
|
425
|
+
cookies: {}
|
|
391
426
|
});
|
|
392
427
|
};
|
|
393
428
|
this._onListeners.push(() => {
|
|
@@ -406,7 +441,7 @@ class Application {
|
|
|
406
441
|
*/
|
|
407
442
|
get(path, ...handlers) {
|
|
408
443
|
this._onListeners.push(() => {
|
|
409
|
-
return this._router.get(path, this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
444
|
+
return this._router.get(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
410
445
|
});
|
|
411
446
|
return this;
|
|
412
447
|
}
|
|
@@ -421,7 +456,7 @@ class Application {
|
|
|
421
456
|
*/
|
|
422
457
|
post(path, ...handlers) {
|
|
423
458
|
this._onListeners.push(() => {
|
|
424
|
-
return this._router.post(path, this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
459
|
+
return this._router.post(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
425
460
|
});
|
|
426
461
|
return this;
|
|
427
462
|
}
|
|
@@ -436,7 +471,7 @@ class Application {
|
|
|
436
471
|
*/
|
|
437
472
|
put(path, ...handlers) {
|
|
438
473
|
this._onListeners.push(() => {
|
|
439
|
-
return this._router.put(path, this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
474
|
+
return this._router.put(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
440
475
|
});
|
|
441
476
|
return this;
|
|
442
477
|
}
|
|
@@ -451,7 +486,7 @@ class Application {
|
|
|
451
486
|
*/
|
|
452
487
|
patch(path, ...handlers) {
|
|
453
488
|
this._onListeners.push(() => {
|
|
454
|
-
return this._router.patch(path, this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
489
|
+
return this._router.patch(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
455
490
|
});
|
|
456
491
|
return this;
|
|
457
492
|
}
|
|
@@ -466,12 +501,12 @@ class Application {
|
|
|
466
501
|
*/
|
|
467
502
|
delete(path, ...handlers) {
|
|
468
503
|
this._onListeners.push(() => {
|
|
469
|
-
return this._router.delete(path, this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
504
|
+
return this._router.delete(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
470
505
|
});
|
|
471
506
|
return this;
|
|
472
507
|
}
|
|
473
508
|
/**
|
|
474
|
-
* The 'all' method is used to add the request handler to the router for
|
|
509
|
+
* The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' methods.
|
|
475
510
|
*
|
|
476
511
|
* @param {string} path
|
|
477
512
|
* @callback {...Function[]} handlers of the middlewares
|
|
@@ -481,65 +516,44 @@ class Application {
|
|
|
481
516
|
*/
|
|
482
517
|
all(path, ...handlers) {
|
|
483
518
|
this._onListeners.push(() => {
|
|
484
|
-
return this._router.all(path, this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
519
|
+
return this._router.all(this._normalizePath(this._globalPrefix, path), this._wrapHandlers(...this._globalMiddlewares, ...handlers));
|
|
485
520
|
});
|
|
486
521
|
return this;
|
|
487
522
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
port = 3000;
|
|
523
|
+
_clusterMode(server, port, callback) {
|
|
524
|
+
var _a;
|
|
525
|
+
if (cluster_1.default.isPrimary) {
|
|
526
|
+
const numCPUs = os_1.default.cpus().length;
|
|
527
|
+
const maxWorkers = ((_a = this._cluster) === null || _a === void 0 ? void 0 : _a.maxWorkers) == null
|
|
528
|
+
? numCPUs
|
|
529
|
+
: this._cluster.maxWorkers > numCPUs
|
|
530
|
+
? numCPUs
|
|
531
|
+
: this._cluster.maxWorkers;
|
|
532
|
+
for (let i = 0; i < maxWorkers; i++) {
|
|
533
|
+
cluster_1.default.fork();
|
|
500
534
|
}
|
|
501
|
-
|
|
535
|
+
cluster_1.default.on('exit', () => {
|
|
536
|
+
cluster_1.default.fork();
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
if (cluster_1.default.isWorker) {
|
|
540
|
+
server.listen(port == null ? 3000 : port, () => {
|
|
541
|
+
if (callback) {
|
|
542
|
+
callback({ server, port });
|
|
543
|
+
}
|
|
544
|
+
});
|
|
502
545
|
server.on('listening', () => {
|
|
503
546
|
this._onListeners.forEach(listener => listener());
|
|
547
|
+
if (this._swagger.use) {
|
|
548
|
+
this._swaggerHandler();
|
|
549
|
+
}
|
|
504
550
|
});
|
|
505
551
|
server.on('error', (_) => {
|
|
506
552
|
port = Math.floor(Math.random() * 8999) + 1000;
|
|
507
553
|
server.listen(port);
|
|
508
554
|
});
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
cb();
|
|
512
|
-
});
|
|
513
|
-
return;
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
_logger({ req, res }, next) {
|
|
517
|
-
const diffTime = (hrtime) => {
|
|
518
|
-
const MS = 1000;
|
|
519
|
-
if (hrtime == null)
|
|
520
|
-
return 0;
|
|
521
|
-
const [start, end] = process.hrtime(hrtime);
|
|
522
|
-
const time = +(((start * MS) + (end / 1e6)).toFixed(2));
|
|
523
|
-
return `${time > MS ? `${time / MS} s` : `${time} ms`}`;
|
|
524
|
-
};
|
|
525
|
-
const statusCode = (res) => {
|
|
526
|
-
const statusCode = res.statusCode == null ? 500 : Number(res.statusCode);
|
|
527
|
-
return statusCode < 400
|
|
528
|
-
? `\x1b[32m${statusCode}\x1b[0m`
|
|
529
|
-
: `\x1b[31m${statusCode}\x1b[0m`;
|
|
530
|
-
};
|
|
531
|
-
const startTime = process.hrtime();
|
|
532
|
-
(0, on_finished_1.default)(res, () => {
|
|
533
|
-
console.log([
|
|
534
|
-
`[\x1b[1m\x1b[34mINFO\x1b[0m]`,
|
|
535
|
-
`\x1b[34m${new Date().toJSON()}\x1b[0m`,
|
|
536
|
-
`\x1b[33m${req.method}\x1b[0m`,
|
|
537
|
-
`${decodeURIComponent(String(req.url))}`,
|
|
538
|
-
`${statusCode(res)}`,
|
|
539
|
-
`${diffTime(startTime)}`,
|
|
540
|
-
].join(" "));
|
|
541
|
-
});
|
|
542
|
-
return next();
|
|
555
|
+
}
|
|
556
|
+
return;
|
|
543
557
|
}
|
|
544
558
|
_import(dir, pattern) {
|
|
545
559
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -560,6 +574,7 @@ class Application {
|
|
|
560
574
|
}
|
|
561
575
|
_registerControllers() {
|
|
562
576
|
return __awaiter(this, void 0, void 0, function* () {
|
|
577
|
+
var _a, _b, _c, _d, _e, _f;
|
|
563
578
|
if (this._controllers == null)
|
|
564
579
|
return;
|
|
565
580
|
if (!Array.isArray(this._controllers)) {
|
|
@@ -568,40 +583,40 @@ class Application {
|
|
|
568
583
|
const response = yield Promise.resolve(`${file}`).then(s => __importStar(require(s)));
|
|
569
584
|
const controller = response === null || response === void 0 ? void 0 : response.default;
|
|
570
585
|
const controllerInstance = new controller();
|
|
571
|
-
const prefixPath = Reflect.getMetadata("controllers", controller);
|
|
572
|
-
const routers = Reflect.getMetadata("routers", controller);
|
|
586
|
+
const prefixPath = (_a = Reflect.getMetadata("controllers", controller)) !== null && _a !== void 0 ? _a : '';
|
|
587
|
+
const routers = (_b = Reflect.getMetadata("routers", controller)) !== null && _b !== void 0 ? _b : [];
|
|
588
|
+
const swaggers = (_c = Reflect.getMetadata("swaggers", controller)) !== null && _c !== void 0 ? _c : [];
|
|
573
589
|
if (prefixPath == null)
|
|
574
590
|
continue;
|
|
575
|
-
for (const { method, path, handler } of routers) {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
this[method](normalizePath, this._wrapResponse(controllerInstance[String(handler)].bind(controllerInstance)));
|
|
591
|
+
for (const { method, path, handler } of Array.from(routers)) {
|
|
592
|
+
const find = Array.from(swaggers).find(s => s.handler === handler);
|
|
593
|
+
if (find != null) {
|
|
594
|
+
this._swaggerAdditional = [
|
|
595
|
+
...this._swaggerAdditional,
|
|
596
|
+
Object.assign(Object.assign({}, find), { path: this._normalizePath(this._globalPrefix, prefixPath, path), method })
|
|
597
|
+
];
|
|
598
|
+
}
|
|
599
|
+
this[method](this._normalizePath(this._globalPrefix, prefixPath, path), this._wrapResponse(controllerInstance[String(handler)].bind(controllerInstance)));
|
|
585
600
|
}
|
|
586
601
|
}
|
|
587
602
|
return;
|
|
588
603
|
}
|
|
589
604
|
for (const controller of this._controllers) {
|
|
590
605
|
const controllerInstance = new controller();
|
|
591
|
-
const prefixPath = Reflect.getMetadata("controllers", controller);
|
|
592
|
-
const routers = Reflect.getMetadata("routers", controller);
|
|
606
|
+
const prefixPath = (_d = Reflect.getMetadata("controllers", controller)) !== null && _d !== void 0 ? _d : '';
|
|
607
|
+
const routers = (_e = Reflect.getMetadata("routers", controller)) !== null && _e !== void 0 ? _e : [];
|
|
608
|
+
const swaggers = (_f = Reflect.getMetadata("swaggers", controller)) !== null && _f !== void 0 ? _f : [];
|
|
593
609
|
if (prefixPath == null)
|
|
594
610
|
continue;
|
|
595
|
-
for (const { method, path, handler } of routers) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
this[method](normalizePath, this._wrapResponse(controllerInstance[String(handler)].bind(controllerInstance)));
|
|
611
|
+
for (const { method, path, handler } of Array.from(routers)) {
|
|
612
|
+
const find = Array.from(swaggers).find(s => s.handler === handler);
|
|
613
|
+
if (find != null) {
|
|
614
|
+
this._swaggerAdditional = [
|
|
615
|
+
...this._swaggerAdditional,
|
|
616
|
+
Object.assign(Object.assign({}, find), { path: this._normalizePath(this._globalPrefix, prefixPath, path), method })
|
|
617
|
+
];
|
|
618
|
+
}
|
|
619
|
+
this[method](this._normalizePath(this._globalPrefix, prefixPath, path), this._wrapResponse(controllerInstance[String(handler)].bind(controllerInstance)));
|
|
605
620
|
}
|
|
606
621
|
}
|
|
607
622
|
});
|
|
@@ -626,28 +641,6 @@ class Application {
|
|
|
626
641
|
return;
|
|
627
642
|
});
|
|
628
643
|
}
|
|
629
|
-
_cookiesParser(req) {
|
|
630
|
-
var _a;
|
|
631
|
-
const cookies = {};
|
|
632
|
-
const cookieString = (_a = req.headers) === null || _a === void 0 ? void 0 : _a.cookie;
|
|
633
|
-
if (cookieString == null)
|
|
634
|
-
return null;
|
|
635
|
-
for (const cookie of cookieString.split(';')) {
|
|
636
|
-
const [name, value] = cookie.split('=').map(v => v.trim());
|
|
637
|
-
cookies[name] = decodeURIComponent(value);
|
|
638
|
-
}
|
|
639
|
-
for (const name of Object.keys(cookies)) {
|
|
640
|
-
const cookie = cookies[name];
|
|
641
|
-
if (!cookie.startsWith('Expires='))
|
|
642
|
-
continue;
|
|
643
|
-
const expiresString = cookie.replace('Expires=', '');
|
|
644
|
-
const expiresDate = new Date(expiresString);
|
|
645
|
-
if (isNaN(expiresDate.getTime()) || expiresDate < new Date()) {
|
|
646
|
-
delete cookies[name];
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
return cookies;
|
|
650
|
-
}
|
|
651
644
|
_customizeResponse(req, res) {
|
|
652
645
|
const response = res;
|
|
653
646
|
response.json = (results) => {
|
|
@@ -675,6 +668,10 @@ class Application {
|
|
|
675
668
|
res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
|
|
676
669
|
return res.end(results);
|
|
677
670
|
};
|
|
671
|
+
response.html = (results) => {
|
|
672
|
+
res.writeHead(res.statusCode, { 'Content-Type': 'text/html' });
|
|
673
|
+
return res.end(results);
|
|
674
|
+
};
|
|
678
675
|
response.error = (err) => {
|
|
679
676
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
680
677
|
let code = +((_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code) ||
|
|
@@ -805,6 +802,7 @@ class Application {
|
|
|
805
802
|
return response;
|
|
806
803
|
}
|
|
807
804
|
_nextFunction(ctx) {
|
|
805
|
+
const NEXT_MESSAGE = "The 'next' function does not have any subsequent function.";
|
|
808
806
|
return (err) => __awaiter(this, void 0, void 0, function* () {
|
|
809
807
|
if (err != null) {
|
|
810
808
|
if (this._errorHandler != null) {
|
|
@@ -821,24 +819,22 @@ class Application {
|
|
|
821
819
|
}, null, 2));
|
|
822
820
|
}
|
|
823
821
|
if (this._errorHandler != null) {
|
|
824
|
-
return this._errorHandler(new Error(
|
|
822
|
+
return this._errorHandler(new Error(NEXT_MESSAGE), ctx);
|
|
825
823
|
}
|
|
826
824
|
ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
827
825
|
if (this._formatResponse != null) {
|
|
828
826
|
return ctx.res.end(JSON.stringify(this._formatResponse({
|
|
829
|
-
message:
|
|
827
|
+
message: NEXT_MESSAGE
|
|
830
828
|
}, ctx.res.statusCode), null, 2));
|
|
831
829
|
}
|
|
832
830
|
return ctx.res.end(JSON.stringify({
|
|
833
|
-
message:
|
|
831
|
+
message: NEXT_MESSAGE
|
|
834
832
|
}, null, 2));
|
|
835
833
|
});
|
|
836
834
|
}
|
|
837
835
|
_wrapResponse(handler) {
|
|
838
836
|
return (ctx, next) => __awaiter(this, void 0, void 0, function* () {
|
|
839
837
|
const result = yield handler(ctx, next);
|
|
840
|
-
if (result == null)
|
|
841
|
-
return;
|
|
842
838
|
if (result instanceof http_1.ServerResponse)
|
|
843
839
|
return;
|
|
844
840
|
if (typeof result === 'string') {
|
|
@@ -858,11 +854,17 @@ class Application {
|
|
|
858
854
|
if (!ctx.res.headersSent) {
|
|
859
855
|
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
860
856
|
}
|
|
857
|
+
if (Array.isArray(result)) {
|
|
858
|
+
return ctx.res.end(JSON.stringify(this._formatResponse(result)));
|
|
859
|
+
}
|
|
861
860
|
return ctx.res.end(JSON.stringify(this._formatResponse(Object.assign({}, result), ctx.res.statusCode), null, 2));
|
|
862
861
|
}
|
|
863
862
|
if (!ctx.res.headersSent) {
|
|
864
863
|
ctx.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
865
864
|
}
|
|
865
|
+
if (Array.isArray(result)) {
|
|
866
|
+
return ctx.res.end(JSON.stringify(result));
|
|
867
|
+
}
|
|
866
868
|
return ctx.res.end(JSON.stringify(Object.assign({}, result), null, 2));
|
|
867
869
|
});
|
|
868
870
|
}
|
|
@@ -873,9 +875,35 @@ class Application {
|
|
|
873
875
|
const server = http_1.default.createServer((req, res) => {
|
|
874
876
|
return this._router.lookup(req, res);
|
|
875
877
|
});
|
|
878
|
+
server.keepAliveTimeout = 1000 * 120;
|
|
879
|
+
server.requestTimeout = 1000 * 120;
|
|
876
880
|
return server;
|
|
877
881
|
});
|
|
878
882
|
}
|
|
883
|
+
_normalizePath(...paths) {
|
|
884
|
+
const path = paths
|
|
885
|
+
.join('/')
|
|
886
|
+
.replace(/\/+/g, '/')
|
|
887
|
+
.replace(/\/+$/, '');
|
|
888
|
+
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
|
889
|
+
return /\/api\/api/.test(normalizedPath) ? normalizedPath.replace(/\/api\/api\//, "/api/") : normalizedPath;
|
|
890
|
+
}
|
|
891
|
+
_swaggerHandler() {
|
|
892
|
+
const routes = this.routers
|
|
893
|
+
.routes.filter(r => ["GET", "POST", "PUT", "PATCH", "DELETE"].includes(r.method));
|
|
894
|
+
const { path, html, staticSwaggerHandler, staticUrl } = this._parser.swagger(Object.assign(Object.assign({}, this._swagger), { options: this._swaggerAdditional, routes }));
|
|
895
|
+
this._router.get(staticUrl, staticSwaggerHandler);
|
|
896
|
+
this._router.get(String(path), (req, res) => {
|
|
897
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
898
|
+
res.write(html);
|
|
899
|
+
return res.end();
|
|
900
|
+
});
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
exports.Spear = Spear;
|
|
905
|
+
class Application extends Spear {
|
|
879
906
|
}
|
|
880
907
|
exports.Application = Application;
|
|
881
|
-
exports.default =
|
|
908
|
+
exports.default = Spear;
|
|
909
|
+
//# sourceMappingURL=index.js.map
|