tspace-spear 1.0.1 → 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/README.md CHANGED
@@ -3,7 +3,8 @@
3
3
  [![NPM version](https://img.shields.io/npm/v/tspace-spear.svg)](https://www.npmjs.com)
4
4
  [![NPM downloads](https://img.shields.io/npm/dm/tspace-spear.svg)](https://www.npmjs.com)
5
5
 
6
- tspace-spear is a lightweight API framework for Node.js that is fast and highly focused on providing the best developer experience. It utilizes the native HTTP server.
6
+ tspace-spear is a lightweight API framework for Node.js that is fast and highly focused on providing the best developer experience.
7
+ It utilizes the native HTTP server.
7
8
 
8
9
  ## Install
9
10
 
@@ -16,6 +17,7 @@ npm install tspace-spear --save
16
17
  ## Basic Usage
17
18
  - [StartServer](#start-server)
18
19
  - [CRUD](#crud)
20
+ - [Cluster](#cluster)
19
21
  - [Middleware](#middleware)
20
22
  - [Controller](#controller)
21
23
  - [Router](#router)
@@ -103,6 +105,27 @@ new Spear()
103
105
  )
104
106
  ```
105
107
 
108
+ ## Cluster
109
+ ```js
110
+ import Spear from "tspace-spear";
111
+ new Spear({
112
+ cluster : {
113
+ use : true,
114
+ maxWorkers : 3
115
+ }
116
+ })
117
+ .get('/' , () => 'Hello world!')
118
+ .get('/json' , () => {
119
+ return {
120
+ message : 'Hello world!'
121
+ }
122
+ })
123
+ .listen(3000 , ({ server, port }) =>
124
+ console.log(`server listening on : http://localhost:${port}`)
125
+ )
126
+
127
+ ```
128
+
106
129
  ## Middleware
107
130
  ```js
108
131
  // file cat-middleware.ts
@@ -511,6 +534,11 @@ const app = new Spear({
511
534
  logger : true, // logging
512
535
  globalPrefix : '/api' // prefix all routes
513
536
  })
537
+ // or use this for logging
538
+ app.useLogger({
539
+ methods : ['GET','POST'],
540
+ exceptPath : ['/']
541
+ })
514
542
 
515
543
  app.enableCors({
516
544
  origins: [
@@ -82,7 +82,7 @@ const Cookies = (...cookiesParms) => {
82
82
  var _a;
83
83
  const q = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.cookies) !== null && _a !== void 0 ? _a : {};
84
84
  const cookies = cookiesParms.reduce((acc, key) => (q[key] != null ? Object.assign(Object.assign({}, acc), { [key]: q[key] }) : acc), {});
85
- ctx.cookies = Object.keys(cookies).length ? cookies : null;
85
+ ctx.cookies = Object.keys(cookies).length ? cookies : {};
86
86
  return yield originalMethod.call(this, ctx, next);
87
87
  });
88
88
  };
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/lib/core/decorators/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/lib/core/decorators/context.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEO,MAAM,IAAI,GAAG,CAAC,GAAG,SAAoB,EAAE,EAAE;IAC5C,OAAO,UAAS,MAAW,EAAE,GAAW,EAAE,UAA8B;QACpE,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,UAAU,CAAC,KAAK,GAAG,UAAe,GAAc,EAAG,IAAmB;;;gBAClE,MAAM,CAAC,GAAG,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,IAAI,mCAAI,EAAE,CAAA;gBACzB,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,iCAAM,GAAG,KAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAG,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;gBACnG,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;gBAE/C,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAG,IAAI,CAAC,CAAC;YACvD,CAAC;SAAA,CAAC;QAEF,OAAO,UAAU,CAAC;IACtB,CAAC,CAAC;AACN,CAAC,CAAA;AAdY,QAAA,IAAI,QAchB;AAEM,MAAM,KAAK,GAAG,CAAC,GAAG,UAAqB,EAAE,EAAE;IAC9C,OAAO,UAAS,MAAW,EAAE,GAAW,EAAE,UAA8B;QACpE,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,UAAU,CAAC,KAAK,GAAG,UAAe,GAAc,EAAG,IAAmB;;;gBAClE,MAAM,CAAC,GAAG,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,mCAAI,EAAE,CAAA;gBAC1B,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,iCAAM,GAAG,KAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAG,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;gBACrG,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;gBAElD,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAG,IAAI,CAAC,CAAC;YACvD,CAAC;SAAA,CAAC;QAEF,OAAO,UAAU,CAAC;IACtB,CAAC,CAAC;AACN,CAAC,CAAA;AAdY,QAAA,KAAK,SAcjB;AAEM,MAAM,MAAM,GAAG,CAAC,GAAG,UAAqB,EAAE,EAAE;IAC/C,OAAO,UAAS,MAAW,EAAE,GAAW,EAAE,UAA8B;QACpE,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,UAAU,CAAC,KAAK,GAAG,UAAe,GAAc,EAAG,IAAmB;;;gBAClE,MAAM,CAAC,GAAG,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,MAAM,mCAAI,EAAE,CAAA;gBAC3B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,iCAAM,GAAG,KAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAG,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;gBACtG,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;gBAErD,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAG,IAAI,CAAC,CAAC;YACvD,CAAC;SAAA,CAAC;QAEF,OAAO,UAAU,CAAC;IACtB,CAAC,CAAC;AACN,CAAC,CAAA;AAdY,QAAA,MAAM,UAclB;AAEM,MAAM,KAAK,GAAG,CAAC,GAAG,UAAqB,EAAE,EAAE;IAC9C,OAAO,UAAS,MAAW,EAAE,GAAW,EAAE,UAA8B;QACpE,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,UAAU,CAAC,KAAK,GAAG,UAAe,GAAc,EAAG,IAAmB;;;gBAClE,MAAM,CAAC,GAAG,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,KAAK,mCAAI,EAAE,CAAA;gBAC1B,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,iCAAM,GAAG,KAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAG,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;gBACrG,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;gBAElD,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAG,IAAI,CAAC,CAAC;YACvD,CAAC;SAAA,CAAC;QAEF,OAAO,UAAU,CAAC;IACtB,CAAC,CAAC;AACN,CAAC,CAAA;AAdY,QAAA,KAAK,SAcjB;AAGM,MAAM,OAAO,GAAG,CAAC,GAAG,YAAuB,EAAE,EAAE;IAClD,OAAO,UAAS,MAAW,EAAE,GAAW,EAAE,UAA8B;QACpE,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QAExC,UAAU,CAAC,KAAK,GAAG,UAAe,GAAc,EAAG,IAAmB;;;gBAClE,MAAM,CAAC,GAAG,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,mCAAI,EAAE,CAAA;gBAC5B,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,iCAAM,GAAG,KAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAG,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;gBACzG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;gBAExD,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAG,IAAI,CAAC,CAAC;YACvD,CAAC;SAAA,CAAC;QAEF,OAAO,UAAU,CAAC;IACtB,CAAC,CAAC;AACN,CAAC,CAAA;AAdY,QAAA,OAAO,WAcnB"}
@@ -1,13 +1,14 @@
1
- import findMyWayRouter from 'find-my-way';
2
1
  import { Server, ServerResponse } from 'http';
3
- import { Router, TContext, TNextFunction, TApplication } from '../..';
2
+ import findMyWayRouter from 'find-my-way';
3
+ import { Router } from './router';
4
+ import type { TContext, TNextFunction, TApplication } from '../types';
4
5
  /**
5
6
  *
6
7
  * The 'Spear' class is used to create a server and handle HTTP requests.
7
8
  *
8
9
  * @returns {Spear} application
9
10
  * @example
10
- * new Application()
11
+ * new Spear()
11
12
  * .get('/' , () => 'Hello world!')
12
13
  * .get('/json' , () => {
13
14
  * return {
@@ -21,6 +22,7 @@ declare class Spear {
21
22
  private readonly _controllers?;
22
23
  private readonly _middlewares?;
23
24
  private readonly _globalPrefix;
25
+ private readonly _cluster?;
24
26
  private readonly _router;
25
27
  private readonly _parser;
26
28
  private _swagger;
@@ -30,30 +32,30 @@ declare class Spear {
30
32
  private _formatResponse;
31
33
  private _onListeners;
32
34
  private _fileUploadOptions;
33
- constructor({ controllers, middlewares, globalPrefix, logger }?: TApplication);
35
+ constructor({ controllers, middlewares, globalPrefix, logger, cluster }?: TApplication);
34
36
  get instance(): this;
35
37
  get routers(): findMyWayRouter.Instance<findMyWayRouter.HTTPVersion.V1>;
36
38
  /**
37
- * The 'enableCors' is used to enable the cors origins on the server.
39
+ * The 'use' method is used to add the middleware into the request pipeline.
38
40
  *
39
- * @params {Object}
40
- * @property {(string | RegExp)[]} origins
41
- * @property {boolean} credentials
42
- * @returns
41
+ * @callback {Function} middleware
42
+ * @property {Object} ctx - context { req , res , query , params , cookies , files , body}
43
+ * @property {Function} next - go to next function
44
+ * @returns {this}
43
45
  */
44
- enableCors({ origins, credentials }?: {
45
- origins?: (string | RegExp)[];
46
- credentials?: boolean;
47
- }): this;
46
+ use(middleware: (ctx: TContext, next: TNextFunction) => void): this;
48
47
  /**
49
- * The 'use' method is used to add the middleware into the request pipeline.
48
+ * The 'useLogger' method is used to add the middleware view logger response.
50
49
  *
51
50
  * @callback {Function} middleware
52
51
  * @property {Object} ctx - context { req , res , query , params , cookies , files , body}
53
52
  * @property {Function} next - go to next function
54
53
  * @returns {this}
55
54
  */
56
- use(middleware: (ctx: TContext, next: TNextFunction) => void): this;
55
+ useLogger({ methods, exceptPath }?: {
56
+ methods?: ('GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE')[];
57
+ exceptPath?: string[] | RegExp;
58
+ }): this;
57
59
  /**
58
60
  * The 'useBodyParser' method is a middleware used to parse the request body of incoming HTTP requests.
59
61
  *
@@ -116,6 +118,29 @@ declare class Spear {
116
118
  version?: string;
117
119
  };
118
120
  }): this;
121
+ /**
122
+ * The 'listen' method is used to bind and start a server to a particular port and optionally a hostname.
123
+ *
124
+ * @param {number} port
125
+ * @param {function} callback
126
+ * @returns
127
+ */
128
+ listen(port: (number | (() => ServerResponse)) | undefined, callback: (callback: {
129
+ server: Server;
130
+ port: number;
131
+ }) => void): Promise<void>;
132
+ /**
133
+ * The 'enableCors' is used to enable the cors origins on the server.
134
+ *
135
+ * @params {Object}
136
+ * @property {(string | RegExp)[]} origins
137
+ * @property {boolean} credentials
138
+ * @returns
139
+ */
140
+ enableCors({ origins, credentials }?: {
141
+ origins?: (string | RegExp)[];
142
+ credentials?: boolean;
143
+ }): this;
119
144
  /**
120
145
  * The 'formatResponse' method is used to format the response
121
146
  *
@@ -124,7 +149,9 @@ declare class Spear {
124
149
  */
125
150
  formatResponse(format: (r: unknown, statusCode: number) => any): this;
126
151
  /**
127
- * The 'errorHandler' method is middleware that is specifically designed to handle errors that occur during the processing of requests
152
+ * The 'errorHandler' method is middleware that is specifically designed to handle errors.
153
+ *
154
+ * that occur during the processing of requests
128
155
  *
129
156
  * @param {function} error
130
157
  * @returns
@@ -188,7 +215,7 @@ declare class Spear {
188
215
  */
189
216
  delete(path: string, ...handlers: ((ctx: TContext, next: TNextFunction) => any)[]): this;
190
217
  /**
191
- * The 'all' method is used to add the request handler to the router for the 'all' method.
218
+ * The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' methods.
192
219
  *
193
220
  * @param {string} path
194
221
  * @callback {...Function[]} handlers of the middlewares
@@ -197,18 +224,7 @@ declare class Spear {
197
224
  * @returns {this}
198
225
  */
199
226
  all(path: string, ...handlers: ((ctx: TContext, next: TNextFunction) => any)[]): this;
200
- /**
201
- * The 'listen' method is used to bind and start a server to a particular port and optionally a hostname.
202
- *
203
- * @param {number} port
204
- * @param {function} cb
205
- * @returns
206
- */
207
- listen(port: (number | (() => ServerResponse)) | undefined, cb: (callback: {
208
- server: Server;
209
- port: number;
210
- }) => void): Promise<void>;
211
- private _logger;
227
+ private _clusterMode;
212
228
  private _import;
213
229
  private _registerControllers;
214
230
  private _registerMiddlewares;
@@ -218,8 +234,9 @@ declare class Spear {
218
234
  private _wrapResponse;
219
235
  private _createServer;
220
236
  private _normalizePath;
237
+ private _swaggerHandler;
221
238
  }
222
- export { Spear };
223
239
  export declare class Application extends Spear {
224
240
  }
241
+ export { Spear };
225
242
  export default Spear;
@@ -35,13 +35,15 @@ 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 = exports.Spear = 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
43
  const url_1 = require("url");
43
44
  const on_finished_1 = __importDefault(require("on-finished"));
44
45
  const http_1 = __importStar(require("http"));
46
+ const find_my_way_1 = __importDefault(require("find-my-way"));
45
47
  const parser_factory_1 = require("./parser-factory");
46
48
  /**
47
49
  *
@@ -49,7 +51,7 @@ const parser_factory_1 = require("./parser-factory");
49
51
  *
50
52
  * @returns {Spear} application
51
53
  * @example
52
- * new Application()
54
+ * new Spear()
53
55
  * .get('/' , () => 'Hello world!')
54
56
  * .get('/json' , () => {
55
57
  * return {
@@ -60,7 +62,7 @@ const parser_factory_1 = require("./parser-factory");
60
62
  *
61
63
  */
62
64
  class Spear {
63
- constructor({ controllers, middlewares, globalPrefix, logger } = {}) {
65
+ constructor({ controllers, middlewares, globalPrefix, logger, cluster } = {}) {
64
66
  this._router = (0, find_my_way_1.default)();
65
67
  this._parser = new parser_factory_1.ParserFactory();
66
68
  this._swagger = {
@@ -140,7 +142,8 @@ class Spear {
140
142
  });
141
143
  };
142
144
  if (logger)
143
- this._onListeners.push(() => this.use(this._logger));
145
+ this.useLogger();
146
+ this._cluster = cluster;
144
147
  this._controllers = controllers;
145
148
  this._middlewares = middlewares;
146
149
  this._globalPrefix = globalPrefix == null ? '' : globalPrefix;
@@ -152,46 +155,63 @@ class Spear {
152
155
  return this._router;
153
156
  }
154
157
  /**
155
- * The 'enableCors' is used to enable the cors origins on the server.
158
+ * The 'use' method is used to add the middleware into the request pipeline.
156
159
  *
157
- * @params {Object}
158
- * @property {(string | RegExp)[]} origins
159
- * @property {boolean} credentials
160
- * @returns
160
+ * @callback {Function} middleware
161
+ * @property {Object} ctx - context { req , res , query , params , cookies , files , body}
162
+ * @property {Function} next - go to next function
163
+ * @returns {this}
161
164
  */
162
- enableCors({ origins, credentials } = {}) {
163
- this._globalMiddlewares.push(({ req, res }, next) => {
164
- var _a;
165
- const origin = (_a = req.headers) === null || _a === void 0 ? void 0 : _a.origin;
166
- if (origin == null)
167
- return next();
168
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
169
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
170
- if (origins == null) {
171
- res.setHeader('Access-Control-Allow-Origin', '*');
172
- }
173
- if (Array.isArray(origins) && origins.length) {
174
- if (origins.includes(origin)) {
175
- res.setHeader('Access-Control-Allow-Origin', origin);
176
- }
177
- }
178
- if (credentials) {
179
- res.setHeader('Access-Control-Allow-Credentials', 'true');
180
- }
181
- return next();
182
- });
165
+ use(middleware) {
166
+ this._globalMiddlewares.push(middleware);
183
167
  return this;
184
168
  }
185
169
  /**
186
- * The 'use' method is used to add the middleware into the request pipeline.
170
+ * The 'useLogger' method is used to add the middleware view logger response.
187
171
  *
188
172
  * @callback {Function} middleware
189
173
  * @property {Object} ctx - context { req , res , query , params , cookies , files , body}
190
174
  * @property {Function} next - go to next function
191
175
  * @returns {this}
192
176
  */
193
- use(middleware) {
194
- this._globalMiddlewares.push(middleware);
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
+ });
195
215
  return this;
196
216
  }
197
217
  /**
@@ -264,10 +284,8 @@ class Spear {
264
284
  this._globalMiddlewares.push((_a, next_1) => __awaiter(this, [_a, next_1], void 0, function* ({ req }, next) {
265
285
  const contentType = req === null || req === void 0 ? void 0 : req.headers['content-type'];
266
286
  const isFileUpload = contentType && contentType.startsWith('multipart/form-data');
267
- const isListMethods = ['POST', 'PATCH', 'PUT'].includes(String(req.method));
268
- if (!isListMethods)
269
- return next();
270
- if (!isFileUpload)
287
+ const isListMethods = ['POST', 'PATCH', 'PUT', 'DELETE'].includes(String(req.method));
288
+ if (!isListMethods || !isFileUpload)
271
289
  return next();
272
290
  if ((req === null || req === void 0 ? void 0 : req._filesParser) != null)
273
291
  return next();
@@ -298,6 +316,74 @@ class Spear {
298
316
  };
299
317
  return this;
300
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
+ }
301
387
  /**
302
388
  * The 'formatResponse' method is used to format the response
303
389
  *
@@ -309,7 +395,9 @@ class Spear {
309
395
  return this;
310
396
  }
311
397
  /**
312
- * The 'errorHandler' method is middleware that is specifically designed to handle errors that occur during the processing of requests
398
+ * The 'errorHandler' method is middleware that is specifically designed to handle errors.
399
+ *
400
+ * that occur during the processing of requests
313
401
  *
314
402
  * @param {function} error
315
403
  * @returns
@@ -418,7 +506,7 @@ class Spear {
418
506
  return this;
419
507
  }
420
508
  /**
421
- * The 'all' method is used to add the request handler to the router for the 'all' method.
509
+ * The 'all' method is used to add the request handler to the router for 'GET' 'POST' 'PUT' 'PATCH' 'DELETE' methods.
422
510
  *
423
511
  * @param {string} path
424
512
  * @callback {...Function[]} handlers of the middlewares
@@ -432,73 +520,40 @@ class Spear {
432
520
  });
433
521
  return this;
434
522
  }
435
- /**
436
- * The 'listen' method is used to bind and start a server to a particular port and optionally a hostname.
437
- *
438
- * @param {number} port
439
- * @param {function} cb
440
- * @returns
441
- */
442
- listen() {
443
- var arguments_1 = arguments;
444
- return __awaiter(this, arguments, void 0, function* (port = 3000, cb) {
445
- if (arguments_1.length === 1 && typeof port === 'function') {
446
- cb = port;
447
- 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();
448
534
  }
449
- const server = yield this._createServer();
535
+ cluster_1.default.on('exit', () => {
536
+ cluster_1.default.fork();
537
+ });
538
+ }
539
+ if (cluster_1.default.isWorker) {
450
540
  server.listen(port == null ? 3000 : port, () => {
451
- if (cb)
452
- cb({ server, port });
541
+ if (callback) {
542
+ callback({ server, port });
543
+ }
453
544
  });
454
545
  server.on('listening', () => {
455
546
  this._onListeners.forEach(listener => listener());
456
547
  if (this._swagger.use) {
457
- const routes = this.routers
458
- .routes.filter(r => ["GET", "POST", "PUT", "PATCH", "DELETE"].includes(r.method));
459
- const { path, html, staticSwaggerHandler, staticUrl } = this._parser.swagger(Object.assign(Object.assign({}, this._swagger), { options: this._swaggerAdditional, routes }));
460
- this.routers.get(staticUrl, staticSwaggerHandler);
461
- this.routers.get(String(path), (req, res) => {
462
- res.writeHead(200, { 'Content-Type': 'text/html' });
463
- res.write(html);
464
- return res.end();
465
- });
548
+ this._swaggerHandler();
466
549
  }
467
550
  });
468
551
  server.on('error', (_) => {
469
552
  port = Math.floor(Math.random() * 8999) + 1000;
470
553
  server.listen(port);
471
554
  });
472
- return;
473
- });
474
- }
475
- _logger({ req, res }, next) {
476
- const diffTime = (hrtime) => {
477
- const MS = 1000;
478
- if (hrtime == null)
479
- return 0;
480
- const [start, end] = process.hrtime(hrtime);
481
- const time = +(((start * MS) + (end / 1e6)).toFixed(2));
482
- return `${time > MS ? `${time / MS} s` : `${time} ms`}`;
483
- };
484
- const statusCode = (res) => {
485
- const statusCode = res.statusCode == null ? 500 : Number(res.statusCode);
486
- return statusCode < 400
487
- ? `\x1b[32m${statusCode}\x1b[0m`
488
- : `\x1b[31m${statusCode}\x1b[0m`;
489
- };
490
- const startTime = process.hrtime();
491
- (0, on_finished_1.default)(res, () => {
492
- console.log([
493
- `[\x1b[1m\x1b[34mINFO\x1b[0m]`,
494
- `\x1b[34m${new Date().toJSON()}\x1b[0m`,
495
- `\x1b[33m${req.method}\x1b[0m`,
496
- `${decodeURIComponent(String(req.url))}`,
497
- `${statusCode(res)}`,
498
- `${diffTime(startTime)}`,
499
- ].join(" "));
500
- });
501
- return next();
555
+ }
556
+ return;
502
557
  }
503
558
  _import(dir, pattern) {
504
559
  return __awaiter(this, void 0, void 0, function* () {
@@ -613,6 +668,10 @@ class Spear {
613
668
  res.writeHead(res.statusCode, { 'Content-Type': 'text/plain' });
614
669
  return res.end(results);
615
670
  };
671
+ response.html = (results) => {
672
+ res.writeHead(res.statusCode, { 'Content-Type': 'text/html' });
673
+ return res.end(results);
674
+ };
616
675
  response.error = (err) => {
617
676
  var _a, _b, _c, _d, _e, _f, _g, _h;
618
677
  let code = +((_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code) ||
@@ -743,6 +802,7 @@ class Spear {
743
802
  return response;
744
803
  }
745
804
  _nextFunction(ctx) {
805
+ const NEXT_MESSAGE = "The 'next' function does not have any subsequent function.";
746
806
  return (err) => __awaiter(this, void 0, void 0, function* () {
747
807
  if (err != null) {
748
808
  if (this._errorHandler != null) {
@@ -759,16 +819,16 @@ class Spear {
759
819
  }, null, 2));
760
820
  }
761
821
  if (this._errorHandler != null) {
762
- return this._errorHandler(new Error(`The 'next' function does not have any subsequent function.`), ctx);
822
+ return this._errorHandler(new Error(NEXT_MESSAGE), ctx);
763
823
  }
764
824
  ctx.res.writeHead(500, { 'Content-Type': 'application/json' });
765
825
  if (this._formatResponse != null) {
766
826
  return ctx.res.end(JSON.stringify(this._formatResponse({
767
- message: `The 'next' function does not have any subsequent function.`
827
+ message: NEXT_MESSAGE
768
828
  }, ctx.res.statusCode), null, 2));
769
829
  }
770
830
  return ctx.res.end(JSON.stringify({
771
- message: `The 'next' function does not have any subsequent function.`
831
+ message: NEXT_MESSAGE
772
832
  }, null, 2));
773
833
  });
774
834
  }
@@ -815,6 +875,8 @@ class Spear {
815
875
  const server = http_1.default.createServer((req, res) => {
816
876
  return this._router.lookup(req, res);
817
877
  });
878
+ server.keepAliveTimeout = 1000 * 120;
879
+ server.requestTimeout = 1000 * 120;
818
880
  return server;
819
881
  });
820
882
  }
@@ -826,6 +888,18 @@ class Spear {
826
888
  const normalizedPath = path.startsWith('/') ? path : `/${path}`;
827
889
  return /\/api\/api/.test(normalizedPath) ? normalizedPath.replace(/\/api\/api\//, "/api/") : normalizedPath;
828
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
+ }
829
903
  }
830
904
  exports.Spear = Spear;
831
905
  class Application extends Spear {