From 4de4dc0cd6dbb6d4463fb8d5e3aa5b408e865e96 Mon Sep 17 00:00:00 2001 From: "Mr.MKZ" Date: Sun, 17 Nov 2024 00:25:15 +0330 Subject: [PATCH 1/2] feat(cors): CORS handler core added. feat(cors): Now AxonCore can handle preflight requests and default cors configs but custom cors config will add soon. --- package-lock.json | 38 ++++++- package.json | 6 +- src/core/AxonCore.ts | 46 ++++---- src/core/AxonCors.ts | 250 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 316 insertions(+), 24 deletions(-) create mode 100644 src/core/AxonCors.ts diff --git a/package-lock.json b/package-lock.json index f7f2500..769fe08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,26 @@ { "name": "@mr-mkz/axon", - "version": "0.2.2-1", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mr-mkz/axon", - "version": "0.2.2-1", + "version": "0.3.0", "license": "ISC", "dependencies": { "@spacingbat3/kolor": "^4.0.0", "@types/node": "^22.5.4", "moment": "^2.30.1", + "object-assign": "^4.1.1", "pino": "^9.4.0", - "pino-pretty": "^11.2.2" + "pino-pretty": "^11.2.2", + "vary": "^1.1.2" }, "devDependencies": { "@types/jest": "^29.5.12", + "@types/object-assign": "^4.0.33", + "@types/vary": "^1.1.3", "jest": "^29.7.0", "nodemon": "^3.1.4", "path-to-regexp": "^8.1.0", @@ -1934,6 +1938,13 @@ "undici-types": "~6.19.2" } }, + "node_modules/@types/object-assign": { + "version": "4.0.33", + "resolved": "https://registry.npmjs.org/@types/object-assign/-/object-assign-4.0.33.tgz", + "integrity": "sha512-HeuamLPmpVPuJU/oY7z/YGAezy4HFy6mhvzwupi9Xc8n0FKY8tR1/U3AKaOn/I5Mb4dvbw2szSYcXi84eW07TQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -1946,6 +1957,16 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true }, + "node_modules/@types/vary": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/vary/-/vary-1.1.3.tgz", + "integrity": "sha512-XJT8/ZQCL7NUut9QDLf6l24JfAEl7bnNdgxfj50cHIpEPRJLHHDDFOAq6i+GsEmeFfH7NamhBE4c4Thtb2egWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -4708,7 +4729,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6238,6 +6259,15 @@ "node": ">=10.12.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", diff --git a/package.json b/package.json index 8bc16e3..0f003b8 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,8 @@ }, "devDependencies": { "@types/jest": "^29.5.12", + "@types/object-assign": "^4.0.33", + "@types/vary": "^1.1.3", "jest": "^29.7.0", "nodemon": "^3.1.4", "path-to-regexp": "^8.1.0", @@ -55,7 +57,9 @@ "@spacingbat3/kolor": "^4.0.0", "@types/node": "^22.5.4", "moment": "^2.30.1", + "object-assign": "^4.1.1", "pino": "^9.4.0", - "pino-pretty": "^11.2.2" + "pino-pretty": "^11.2.2", + "vary": "^1.1.2" } } diff --git a/src/core/AxonCore.ts b/src/core/AxonCore.ts index e8b2484..67ad7ce 100644 --- a/src/core/AxonCore.ts +++ b/src/core/AxonCore.ts @@ -12,6 +12,7 @@ import { Request, Response, Headers } from ".."; import AxonResponse from "./AxonResponse"; import { PLuginLoader } from "./PluginLoader"; import { AxonPlugin } from "../types/AxonPlugin"; +import AxonCors from "./AxonCors"; const defaultResponses = { notFound: "Not found", @@ -110,6 +111,7 @@ export default class AxonCore { route = `/${route}` this.routes[method][route] = routerRoutes[method][originalRoute] + this.routes['OPTIONS'][route] = routerRoutes[method][originalRoute]; logger.debug(`loaded route ${method} ${route}`) } else { @@ -206,26 +208,32 @@ export default class AxonCore { let controller: Controller = route.getController(); - return await this.handleMiddleware(req, res, async () => { + const axonCors = await AxonCors.middlewareWrapper(); // this function gives custom config. + + // TODO: AxonCors is ready and I need to add cors config to AxonConfing option. + + return this.handleMiddleware(req, res, async () => { return await this.handleMiddleware(req, res, async () => { - await controller(req, res); - - // log incoming requests - if (this.config.LOGGER_VERBOSE) { - logger.request({ - ip: req.socket.remoteAddress, - url: req.url, - method: req.method, - headers: req.headers, - body: req.body, - code: res.statusCode - }, "new http request") - } else { - logger.request(`${req.socket.remoteAddress} - ${req.method} ${req.url} ${res.statusCode} - ${req.headers["user-agent"]}`) - } - - }, middlewares); - }, this.globalMiddlewares); + return await this.handleMiddleware(req, res, async () => { + await controller(req, res); + + // log incoming requests + if (this.config.LOGGER_VERBOSE) { + logger.request({ + ip: req.socket.remoteAddress, + url: req.url, + method: req.method, + headers: req.headers, + body: req.body, + code: res.statusCode + }, "new http request") + } else { + logger.request(`${req.socket.remoteAddress} - ${req.method} ${req.url} ${res.statusCode} - ${req.headers["user-agent"]}`) + } + + }, middlewares); + }, this.globalMiddlewares); + }, [axonCors]); } else { return; diff --git a/src/core/AxonCors.ts b/src/core/AxonCors.ts new file mode 100644 index 0000000..054369a --- /dev/null +++ b/src/core/AxonCors.ts @@ -0,0 +1,250 @@ +import assign from "object-assign"; +import { nextFn, Request, Response } from ".."; +import vary from "vary"; + +const defaults = { + origin: '*', + methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', + preflightContinue: false, + optionsSuccessStatus: 204 +} + +const isString = (s: any) => { + return typeof s === 'string' || s instanceof String; +} + +const isOriginAllowed = async (origin: any, allowedOrigin: any) => { + if (Array.isArray(allowedOrigin)) { + for (var i = 0; i < allowedOrigin.length; ++i) { + if (await isOriginAllowed(origin, allowedOrigin[i])) { + return true; + } + } + return false; + } else if (isString(allowedOrigin)) { + return origin === allowedOrigin; + } else if (allowedOrigin instanceof RegExp) { + return allowedOrigin.test(origin); + } else { + return !!allowedOrigin; + } +} + +const configureOrigin = async (options: any, req: Request) => { + var requestOrigin = req.headers.origin, + headers = [], + isAllowed; + + if (!options.origin || options.origin === '*') { + // allow any origin + headers.push([{ + key: 'Access-Control-Allow-Origin', + value: '*' + }]); + } else if (isString(options.origin)) { + // fixed origin + headers.push([{ + key: 'Access-Control-Allow-Origin', + value: options.origin + }]); + headers.push([{ + key: 'Vary', + value: 'Origin' + }]); + } else { + isAllowed = await isOriginAllowed(requestOrigin, options.origin); + // reflect origin + headers.push([{ + key: 'Access-Control-Allow-Origin', + value: isAllowed ? requestOrigin : false + }]); + headers.push([{ + key: 'Vary', + value: 'Origin' + }]); + } + + return headers; +} + +const configureMethods = async (options: any) => { + var methods = options.methods; + if (methods.join) { + methods = options.methods.join(','); // .methods is an array, so turn it into a string + } + return { + key: 'Access-Control-Allow-Methods', + value: methods + }; +} + +const configureCredentials = async (options: any) => { + if (options.credentials === true) { + return { + key: 'Access-Control-Allow-Credentials', + value: 'true' + }; + } + return null; +} + +const configureAllowedHeaders = async (options: any, req: Request) => { + var allowedHeaders = options.allowedHeaders || options.headers; + var headers = []; + + if (!allowedHeaders) { + allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers + headers.push([{ + key: 'Vary', + value: 'Access-Control-Request-Headers' + }]); + } else if (allowedHeaders.join) { + allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string + } + if (allowedHeaders && allowedHeaders.length) { + headers.push([{ + key: 'Access-Control-Allow-Headers', + value: allowedHeaders + }]); + } + + return headers; +} + +const configureExposedHeaders = async (options: any) => { + var headers = options.exposedHeaders; + if (!headers) { + return null; + } else if (headers.join) { + headers = headers.join(','); // .headers is an array, so turn it into a string + } + if (headers && headers.length) { + return { + key: 'Access-Control-Expose-Headers', + value: headers + }; + } + return null; +} + +const configureMaxAge = async (options: any) => { + var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString() + if (maxAge && maxAge.length) { + return { + key: 'Access-Control-Max-Age', + value: maxAge + }; + } + return null; +} + +const applyHeaders = async (headers: any, res: Response) => { + for (var i = 0, n = headers.length; i < n; i++) { + var header = headers[i]; + if (header) { + if (Array.isArray(header)) { + applyHeaders(header, res); + } else if (header.key === 'Vary' && header.value) { + vary(res, header.value); + } else if (header.value) { + res.setHeader(header.key, header.value); + } + } + } +} + +const cors = async (options: any, req: Request, res: Response, next: nextFn) => { + var headers = [], + method = req.method && req.method.toUpperCase && req.method.toUpperCase(); + + if (method === 'OPTIONS') { + // preflight + headers.push(await configureOrigin(options, req)); + headers.push(await configureCredentials(options)) + headers.push(await configureMethods(options)) + headers.push(await configureAllowedHeaders(options, req)); + headers.push(await configureMaxAge(options)) + headers.push(await configureExposedHeaders(options)) + await applyHeaders(headers, res); + + if (options.preflightContinue) { + await next(); + } else { + // Safari (and potentially other browsers) need content-length 0, + // for 204 or they just hang waiting for a body + res.statusCode = options.optionsSuccessStatus; + res.setHeader('Content-Length', '0'); + res.end(); + } + } else { + // actual response + headers.push(await configureOrigin(options, req)); + headers.push(await configureCredentials(options)) + headers.push(await configureExposedHeaders(options)) + await applyHeaders(headers, res); + await next(); + } +} + +const middlewareWrapper = async (o?: any) => { + // if options are static (either via defaults or custom options passed in), wrap in a function + var optionsCallback: (req: Request, cb: any) => Promise; + if (typeof o === 'function') { + optionsCallback = o; + } else { + optionsCallback = async (req: Request, cb: any) => { + await cb(null, o); + }; + } + + return async (req: Request, res: Response, next: nextFn) => { + await optionsCallback(req, async (err: any, options: any) => { + if (err) { + return res.status(500).body({ + err: err, + meta: { + module: "AxonCors", + root: "optionsCallback", + line: 203 + } + }); + // await next(err); + } else { + var corsOptions = assign({}, defaults, options); + var originCallback = null; + if (corsOptions.origin && typeof corsOptions.origin === 'function') { + originCallback = corsOptions.origin; + } else if (corsOptions.origin) { + originCallback = async (origin: any, cb: any) => { + await cb(null, corsOptions.origin); + }; + } + + if (originCallback) { + await originCallback(req.headers.origin, async (err2: any, origin: any) => { + if (err2 || !origin) { + return res.status(500).body({ + err: err, + meta: { + module: "AxonCors", + root: "optionsCallback", + line: 225 + } + }); + // await next(err2); + } else { + corsOptions.origin = origin; + await cors(corsOptions, req, res, next); + } + }); + } else { + await next(); + } + } + }); + }; +} + +export default { + middlewareWrapper +}; \ No newline at end of file From ed6024f5ad1ee9f0f68b87411b84d960a727d109 Mon Sep 17 00:00:00 2001 From: "Mr.MKZ" Date: Sun, 17 Nov 2024 23:11:51 +0330 Subject: [PATCH 2/2] feat(core): Cors config added to AxonCore config options. docs(readme): Cors config document added to readme. docs(web): web document updated. --- README.md | 3 + docs/assets/navigation.js | 2 +- docs/assets/search.js | 2 +- docs/classes/AxonCore.html | 13 +-- docs/functions/Router.html | 2 +- docs/index.html | 16 +++- docs/interfaces/AxonCoreConfig.html | 10 ++- docs/interfaces/AxonPlugin.html | 4 + docs/interfaces/AxonResponseMessage.html | 9 +- docs/interfaces/Headers.html | 2 +- docs/interfaces/Request.html | 14 ++-- docs/interfaces/Response.html | 6 +- docs/media/index.ts | 14 +++- docs/modules.html | 4 +- docs/types/AxonCorsConfig.html | 59 +++++++++++++ docs/types/Controller.html | 2 +- docs/types/Middleware.html | 2 +- docs/types/nextFn.html | 2 +- examples/index.js | 3 + examples/index.ts | 3 + src/core/AxonCore.ts | 24 ++++-- src/core/coreTypes.ts | 102 ++++++++++++++++++++++- src/index.ts | 3 +- 23 files changed, 251 insertions(+), 50 deletions(-) create mode 100644 docs/interfaces/AxonPlugin.html create mode 100644 docs/types/AxonCorsConfig.html diff --git a/README.md b/README.md index 953c246..9507b09 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ You can checkout Axon benchmarks document and results from below link. - Configurable core - Plugin manager (You can create your own plugins and use them in other projects) - Controllers and Middlewares +- Default cors configuration method **More features soon...** @@ -162,6 +163,7 @@ AxonJs has some types which can help you in developing your applications for aut - `AxonCoreConfig`: Type of core config object for configuration Axon core as you want. - `AxonResponseMessage`: Type of core config option RESPONSE_MESSAGES. +- `AxonCorsConfig`: Type of core config option CORS. - `Request`: Type of controller request param. (IncomingMessage) - `Response`: Type of controller response param. (ServerResponse) - `Headers`: Type of response headers. (OutgoingHeaders) @@ -187,6 +189,7 @@ Configs: - `LOGGER`: boolean to set core logger on or off. (default true) - `LOGGER_VERBOSE`: boolean to set core logger in verbose mode. (default false) - `RESPONSE_MESSAGES`: object to change default value of some core responses. (type: AxonResponseMessage) +- `CORS`: object to change core cors settings. (type: AxonCorsConfig) ### Running server diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js index c696708..7041108 100644 --- a/docs/assets/navigation.js +++ b/docs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAACoWRPQvCQAxA/0vmYrX42U0K4uLSVRyONtXDM1cvKVbE/+5wSmvVuublPQLZ3kCwFohhWVtKrEMIoFRygBgyo5iRwxcZHORkIICjphziUTS/Bx92YqnQ+6ahSdAVKmtl/Mp7LJpMO7EUubTEuEFmtcefxc5eX3aNKkfHX1NP1qeneK6Q5av+ZP26P/SH72FfILEkzhqDrknItUQOG9Lxh4vZaBK1Ghud5wYvqv1m32jIvwZhLSvq+n76z01tJe37i4oy0ZY49OTdn47vuwc9cxgUoQIAAA==" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAACoWSsWrDMBBA/+Vm0ySmSVtvxRC6BIrX0kHYZ0dEObm6M3Up+fcMSrGj2taqp/c4dPr4BcFeIIPX3lJuHUICrZIjZFAaxYy8+iMPRzkbSOCkqYJskz5fkn92bqnWzdDQJOhqVY4y/sp9LN3ugti76RpNsyGPY5ECubXEeEBm1eBsLbi3lH1DVaHjydSNLekFfnXIMqnf2LLuB53xPYy9Sm4dh3uSn3ZYEU+uaP3ytNmmo1ZuSZw1Bl3YGUiscdBVZfBbjf+dbwwk1iDsZU+h709jbmE7Gc9fd1SKtsQrT+793ePl8wqLHt3bMgMAAA==" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index fba10be..4e48aa4 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAACqWZXW/iOBSG/4u59VDOgQDhrtNluittZ1ZFOzcRQikxbbQhZp3QdoT47yOTD9vYgGmv2mK/7zk+fjhO3B0R/K0gk2hH/kvzhEyGA0ryeM3IhDzybckEoWQrMjIhq22+LFOeFzfVQPelXGeEkmUWFwUryISQPW1sMBgqH/b/lhVla5TmJROreMmKm3rorBX0UOX0xJNfl4w69STlVhbJl7T4kuYvTKQlSwglm1iwvNSyOxFwE4t4XVwM2U77aFCzYMWG5wVzR63G/EtWlHG5PbECzavTzvNdQp2kCjsMgr5axWJR/tpcXkMdt9tO11bkCNet03RX7k8WJ0w4F1sPna8bjlur23ee33GhFlArbpqBs04BYOu05HlRiu2y5OK8Wcec6S5Em5dWgd5A5Z3xOLnj+Sp9vhDMmPjxWIdm4BGqmfexSM8Zf4qzhzRJMvYWX9qVjmP6B1eYFiXLLy2vmeQfQ2O2GT7aNA1dc4b/N/+P6dd/7z0NO83k82uokzwR8O8f9/fTR9+I7ezPh1z8nD5+/TGbXhdaU30mhcfp7J8f32fTxcN0Nru9n858s3AJr0zkGKSmTT6wooifnd3XMc0fqZyX3/g2T64x7mii08s7zvzUacbEKxNTIbRm6pODqft0GmtWvvDkOy9vs4y/sevq4RB/JCHshSMI1DmTs/fym+pV8jgtbqoPz27w2WPbculcOKjrLE6necfzUvAs0x4tqyBq4LPpHjldSlnL6HTajrOnCqYGPpv2kdOltLWM9nNK0jxh72SyI69MFCnPyYRgt98NCSWrlGWJfMqvwlOy5Ou1NKEk4cvt4dd5Pe0nk48fcnI1+6ZHaNSjGHbDYDSf06gRHwYOHzQe6pODEAiNwCUESwiGEAmN0CVES4iGsE9o1HcJ+5awbwgHhEYDl3BgCQeGMCA0ClzCwBIGhnBIaDSkMO6GIzCEQ0s4NIQjQqORK+LIEo4M4ZjQaOwSji3h2BCGhEahSxhawtAEQPIATnbAhgeO6Dng4+bHAZBJEEguwMkQ2BCBSRFINsDJEdgggUkSSD7AyRLYMIFJE0hGwMkT2ECBSRRITmDoFNtQgUkVSFbAyRXYYIFJFkhewMkW2HCBSRdIZsDJF9iAgUkYSmbQSRjahKFJGEpm0EkY2oThUY86NCl3l3K0KZMwlMygkzC0CUOTMBycah1oA4YmYCiRQSedaAOGJmB4smehzReafKEkBp1ko80Xmnzh+GRgG6/6o8OB+MpEyZK/qoMxitpTd0cW9WnZnsg7MiST3Z4SHNQ/m7/H8udenZmHT9tjU47J+PE7z5eH6wJlPlbm15ks61dBZQUD5QUDbzNRPzyum9cBzTHUHEMvx+peTVmgckAvA+N+Q/lomfglstQeIbV0tBph4GWUsKetWedAq4qfR3XXsNYeDzU7rUTgV6OX5gpLuYyUycjLo7mQ0BLpa4n0/Ux4nDhA7GlGPW8jUd3+aD6g+YCnz/OzueOgfX1heIXJ4pWJJ16YGWllBr86Vy9yOS/j5kVOo1H/dvhtvZsh1JBEv7zkO9jK2H/U9h/99j/n5ap6a9dstN1Hv91vbsaViZaKXyai+QeCtlnaXnl6NHfqykTrF34ttTFZ1P3UWBZo7R78+r2o/8OiTLT6+pW3utdg1b2GtlFagdCvQs39vzLRwPNohXNKNumGZWnOyCSa7/e/ATCoNXlcGgAA"; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAACq2abW/iOBDHv4t5m6X1ONDCu26P7Z103a6Kbt9EVZUSQ6MLMZeEbldVv/vJ5GkcT4qBvgKRmf+Mxz8/xOaNZepXzqbBG/s3TiM2HfseS8O1ZFN2r7aFzJjHtlnCpmy5TRdFrNL8rHwwfC7WCfPYIgnzXOZsyti7V8vAaNzqyP+2Mi8aoTgtZLYMFzI/qx59KMXPoc3pSUW/9wkNKqNWrcijL3H+JU6fZRYXMmIe24SZTAuUXU/ATZiF63xvyMbs2KBmwfKNSnNJRy2fuZcsL8Ji29MCpDVo7FybUCXZhh2PRqJtxeNj8Xuzvw1V3GFjjlpEhBtWadKV+1OGkczIxlaPPq4bXDZSV68qvVZZ24DK46x+8KHSiEOjtFBpXmTbRaGyj8UGpiVdiCYvVIFzv807UWH0I9mu4nRPMMPw+FjXKl3GK4dYjeHxsXYTj0Oo2u64SKtEPYXJbRxFifwV7iNgQJgf2cI4L+TeXquN3GOg8VE/7nQaGiamhfss88fs6z83joKD2vjjNlRJ9gT8++7mZnbvGrGxPj3k48/Z/de7+eyw0MjrlBTuZ/Mfd9/ns8fb2Xx+dTObu2ZBOZ6SyPXdvXPsyvbAcF1u6xXgVuZ5uCIXFsLMneBUFd/UNo0OER4gp/7mdTPvW6hl9iKzWZahdcIlB9Pv5DTWsnhW0XdVXCWJ+iUPqwfhfExCcD654CPozlt5Z97SO4YGudxhyvpwh9KrNtizN+lk11NXlcV4Ud4XbdjYuwStt08f9mnuHrx1+IToYclCd3O2NwnL7xNyka8blR+Ri+X3CbksMhnJtIjD5IBETKfPYCN8vVq5j4JhY/8JsTeZXCbx6rm4VmkRp9sD0qBcPyEjtdm94863i4XM87n57rR/zNLex+XVnQRT+Vp8604g5Y+nTnpIZd9kV2XRv053Xj46q0b59IBVWX/s1xpUdv2VrtLqCfMiszxWLlkPWtMDghkb/TiNydOQbqTK7qAwJjJ6bGQqSdAxTtnh7YNT0eko7cMHZdSfNvHuVQZrH5yadkdpX9ooo/cHj8VpJF/Z9K3hZspgKIYT5rFlLJNIn6jV6C7Ueq1FPBapxXb39aEy+yn1q742Lq3PzpkXnHvCH4KAhwcvqJ13D3Y/1BrtLztHzryAU47ccuSGIzAvAMoRLEcwHAXzAkE5CstRGI4+8wKfcvQtR99wHDEvGFGOI8txZDiOmReMPeBDEBPDcWw5jg3HC+YFF1TEC8vxwnC8ZF5wSTleWo6XhuOEecGEcpxYjhMTAM0DJ9nhNjy8Q88OH5ofAiCTIK654CRD3IaImxRxzQYnOeI2SNwkiWs+OMkSt2HiJk1cM8JJnrgNFDeJ4poTPiadbai4SRXXrHCSK26DxU2yuOaFk2xxGy5u0sU1M5zki9uAcZMw0MwASRjYhIFJGGhmgCQMbMKgM0ftJil6liKmKZMw0MwASRjYhIFJGGhmgCQMbMLAJAw0M0ASBjZhYBIGvZMW2ICBCRhoZICkE2zAwAQMNDJA0gk2YGACBhoZIOkEGzAwARM7wEg6hQ2YMAETGhlB0ilswIQJmNDICJJOYQMmOgvhbiUk6RTEWmgCJjQygl5HbcCECZjQyAiSTmEDJkzARC9gwgZMmIAJjYwgyRY2YMIETGhkBEmnsAETJmBCIyNIOoUNmDAB8zUygqTTtwHzTcD8HWAknb4NmG8C5kNfsX2bL9/ky9fE+CTZvs2X39ls+b2Bie1W+dNuf/sis0JGf5X73CBoNtFv7LHa/DYb7Dc2ZtO3d49B9SmqTx+qT19/vrdb4d2vzW5YP9N5VMc9z/URSxuqvZZ7YzBxE3tV6WJ3fdfKIJXLg0QW1bFjK8VHrRYfHSKW22KAxMBdbFO9aLdCAgmJC2ehrDqHXdcn6yg1jlLjTorl7TuSQApOAsYtaKszaXXcEFigl19UI6Tju7VI95rRonPUpHM3CXxqh5JBSsItmUg+bU0U0UDkYyeN6jCTGmmoOsKtaeX95xq9sqPcBMpNOMkRSV20Im5QlwcnqMxo5PturarvWVFbfNQWtxlN30UTcwcaU9yt07WQPdw5ooc7NkuFUVbejiMdNES52xhN1GpljiuOeom7dVMp8vgisyeVmxmhDuNuc/U6fO3MXQLVWbg1q7z2SFUR1tdXaGig/ge3/m9uUZAKKhM4towcWj7qfN9taJUHUqhAaOYQbrno09+lueagsgi3xStVxbK8NEV1wcuEW2dVh+15edhe/30JZYYmH+HWYfWdG8oL1QjcsK7/C4YyQYm4SdSXG4vmcgOpoVIJN72s/gseGmJohDlq1P9KQxAiBg8Seaz2GkaZOFp8uNsan1X/UWxF0LBwmxLL63NZXp+jjkedBm5VthFE+zG3odFcLqDuRjOGcKjKg8c28UYmcSrZNHh4f/8fHjl3ReQpAAA="; \ No newline at end of file diff --git a/docs/classes/AxonCore.html b/docs/classes/AxonCore.html index 2fd3e24..230d56e 100644 --- a/docs/classes/AxonCore.html +++ b/docs/classes/AxonCore.html @@ -1,15 +1,18 @@ -AxonCore | @mr-mkz/axon

Class AxonCore

Constructors

constructor +AxonCore | @mr-mkz/axon

Class AxonCore

Constructors

Methods

  • Parameters

    Returns Promise<void>

  • Start listening to http incoming requests

    +

Constructors

Methods

  • Start listening to http incoming requests

    Parameters

    • host: string = "127.0.0.1"

      server host address

    • port: number = 8000

      server port

    • Optionalcallback: (() => void)

      callback a function to run after starting to listen

      -
        • (): void
        • Returns void

    Returns Promise<void>

  • A method to config core as you want

    +
      • (): void
      • Returns void

Returns Promise<void>

  • A method to config core as you want

    If you want to config the core, use this method before all other methods.

    Parameters

    Returns void

  • loads created routes

    +

Returns Promise<void>

  • Loads a specified Axon plugin using the plugin loader.

    +

    Parameters

    • plugin: AxonPlugin

      The plugin to be loaded. It should be an instance of AxonPlugin.

      +

    Returns Promise<void>

  • loads created routes

    Parameters

    • router: AxonRouter

      instance of Router which routes setted with it.

      -
    • Optionalprefix: string

    Returns Promise<void>

+
  • Optionalprefix: string
  • Returns Promise<void>

    diff --git a/docs/functions/Router.html b/docs/functions/Router.html index b3e17f7..2408056 100644 --- a/docs/functions/Router.html +++ b/docs/functions/Router.html @@ -1 +1 @@ -Router | @mr-mkz/axon

    Function Router

    • Returns AxonRouter

    +Router | @mr-mkz/axon

    Function Router

    diff --git a/docs/index.html b/docs/index.html index b86720e..5efc37c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,6 +1,11 @@ @mr-mkz/axon

    @mr-mkz/axon

    Axon.js

    like the brain's powerful neural pathways, simple yet strong.

    Axon is a backend library who tries to be simple and powerfull.

    Currently Axon is 2X faster than Express. :D please checkout Axon Benchmarks

    +

    Latest change:

    +
      +
    • text/plain response in core default response errors bug fixed.
    • +
    • Plugin manager system added to core. (Document will update soon - 2024/10/24)
    • +

    Install Axon.js with npm

      npm install @mr-mkz/axon
     
    @@ -37,18 +42,19 @@

    • Simple routing system
    • -
    • Support methods: GET, POST, PUT, PATCH, DELETE, OPTIONS. more methods soon...
    • +
    • Support methods: GET, POST, PUT, PATCH, DELETE, OPTIONS.
    • Flexible routing system. (You can define routes in another files and then add them to core)
    • -
    • Default core logger (still developing)
    • +
    • Default core logger
    • Configurable core
    • +
    • Plugin manager (You can create your own plugins and use them in other projects)
    • +
    • Controllers and Middlewares
    • +
    • Default cors configuration method

    More features soon...

    • Support controllers better than now.
    • -
    • Support middlewares.
    • Some changes in response structure.
    • Response meta generator.
    • -
    • Logger system. [In Progress]
    • Auto error detector (maybe)
    • Default schemas.
    • Default database connection methods.
    • @@ -130,6 +136,7 @@
      • AxonCoreConfig: Type of core config object for configuration Axon core as you want.
      • AxonResponseMessage: Type of core config option RESPONSE_MESSAGES.
      • +
      • AxonCorsConfig: Type of core config option CORS.
      • Request: Type of controller request param. (IncomingMessage)
      • Response: Type of controller response param. (ServerResponse)
      • Headers: Type of response headers. (OutgoingHeaders)
      • @@ -149,6 +156,7 @@
      • LOGGER: boolean to set core logger on or off. (default true)
      • LOGGER_VERBOSE: boolean to set core logger in verbose mode. (default false)
      • RESPONSE_MESSAGES: object to change default value of some core responses. (type: AxonResponseMessage)
      • +
      • CORS: object to change core cors settings. (type: AxonCorsConfig)

      listen method runs your webserver.

      core.listen() has some default values

      diff --git a/docs/interfaces/AxonCoreConfig.html b/docs/interfaces/AxonCoreConfig.html index 3f9c139..22343e9 100644 --- a/docs/interfaces/AxonCoreConfig.html +++ b/docs/interfaces/AxonCoreConfig.html @@ -1,5 +1,11 @@ -AxonCoreConfig | @mr-mkz/axon

      Interface AxonCoreConfig

      interface AxonCoreConfig {
          DEBUG?: boolean;
          LOGGER?: boolean;
          LOGGER_VERBOSE?: boolean;
          RESPONSE_MESSAGES?: AxonResponseMessage;
      }

      Properties

      DEBUG? +AxonCoreConfig | @mr-mkz/axon

      Interface AxonCoreConfig

      interface AxonCoreConfig {
          CORS?: AxonCorsConfig;
          DEBUG?: boolean;
          LOGGER?: boolean;
          LOGGER_VERBOSE?: boolean;
          RESPONSE_MESSAGES?: AxonResponseMessage;
      }

      Properties

      DEBUG?: boolean
      LOGGER?: boolean
      LOGGER_VERBOSE?: boolean
      RESPONSE_MESSAGES?: AxonResponseMessage
      +

      Properties

      Cors configuration for AxonCore.

      +
      DEBUG?: boolean

      AxonCore debug mode.

      +
      LOGGER?: boolean

      AxonCore logger.

      +
      LOGGER_VERBOSE?: boolean

      Verboose mode of logger.

      +
      RESPONSE_MESSAGES?: AxonResponseMessage

      Configuration for AxonCore custom response messages.

      +
      diff --git a/docs/interfaces/AxonPlugin.html b/docs/interfaces/AxonPlugin.html new file mode 100644 index 0000000..933536d --- /dev/null +++ b/docs/interfaces/AxonPlugin.html @@ -0,0 +1,4 @@ +AxonPlugin | @mr-mkz/axon

      Interface AxonPlugin

      interface AxonPlugin {
          name: string;
          version: string;
          init(core: AxonCore): void;
          [methodName: string]: any;
      }

      Indexable

      • [methodName: string]: any

      Properties

      Methods

      Properties

      name: string
      version: string

      Methods

      diff --git a/docs/interfaces/AxonResponseMessage.html b/docs/interfaces/AxonResponseMessage.html index 6e25304..e2d9e59 100644 --- a/docs/interfaces/AxonResponseMessage.html +++ b/docs/interfaces/AxonResponseMessage.html @@ -1,4 +1,5 @@ -AxonResponseMessage | @mr-mkz/axon

      Interface AxonResponseMessage

      interface AxonResponseMessage {
          methodNotAllowed?: string;
          notFound?: string;
          serverError?: string;
          [key: string]: string | undefined;
      }

      Indexable

      • [key: string]: string | undefined

      Properties

      methodNotAllowed? +AxonResponseMessage | @mr-mkz/axon

      Interface AxonResponseMessage

      Configuration for AxonCore custom response messages.

      +
      interface AxonResponseMessage {
          methodNotAllowed?: string;
          notFound?: string;
          serverError?: string;
          [key: string]: string | undefined;
      }

      Indexable

      • [key: string]: string | undefined

      Properties

      methodNotAllowed?: string

      response error message for 405 method not allowed response from core

      @@ -8,7 +9,7 @@
    • config: 'Method {method} is not allowed'
    • response: 'Method TRACE is not allowed'
    -
    notFound?: string

    response error message for 404 not found response from core

    +
    notFound?: string

    response error message for 404 not found response from core

    use {path} to show request method.

    -
    serverError?: string

    response error message for 500 internal server error response from core

    -
    +
    serverError?: string

    response error message for 500 internal server error response from core

    +
    diff --git a/docs/interfaces/Headers.html b/docs/interfaces/Headers.html index c22ba0e..71320a6 100644 --- a/docs/interfaces/Headers.html +++ b/docs/interfaces/Headers.html @@ -1,4 +1,4 @@ -Headers | @mr-mkz/axon

    Interface Headers

    interface Headers {
        accept?: string | string[];
        accept-charset?: string | string[];
        accept-encoding?: string | string[];
        accept-language?: string | string[];
        accept-ranges?: string;
        access-control-allow-credentials?: string;
        access-control-allow-headers?: string;
        access-control-allow-methods?: string;
        access-control-allow-origin?: string;
        access-control-expose-headers?: string;
        access-control-max-age?: string;
        access-control-request-headers?: string;
        access-control-request-method?: string;
        age?: string;
        allow?: string;
        authorization?: string;
        cache-control?: string;
        cdn-cache-control?: string;
        connection?: string | string[];
        content-disposition?: string;
        content-encoding?: string;
        content-language?: string;
        content-length?: string | number;
        content-location?: string;
        content-range?: string;
        content-security-policy?: string;
        content-security-policy-report-only?: string;
        cookie?: string | string[];
        date?: string;
        dav?: string | string[];
        dnt?: string;
        etag?: string;
        expect?: string;
        expires?: string;
        forwarded?: string;
        from?: string;
        host?: string;
        if-match?: string;
        if-modified-since?: string;
        if-none-match?: string;
        if-range?: string;
        if-unmodified-since?: string;
        last-modified?: string;
        link?: string | string[];
        location?: string;
        max-forwards?: string;
        origin?: string;
        prgama?: string | string[];
        proxy-authenticate?: string | string[];
        proxy-authorization?: string;
        public-key-pins?: string;
        public-key-pins-report-only?: string;
        range?: string;
        referer?: string;
        referrer-policy?: string;
        refresh?: string;
        retry-after?: string;
        sec-websocket-accept?: string;
        sec-websocket-extensions?: string | string[];
        sec-websocket-key?: string;
        sec-websocket-protocol?: string | string[];
        sec-websocket-version?: string;
        server?: string;
        set-cookie?: string | string[];
        strict-transport-security?: string;
        te?: string;
        trailer?: string;
        transfer-encoding?: string;
        upgrade?: string;
        upgrade-insecure-requests?: string;
        user-agent?: string;
        vary?: string;
        via?: string | string[];
        warning?: string;
        www-authenticate?: string | string[];
        x-content-type-options?: string;
        x-dns-prefetch-control?: string;
        x-frame-options?: string;
        x-xss-protection?: string;
    }

    Hierarchy

    • OutgoingHttpHeaders
      • Headers

    Properties

    accept? +Headers | @mr-mkz/axon

    Interface Headers

    interface Headers {
        accept?: string | string[];
        accept-charset?: string | string[];
        accept-encoding?: string | string[];
        accept-language?: string | string[];
        accept-ranges?: string;
        access-control-allow-credentials?: string;
        access-control-allow-headers?: string;
        access-control-allow-methods?: string;
        access-control-allow-origin?: string;
        access-control-expose-headers?: string;
        access-control-max-age?: string;
        access-control-request-headers?: string;
        access-control-request-method?: string;
        age?: string;
        allow?: string;
        authorization?: string;
        cache-control?: string;
        cdn-cache-control?: string;
        connection?: string | string[];
        content-disposition?: string;
        content-encoding?: string;
        content-language?: string;
        content-length?: string | number;
        content-location?: string;
        content-range?: string;
        content-security-policy?: string;
        content-security-policy-report-only?: string;
        cookie?: string | string[];
        date?: string;
        dav?: string | string[];
        dnt?: string;
        etag?: string;
        expect?: string;
        expires?: string;
        forwarded?: string;
        from?: string;
        host?: string;
        if-match?: string;
        if-modified-since?: string;
        if-none-match?: string;
        if-range?: string;
        if-unmodified-since?: string;
        last-modified?: string;
        link?: string | string[];
        location?: string;
        max-forwards?: string;
        origin?: string;
        prgama?: string | string[];
        proxy-authenticate?: string | string[];
        proxy-authorization?: string;
        public-key-pins?: string;
        public-key-pins-report-only?: string;
        range?: string;
        referer?: string;
        referrer-policy?: string;
        refresh?: string;
        retry-after?: string;
        sec-websocket-accept?: string;
        sec-websocket-extensions?: string | string[];
        sec-websocket-key?: string;
        sec-websocket-protocol?: string | string[];
        sec-websocket-version?: string;
        server?: string;
        set-cookie?: string | string[];
        strict-transport-security?: string;
        te?: string;
        trailer?: string;
        transfer-encoding?: string;
        upgrade?: string;
        upgrade-insecure-requests?: string;
        user-agent?: string;
        vary?: string;
        via?: string | string[];
        warning?: string;
        www-authenticate?: string | string[];
        x-content-type-options?: string;
        x-dns-prefetch-control?: string;
        x-frame-options?: string;
        x-xss-protection?: string;
    }

    Hierarchy

    • OutgoingHttpHeaders
      • Headers

    Properties

    accept? accept-charset? accept-encoding? accept-language? diff --git a/docs/interfaces/Request.html b/docs/interfaces/Request.html index c22e5fc..3aca45f 100644 --- a/docs/interfaces/Request.html +++ b/docs/interfaces/Request.html @@ -1,4 +1,4 @@ -Request | @mr-mkz/axon

    Interface Request

    interface Request {
        aborted: boolean;
        body?: any;
        closed: boolean;
        complete: boolean;
        connection: Socket;
        destroyed: boolean;
        errored: null | Error;
        headers: IncomingHttpHeaders;
        headersDistinct: Dict<string[]>;
        httpVersion: string;
        httpVersionMajor: number;
        httpVersionMinor: number;
        method?: string;
        params: any;
        rawHeaders: string[];
        rawTrailers: string[];
        readable: boolean;
        readableAborted: boolean;
        readableDidRead: boolean;
        readableEncoding: null | BufferEncoding;
        readableEnded: boolean;
        readableFlowing: null | boolean;
        readableHighWaterMark: number;
        readableLength: number;
        readableObjectMode: boolean;
        socket: Socket;
        statusCode?: number;
        statusMessage?: string;
        trailers: Dict<string>;
        trailersDistinct: Dict<string[]>;
        url?: string;
        _construct?(callback: ((error?: null | Error) => void)): void;
        _destroy(error: null | Error, callback: ((error?: null | Error) => void)): void;
        _read(size: number): void;
        [asyncDispose](): Promise<void>;
        [asyncIterator](): AsyncIterableIterator<any>;
        [captureRejectionSymbol]?<K>(error: Error, event: string | symbol, ...args: AnyRest): void;
        addListener(event: "close", listener: (() => void)): this;
        addListener(event: "data", listener: ((chunk: any) => void)): this;
        addListener(event: "end", listener: (() => void)): this;
        addListener(event: "error", listener: ((err: Error) => void)): this;
        addListener(event: "pause", listener: (() => void)): this;
        addListener(event: "readable", listener: (() => void)): this;
        addListener(event: "resume", listener: (() => void)): this;
        addListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        asIndexedPairs(options?: Pick<ArrayOptions, "signal">): Readable;
        compose<T>(stream:
            | ComposeFnParam
            | T
            | Iterable<T>
            | AsyncIterable<T>, options?: {
            signal: AbortSignal;
        }): T;
        destroy(error?: Error): this;
        drop(limit: number, options?: Pick<ArrayOptions, "signal">): Readable;
        emit(event: "close"): boolean;
        emit(event: "data", chunk: any): boolean;
        emit(event: "end"): boolean;
        emit(event: "error", err: Error): boolean;
        emit(event: "pause"): boolean;
        emit(event: "readable"): boolean;
        emit(event: "resume"): boolean;
        emit(event: string | symbol, ...args: any[]): boolean;
        eventNames(): (string | symbol)[];
        every(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Promise<boolean>;
        filter(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Readable;
        find<T>(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => data is T), options?: ArrayOptions): Promise<undefined | T>;
        find(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Promise<any>;
        flatMap(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => any), options?: ArrayOptions): Readable;
        forEach(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => void | Promise<void>), options?: ArrayOptions): Promise<void>;
        getMaxListeners(): number;
        isPaused(): boolean;
        iterator(options?: {
            destroyOnReturn?: boolean;
        }): AsyncIterableIterator<any>;
        listenerCount<K>(eventName: string | symbol, listener?: Function): number;
        listeners<K>(eventName: string | symbol): Function[];
        map(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => any), options?: ArrayOptions): Readable;
        off<K>(eventName: string | symbol, listener: ((...args: any[]) => void)): this;
        on(event: "close", listener: (() => void)): this;
        on(event: "data", listener: ((chunk: any) => void)): this;
        on(event: "end", listener: (() => void)): this;
        on(event: "error", listener: ((err: Error) => void)): this;
        on(event: "pause", listener: (() => void)): this;
        on(event: "readable", listener: (() => void)): this;
        on(event: "resume", listener: (() => void)): this;
        on(event: string | symbol, listener: ((...args: any[]) => void)): this;
        once(event: "close", listener: (() => void)): this;
        once(event: "data", listener: ((chunk: any) => void)): this;
        once(event: "end", listener: (() => void)): this;
        once(event: "error", listener: ((err: Error) => void)): this;
        once(event: "pause", listener: (() => void)): this;
        once(event: "readable", listener: (() => void)): this;
        once(event: "resume", listener: (() => void)): this;
        once(event: string | symbol, listener: ((...args: any[]) => void)): this;
        pause(): this;
        pipe<T>(destination: T, options?: {
            end?: boolean;
        }): T;
        prependListener(event: "close", listener: (() => void)): this;
        prependListener(event: "data", listener: ((chunk: any) => void)): this;
        prependListener(event: "end", listener: (() => void)): this;
        prependListener(event: "error", listener: ((err: Error) => void)): this;
        prependListener(event: "pause", listener: (() => void)): this;
        prependListener(event: "readable", listener: (() => void)): this;
        prependListener(event: "resume", listener: (() => void)): this;
        prependListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        prependOnceListener(event: "close", listener: (() => void)): this;
        prependOnceListener(event: "data", listener: ((chunk: any) => void)): this;
        prependOnceListener(event: "end", listener: (() => void)): this;
        prependOnceListener(event: "error", listener: ((err: Error) => void)): this;
        prependOnceListener(event: "pause", listener: (() => void)): this;
        prependOnceListener(event: "readable", listener: (() => void)): this;
        prependOnceListener(event: "resume", listener: (() => void)): this;
        prependOnceListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        push(chunk: any, encoding?: BufferEncoding): boolean;
        rawListeners<K>(eventName: string | symbol): Function[];
        read(size?: number): any;
        reduce<T>(fn: ((previous: any, data: any, options?: Pick<ArrayOptions, "signal">) => T), initial?: undefined, options?: Pick<ArrayOptions, "signal">): Promise<T>;
        reduce<T>(fn: ((previous: T, data: any, options?: Pick<ArrayOptions, "signal">) => T), initial: T, options?: Pick<ArrayOptions, "signal">): Promise<T>;
        removeAllListeners(eventName?: string | symbol): this;
        removeListener(event: "close", listener: (() => void)): this;
        removeListener(event: "data", listener: ((chunk: any) => void)): this;
        removeListener(event: "end", listener: (() => void)): this;
        removeListener(event: "error", listener: ((err: Error) => void)): this;
        removeListener(event: "pause", listener: (() => void)): this;
        removeListener(event: "readable", listener: (() => void)): this;
        removeListener(event: "resume", listener: (() => void)): this;
        removeListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        resume(): this;
        setEncoding(encoding: BufferEncoding): this;
        setMaxListeners(n: number): this;
        setTimeout(msecs: number, callback?: (() => void)): this;
        some(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Promise<boolean>;
        take(limit: number, options?: Pick<ArrayOptions, "signal">): Readable;
        toArray(options?: Pick<ArrayOptions, "signal">): Promise<any[]>;
        unpipe(destination?: WritableStream): this;
        unshift(chunk: any, encoding?: BufferEncoding): void;
        wrap(stream: ReadableStream): this;
    }

    Hierarchy

    • IncomingMessage
      • Request

    Properties

    aborted +Request | @mr-mkz/axon

    Interface Request

    interface Request {
        aborted: boolean;
        body?: any;
        closed: boolean;
        complete: boolean;
        connection: Socket;
        destroyed: boolean;
        errored: null | Error;
        headers: IncomingHttpHeaders;
        headersDistinct: Dict<string[]>;
        httpVersion: string;
        httpVersionMajor: number;
        httpVersionMinor: number;
        method?: string;
        params: any;
        rawHeaders: string[];
        rawTrailers: string[];
        readable: boolean;
        readableAborted: boolean;
        readableDidRead: boolean;
        readableEncoding: null | BufferEncoding;
        readableEnded: boolean;
        readableFlowing: null | boolean;
        readableHighWaterMark: number;
        readableLength: number;
        readableObjectMode: boolean;
        socket: Socket;
        statusCode?: number;
        statusMessage?: string;
        trailers: Dict<string>;
        trailersDistinct: Dict<string[]>;
        url?: string;
        _construct?(callback: ((error?: null | Error) => void)): void;
        _destroy(error: null | Error, callback: ((error?: null | Error) => void)): void;
        _read(size: number): void;
        [asyncDispose](): Promise<void>;
        [asyncIterator](): AsyncIterableIterator<any, any, any>;
        [captureRejectionSymbol]?<K>(error: Error, event: string | symbol, ...args: AnyRest): void;
        addListener(event: "close", listener: (() => void)): this;
        addListener(event: "data", listener: ((chunk: any) => void)): this;
        addListener(event: "end", listener: (() => void)): this;
        addListener(event: "error", listener: ((err: Error) => void)): this;
        addListener(event: "pause", listener: (() => void)): this;
        addListener(event: "readable", listener: (() => void)): this;
        addListener(event: "resume", listener: (() => void)): this;
        addListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        asIndexedPairs(options?: Pick<ArrayOptions, "signal">): Readable;
        compose<T>(stream:
            | ComposeFnParam
            | T
            | Iterable<T, any, any>
            | AsyncIterable<T, any, any>, options?: {
            signal: AbortSignal;
        }): T;
        destroy(error?: Error): this;
        drop(limit: number, options?: Pick<ArrayOptions, "signal">): Readable;
        emit(event: "close"): boolean;
        emit(event: "data", chunk: any): boolean;
        emit(event: "end"): boolean;
        emit(event: "error", err: Error): boolean;
        emit(event: "pause"): boolean;
        emit(event: "readable"): boolean;
        emit(event: "resume"): boolean;
        emit(event: string | symbol, ...args: any[]): boolean;
        eventNames(): (string | symbol)[];
        every(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Promise<boolean>;
        filter(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Readable;
        find<T>(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => data is T), options?: ArrayOptions): Promise<undefined | T>;
        find(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Promise<any>;
        flatMap(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => any), options?: ArrayOptions): Readable;
        forEach(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => void | Promise<void>), options?: ArrayOptions): Promise<void>;
        getMaxListeners(): number;
        isPaused(): boolean;
        iterator(options?: {
            destroyOnReturn?: boolean;
        }): AsyncIterableIterator<any, any, any>;
        listenerCount<K>(eventName: string | symbol, listener?: Function): number;
        listeners<K>(eventName: string | symbol): Function[];
        map(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => any), options?: ArrayOptions): Readable;
        off<K>(eventName: string | symbol, listener: ((...args: any[]) => void)): this;
        on(event: "close", listener: (() => void)): this;
        on(event: "data", listener: ((chunk: any) => void)): this;
        on(event: "end", listener: (() => void)): this;
        on(event: "error", listener: ((err: Error) => void)): this;
        on(event: "pause", listener: (() => void)): this;
        on(event: "readable", listener: (() => void)): this;
        on(event: "resume", listener: (() => void)): this;
        on(event: string | symbol, listener: ((...args: any[]) => void)): this;
        once(event: "close", listener: (() => void)): this;
        once(event: "data", listener: ((chunk: any) => void)): this;
        once(event: "end", listener: (() => void)): this;
        once(event: "error", listener: ((err: Error) => void)): this;
        once(event: "pause", listener: (() => void)): this;
        once(event: "readable", listener: (() => void)): this;
        once(event: "resume", listener: (() => void)): this;
        once(event: string | symbol, listener: ((...args: any[]) => void)): this;
        pause(): this;
        pipe<T>(destination: T, options?: {
            end?: boolean;
        }): T;
        prependListener(event: "close", listener: (() => void)): this;
        prependListener(event: "data", listener: ((chunk: any) => void)): this;
        prependListener(event: "end", listener: (() => void)): this;
        prependListener(event: "error", listener: ((err: Error) => void)): this;
        prependListener(event: "pause", listener: (() => void)): this;
        prependListener(event: "readable", listener: (() => void)): this;
        prependListener(event: "resume", listener: (() => void)): this;
        prependListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        prependOnceListener(event: "close", listener: (() => void)): this;
        prependOnceListener(event: "data", listener: ((chunk: any) => void)): this;
        prependOnceListener(event: "end", listener: (() => void)): this;
        prependOnceListener(event: "error", listener: ((err: Error) => void)): this;
        prependOnceListener(event: "pause", listener: (() => void)): this;
        prependOnceListener(event: "readable", listener: (() => void)): this;
        prependOnceListener(event: "resume", listener: (() => void)): this;
        prependOnceListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        push(chunk: any, encoding?: BufferEncoding): boolean;
        rawListeners<K>(eventName: string | symbol): Function[];
        read(size?: number): any;
        reduce<T>(fn: ((previous: any, data: any, options?: Pick<ArrayOptions, "signal">) => T), initial?: undefined, options?: Pick<ArrayOptions, "signal">): Promise<T>;
        reduce<T>(fn: ((previous: T, data: any, options?: Pick<ArrayOptions, "signal">) => T), initial: T, options?: Pick<ArrayOptions, "signal">): Promise<T>;
        removeAllListeners(eventName?: string | symbol): this;
        removeListener(event: "close", listener: (() => void)): this;
        removeListener(event: "data", listener: ((chunk: any) => void)): this;
        removeListener(event: "end", listener: (() => void)): this;
        removeListener(event: "error", listener: ((err: Error) => void)): this;
        removeListener(event: "pause", listener: (() => void)): this;
        removeListener(event: "readable", listener: (() => void)): this;
        removeListener(event: "resume", listener: (() => void)): this;
        removeListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
        resume(): this;
        setEncoding(encoding: BufferEncoding): this;
        setMaxListeners(n: number): this;
        setTimeout(msecs: number, callback?: (() => void)): this;
        some(fn: ((data: any, options?: Pick<ArrayOptions, "signal">) => boolean | Promise<boolean>), options?: ArrayOptions): Promise<boolean>;
        take(limit: number, options?: Pick<ArrayOptions, "signal">): Readable;
        toArray(options?: Pick<ArrayOptions, "signal">): Promise<any[]>;
        unpipe(destination?: WritableStream): this;
        unshift(chunk: any, encoding?: BufferEncoding): void;
        wrap(stream: ReadableStream): this;
    }

    Hierarchy

    • IncomingMessage
      • Request

    Properties

    aborted body? closed complete @@ -81,7 +81,7 @@

    v10.1.0

    Since v17.0.0,v16.12.0 - Check message.destroyed from stream.Readable.

    body?: any

    the body of request which sent from client

    -
    closed: boolean

    Is true after 'close' has been emitted.

    +
    closed: boolean

    Is true after 'close' has been emitted.

    v18.0.0

    complete: boolean

    The message.complete property will be true if a complete HTTP message has been received and successfully parsed.

    @@ -137,7 +137,7 @@
    rawHeaders: string[]

    The raw request/response headers list exactly as they were received.

    +
    rawHeaders: string[]

    The raw request/response headers list exactly as they were received.

    The keys and values are in the same list. It is not a list of tuples. So, the even-numbered offsets are key values, and the odd-numbered offsets are the associated values.

    @@ -210,7 +210,7 @@

    v0.1.90

    Methods

    • Parameters

      • callback: ((error?: null | Error) => void)
          • (error?): void
          • Parameters

            • Optionalerror: null | Error

            Returns void

      Returns void

    • Parameters

      • error: null | Error
      • callback: ((error?: null | Error) => void)
          • (error?): void
          • Parameters

            • Optionalerror: null | Error

            Returns void

      Returns void

    • Parameters

      • size: number

      Returns void

    • Calls readable.destroy() with an AbortError and returns a promise that fulfills when the stream is finished.

      Returns Promise<void>

      v20.4.0

      -
    • Returns AsyncIterableIterator<any>

    • Type Parameters

      • K

      Parameters

      • error: Error
      • event: string | symbol
      • Rest...args: AnyRest

      Returns void

    • Event emitter +

    • Returns AsyncIterableIterator<any, any, any>

    • Type Parameters

      • K

      Parameters

      • error: Error
      • event: string | symbol
      • Rest...args: AnyRest

      Returns void

    • Event emitter The defined events on documents including:

      1. close
      2. @@ -239,7 +239,7 @@

      Parameters

      • Optionaloptions: Pick<ArrayOptions, "signal">

      Returns Readable

      a stream of indexed pairs.

      v17.5.0

      -
    • Type Parameters

      • T extends ReadableStream

      Parameters

      • stream:
            | ComposeFnParam
            | T
            | Iterable<T>
            | AsyncIterable<T>
      • Optionaloptions: {
            signal: AbortSignal;
        }
        • signal: AbortSignal

      Returns T

    • Calls destroy() on the socket that received the IncomingMessage. If error is provided, an 'error' event is emitted on the socket and error is passed +

    • Type Parameters

      • T extends ReadableStream

      Parameters

      • stream:
            | ComposeFnParam
            | T
            | Iterable<T, any, any>
            | AsyncIterable<T, any, any>
      • Optionaloptions: {
            signal: AbortSignal;
        }
        • signal: AbortSignal

      Returns T

    • Calls destroy() on the socket that received the IncomingMessage. If error is provided, an 'error' event is emitted on the socket and error is passed as an argument to any listeners on the event.

      Parameters

      • Optionalerror: Error

      Returns this

      v0.3.0

    • This method returns a new stream with the first limit chunks dropped from the start.

      @@ -357,13 +357,13 @@

      Returns boolean

      v0.11.14

      -
    • The iterator created by this method gives users the option to cancel the destruction +

    • The iterator created by this method gives users the option to cancel the destruction of the stream if the for await...of loop is exited by return, break, or throw, or if the iterator should destroy the stream if the stream emitted an error during iteration.

      Parameters

      • Optionaloptions: {
            destroyOnReturn?: boolean;
        }
        • OptionaldestroyOnReturn?: boolean

          When set to false, calling return on the async iterator, or exiting a for await...of iteration using a break, return, or throw will not destroy the stream. Default: true.

          -

      Returns AsyncIterableIterator<any>

      v16.3.0

      +

    Returns AsyncIterableIterator<any, any, any>

    v16.3.0

    • Returns the number of listeners listening for the event named eventName. If listener is provided, it will return how many times the listener is found in the list of the listeners of the event.

      diff --git a/docs/interfaces/Response.html b/docs/interfaces/Response.html index bc2b5aa..22280b6 100644 --- a/docs/interfaces/Response.html +++ b/docs/interfaces/Response.html @@ -1,4 +1,4 @@ -Response | @mr-mkz/axon

      Interface Response

      interface Response {
          chunkedEncoding: boolean;
          closed: boolean;
          connection: null | Socket;
          destroyed: boolean;
          errored: null | Error;
          finished: boolean;
          headersSent: boolean;
          req: IncomingMessage;
          sendDate: boolean;
          shouldKeepAlive: boolean;
          socket: null | Socket;
          status: ((code: number) => AxonResponse);
          statusCode: number;
          statusMessage: string;
          strictContentLength: boolean;
          useChunkedEncodingByDefault: boolean;
          writable: boolean;
          writableCorked: number;
          writableEnded: boolean;
          writableFinished: boolean;
          writableHighWaterMark: number;
          writableLength: number;
          writableNeedDrain: boolean;
          writableObjectMode: boolean;
          _construct?(callback: ((error?: null | Error) => void)): void;
          _destroy(error: null | Error, callback: ((error?: null | Error) => void)): void;
          _final(callback: ((error?: null | Error) => void)): void;
          _write(chunk: any, encoding: BufferEncoding, callback: ((error?: null | Error) => void)): void;
          _writev?(chunks: {
              chunk: any;
              encoding: BufferEncoding;
          }[], callback: ((error?: null | Error) => void)): void;
          [captureRejectionSymbol]?<K>(error: Error, event: string | symbol, ...args: AnyRest): void;
          addListener(event: "close", listener: (() => void)): this;
          addListener(event: "drain", listener: (() => void)): this;
          addListener(event: "error", listener: ((err: Error) => void)): this;
          addListener(event: "finish", listener: (() => void)): this;
          addListener(event: "pipe", listener: ((src: Readable) => void)): this;
          addListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          addListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          addTrailers(headers: OutgoingHttpHeaders | readonly [string, string][]): void;
          appendHeader(name: string, value: string | readonly string[]): this;
          assignSocket(socket: Socket): void;
          compose<T>(stream:
              | ComposeFnParam
              | T
              | Iterable<T>
              | AsyncIterable<T>, options?: {
              signal: AbortSignal;
          }): T;
          cork(): void;
          destroy(error?: Error): this;
          detachSocket(socket: Socket): void;
          emit(event: "close"): boolean;
          emit(event: "drain"): boolean;
          emit(event: "error", err: Error): boolean;
          emit(event: "finish"): boolean;
          emit(event: "pipe", src: Readable): boolean;
          emit(event: "unpipe", src: Readable): boolean;
          emit(event: string | symbol, ...args: any[]): boolean;
          end(cb?: (() => void)): this;
          end(chunk: any, cb?: (() => void)): this;
          end(chunk: any, encoding: BufferEncoding, cb?: (() => void)): this;
          eventNames(): (string | symbol)[];
          flushHeaders(): void;
          getHeader(name: string):
              | undefined
              | string
              | number
              | string[];
          getHeaderNames(): string[];
          getHeaders(): OutgoingHttpHeaders;
          getMaxListeners(): number;
          hasHeader(name: string): boolean;
          listenerCount<K>(eventName: string | symbol, listener?: Function): number;
          listeners<K>(eventName: string | symbol): Function[];
          off<K>(eventName: string | symbol, listener: ((...args: any[]) => void)): this;
          on(event: "close", listener: (() => void)): this;
          on(event: "drain", listener: (() => void)): this;
          on(event: "error", listener: ((err: Error) => void)): this;
          on(event: "finish", listener: (() => void)): this;
          on(event: "pipe", listener: ((src: Readable) => void)): this;
          on(event: "unpipe", listener: ((src: Readable) => void)): this;
          on(event: string | symbol, listener: ((...args: any[]) => void)): this;
          once(event: "close", listener: (() => void)): this;
          once(event: "drain", listener: (() => void)): this;
          once(event: "error", listener: ((err: Error) => void)): this;
          once(event: "finish", listener: (() => void)): this;
          once(event: "pipe", listener: ((src: Readable) => void)): this;
          once(event: "unpipe", listener: ((src: Readable) => void)): this;
          once(event: string | symbol, listener: ((...args: any[]) => void)): this;
          pipe<T>(destination: T, options?: {
              end?: boolean;
          }): T;
          prependListener(event: "close", listener: (() => void)): this;
          prependListener(event: "drain", listener: (() => void)): this;
          prependListener(event: "error", listener: ((err: Error) => void)): this;
          prependListener(event: "finish", listener: (() => void)): this;
          prependListener(event: "pipe", listener: ((src: Readable) => void)): this;
          prependListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          prependListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          prependOnceListener(event: "close", listener: (() => void)): this;
          prependOnceListener(event: "drain", listener: (() => void)): this;
          prependOnceListener(event: "error", listener: ((err: Error) => void)): this;
          prependOnceListener(event: "finish", listener: (() => void)): this;
          prependOnceListener(event: "pipe", listener: ((src: Readable) => void)): this;
          prependOnceListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          prependOnceListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          rawListeners<K>(eventName: string | symbol): Function[];
          removeAllListeners(eventName?: string | symbol): this;
          removeHeader(name: string): void;
          removeListener(event: "close", listener: (() => void)): this;
          removeListener(event: "drain", listener: (() => void)): this;
          removeListener(event: "error", listener: ((err: Error) => void)): this;
          removeListener(event: "finish", listener: (() => void)): this;
          removeListener(event: "pipe", listener: ((src: Readable) => void)): this;
          removeListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          removeListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          setDefaultEncoding(encoding: BufferEncoding): this;
          setHeader(name: string, value: string | number | readonly string[]): this;
          setMaxListeners(n: number): this;
          setTimeout(msecs: number, callback?: (() => void)): this;
          uncork(): void;
          write(chunk: any, callback?: ((error: undefined | null | Error) => void)): boolean;
          write(chunk: any, encoding: BufferEncoding, callback?: ((error: undefined | null | Error) => void)): boolean;
          writeContinue(callback?: (() => void)): void;
          writeEarlyHints(hints: Record<string, string | string[]>, callback?: (() => void)): void;
          writeHead(statusCode: number, statusMessage?: string, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this;
          writeHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this;
          writeProcessing(): void;
      }

      Hierarchy

      • ServerResponse
        • Response

      Properties

      chunkedEncoding +Response | @mr-mkz/axon

      Interface Response

      interface Response {
          chunkedEncoding: boolean;
          closed: boolean;
          connection: null | Socket;
          destroyed: boolean;
          errored: null | Error;
          finished: boolean;
          headersSent: boolean;
          req: IncomingMessage;
          sendDate: boolean;
          shouldKeepAlive: boolean;
          socket: null | Socket;
          status: ((code: number) => AxonResponse);
          statusCode: number;
          statusMessage: string;
          strictContentLength: boolean;
          useChunkedEncodingByDefault: boolean;
          writable: boolean;
          writableCorked: number;
          writableEnded: boolean;
          writableFinished: boolean;
          writableHighWaterMark: number;
          writableLength: number;
          writableNeedDrain: boolean;
          writableObjectMode: boolean;
          _construct?(callback: ((error?: null | Error) => void)): void;
          _destroy(error: null | Error, callback: ((error?: null | Error) => void)): void;
          _final(callback: ((error?: null | Error) => void)): void;
          _write(chunk: any, encoding: BufferEncoding, callback: ((error?: null | Error) => void)): void;
          _writev?(chunks: {
              chunk: any;
              encoding: BufferEncoding;
          }[], callback: ((error?: null | Error) => void)): void;
          [captureRejectionSymbol]?<K>(error: Error, event: string | symbol, ...args: AnyRest): void;
          addListener(event: "close", listener: (() => void)): this;
          addListener(event: "drain", listener: (() => void)): this;
          addListener(event: "error", listener: ((err: Error) => void)): this;
          addListener(event: "finish", listener: (() => void)): this;
          addListener(event: "pipe", listener: ((src: Readable) => void)): this;
          addListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          addListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          addTrailers(headers: OutgoingHttpHeaders | readonly [string, string][]): void;
          appendHeader(name: string, value: string | readonly string[]): this;
          assignSocket(socket: Socket): void;
          compose<T>(stream:
              | ComposeFnParam
              | T
              | Iterable<T, any, any>
              | AsyncIterable<T, any, any>, options?: {
              signal: AbortSignal;
          }): T;
          cork(): void;
          destroy(error?: Error): this;
          detachSocket(socket: Socket): void;
          emit(event: "close"): boolean;
          emit(event: "drain"): boolean;
          emit(event: "error", err: Error): boolean;
          emit(event: "finish"): boolean;
          emit(event: "pipe", src: Readable): boolean;
          emit(event: "unpipe", src: Readable): boolean;
          emit(event: string | symbol, ...args: any[]): boolean;
          end(cb?: (() => void)): this;
          end(chunk: any, cb?: (() => void)): this;
          end(chunk: any, encoding: BufferEncoding, cb?: (() => void)): this;
          eventNames(): (string | symbol)[];
          flushHeaders(): void;
          getHeader(name: string):
              | undefined
              | string
              | number
              | string[];
          getHeaderNames(): string[];
          getHeaders(): OutgoingHttpHeaders;
          getMaxListeners(): number;
          hasHeader(name: string): boolean;
          listenerCount<K>(eventName: string | symbol, listener?: Function): number;
          listeners<K>(eventName: string | symbol): Function[];
          off<K>(eventName: string | symbol, listener: ((...args: any[]) => void)): this;
          on(event: "close", listener: (() => void)): this;
          on(event: "drain", listener: (() => void)): this;
          on(event: "error", listener: ((err: Error) => void)): this;
          on(event: "finish", listener: (() => void)): this;
          on(event: "pipe", listener: ((src: Readable) => void)): this;
          on(event: "unpipe", listener: ((src: Readable) => void)): this;
          on(event: string | symbol, listener: ((...args: any[]) => void)): this;
          once(event: "close", listener: (() => void)): this;
          once(event: "drain", listener: (() => void)): this;
          once(event: "error", listener: ((err: Error) => void)): this;
          once(event: "finish", listener: (() => void)): this;
          once(event: "pipe", listener: ((src: Readable) => void)): this;
          once(event: "unpipe", listener: ((src: Readable) => void)): this;
          once(event: string | symbol, listener: ((...args: any[]) => void)): this;
          pipe<T>(destination: T, options?: {
              end?: boolean;
          }): T;
          prependListener(event: "close", listener: (() => void)): this;
          prependListener(event: "drain", listener: (() => void)): this;
          prependListener(event: "error", listener: ((err: Error) => void)): this;
          prependListener(event: "finish", listener: (() => void)): this;
          prependListener(event: "pipe", listener: ((src: Readable) => void)): this;
          prependListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          prependListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          prependOnceListener(event: "close", listener: (() => void)): this;
          prependOnceListener(event: "drain", listener: (() => void)): this;
          prependOnceListener(event: "error", listener: ((err: Error) => void)): this;
          prependOnceListener(event: "finish", listener: (() => void)): this;
          prependOnceListener(event: "pipe", listener: ((src: Readable) => void)): this;
          prependOnceListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          prependOnceListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          rawListeners<K>(eventName: string | symbol): Function[];
          removeAllListeners(eventName?: string | symbol): this;
          removeHeader(name: string): void;
          removeListener(event: "close", listener: (() => void)): this;
          removeListener(event: "drain", listener: (() => void)): this;
          removeListener(event: "error", listener: ((err: Error) => void)): this;
          removeListener(event: "finish", listener: (() => void)): this;
          removeListener(event: "pipe", listener: ((src: Readable) => void)): this;
          removeListener(event: "unpipe", listener: ((src: Readable) => void)): this;
          removeListener(event: string | symbol, listener: ((...args: any[]) => void)): this;
          setDefaultEncoding(encoding: BufferEncoding): this;
          setHeader(name: string, value: string | number | readonly string[]): this;
          setMaxListeners(n: number): this;
          setTimeout(msecs: number, callback?: (() => void)): this;
          uncork(): void;
          write(chunk: any, callback?: ((error: undefined | null | Error) => void)): boolean;
          write(chunk: any, encoding: BufferEncoding, callback?: ((error: undefined | null | Error) => void)): boolean;
          writeContinue(callback?: (() => void)): void;
          writeEarlyHints(hints: Record<string, string | string[]>, callback?: (() => void)): void;
          writeHead(statusCode: number, statusMessage?: string, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this;
          writeHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this;
          writeProcessing(): void;
      }

      Hierarchy

      • ServerResponse
        • Response

      Properties

      chunkedEncoding closed connection destroyed @@ -85,7 +85,7 @@

      v0.3.0

      status: ((code: number) => AxonResponse)

      to add http response code for client.

      Type declaration

        • (code): AxonResponse
        • Parameters

          • code: number

            http response code

            -

          Returns AxonResponse

      statusCode: number

      When using implicit headers (not calling response.writeHead() explicitly), +

    Returns AxonResponse

    statusCode: number

    When using implicit headers (not calling response.writeHead() explicitly), this property controls the status code that will be sent to the client when the headers get flushed.

    response.statusCode = 404;
    @@ -172,7 +172,7 @@ 

    Parameters

    • name: string

      Header name

    • value: string | readonly string[]

      Header value

    Returns this

    v18.3.0, v16.17.0

    -
    • Parameters

      • socket: Socket

      Returns void

    • Type Parameters

      • T extends ReadableStream

      Parameters

      • stream:
            | ComposeFnParam
            | T
            | Iterable<T>
            | AsyncIterable<T>
      • Optionaloptions: {
            signal: AbortSignal;
        }
        • signal: AbortSignal

      Returns T

    • The writable.cork() method forces all written data to be buffered in memory. +

    • Parameters

      • socket: Socket

      Returns void

    • Type Parameters

      • T extends ReadableStream

      Parameters

      • stream:
            | ComposeFnParam
            | T
            | Iterable<T, any, any>
            | AsyncIterable<T, any, any>
      • Optionaloptions: {
            signal: AbortSignal;
        }
        • signal: AbortSignal

      Returns T

    • The writable.cork() method forces all written data to be buffered in memory. The buffered data will be flushed when either the uncork or end methods are called.

      The primary intent of writable.cork() is to accommodate a situation in which several small chunks are written to the stream in rapid succession. Instead of diff --git a/docs/media/index.ts b/docs/media/index.ts index a668ce9..1e5384c 100644 --- a/docs/media/index.ts +++ b/docs/media/index.ts @@ -5,21 +5,23 @@ import { AxonCore, Request, Response, nextFn } from "../src"; import { v1Routes } from "./routes/v1"; import { v2Routes } from "./routes/v2"; +import { LogPluginTest } from "./plugins/log"; const core = new AxonCore() core.loadConfig({ - DEBUG: true, // default false + DEBUG: false, // default false LOGGER: true, // default true LOGGER_VERBOSE: false, // default false RESPONSE_MESSAGES: { notFound: "route '{path}' not found" + }, + CORS: { + origin: '' } }) const testMid = async (req: Request, res: Response, next: nextFn) => { - console.log("global middleware 1"); - next() } @@ -31,6 +33,10 @@ core.globalMiddleware(testMid); core.loadRoute(v1Routes) core.loadRoute(v2Routes, "/api/v1") +// using plugins for more flexible code and also using ready codes to develope faster than past. +// you can make your own plugins with AxonPlugin interface. +core.loadPlugin(new LogPluginTest()); + // callback function is optional and core has default log message for on start event // host default is 127.0.0.1 and port default is 8000 -core.listen("127.0.0.1", 8000) \ No newline at end of file +core.listen("127.0.0.1", 3000) \ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html index 1b51ad0..23a9e24 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -1,10 +1,12 @@ @mr-mkz/axon

      @mr-mkz/axon

      Index

      Classes

      Interfaces

      Type Aliases

      Type Aliases

      Functions

      Router diff --git a/docs/types/AxonCorsConfig.html b/docs/types/AxonCorsConfig.html new file mode 100644 index 0000000..18df4ce --- /dev/null +++ b/docs/types/AxonCorsConfig.html @@ -0,0 +1,59 @@ +AxonCorsConfig | @mr-mkz/axon

      Type Alias AxonCorsConfig

      AxonCorsConfig: {
          allowedHeaders?: string | string[];
          credentials?: boolean;
          exposedHeaders?: string | string[];
          maxAge?: number;
          methods?: string | string[];
          optionsSuccessStatus?: number;
          origin?:
              | boolean
              | string
              | (string | RegExp)[]
              | Function;
          preflightContinue?: boolean;
      }

      Cors configuration for AxonCore.

      +

      Type declaration

      • OptionalallowedHeaders?: string | string[]

        Configures the Access-Control-Allow-Headers CORS header.

        +

        Possible values:

        +
          +
        • +

          String - exprects a comma-delimited 'Content-Type,Authorization'

          +
        • +
        • +

          Array - ['Content-Type', 'Authorization']

          +
        • +
        +

        If not specified, defaults to reflecting the headers specified in the request's Access-Control-Request-Headers header.

        +
      • Optionalcredentials?: boolean

        Configures the Access-Control-Allow-Credentials CORS header.

        +

        Set to true to pass the header, otherwise it is omitted.

        +
      • OptionalexposedHeaders?: string | string[]

        Configures the Access-Control-Expose-Headers CORS header.

        +

        Possible values:

        +
          +
        • +

          String - exprects a comma-delimited 'Content-Range,X-Content-Range'

          +
        • +
        • +

          Array - ['Content-Range', 'X-Content-Range']

          +
        • +
        +

        If not specified, no custom headers are exposed.

        +
      • OptionalmaxAge?: number

        Configures the Access-Control-Max-Age CORS header.

        +

        Set to an integer to pass the header, otherwise it is omitted.

        +
      • Optionalmethods?: string | string[]

        Configures the Access-Control-Allow-Methods CORS header.

        +

        Possible values:

        +
          +
        • +

          String - exprects a comma-delimited 'GET,POST,DELETE'

          +
        • +
        • +

          Array - ['GET', 'POST', 'DELETE']

          +
        • +
        +
      • OptionaloptionsSuccessStatus?: number

        Provides a status code to use for successful OPTIONS requests, since some legacy browsers (IE11, various SmartTVs) choke on 204.

        +
      • Optionalorigin?:
            | boolean
            | string
            | (string | RegExp)[]
            | Function

        Configures the Access-Control-Allow-Origin CORS header.

        +

        Possible values:

        +
          +
        • +

          Boolean - set origin to true to reflect the request origin, as defined by req.header('Origin'), or set it to false to disable CORS.

          +
        • +
        • +

          String - set origin to a specific origin. For example if you set it to "http://example.com" only requests from "http://example.com" will be allowed.

          +
        • +
        • +

          RegExp - set origin to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern /example\.com$/ will reflect any request that is coming from an origin ending with "example.com".

          +
        • +
        • +

          Array - set origin to an array of valid origins. Each origin can be a String or a RegExp. For example ["http://example1.com", /\.example2\.com$/] will accept any request from "http://example1.com" or from a subdomain of "example2.com".

          +
        • +
        • +

          Function - set origin to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature err [object], allow [bool]) as the second.

          +
        • +
        +
      • OptionalpreflightContinue?: boolean

        Pass the CORS preflight response to the next handler.

        +
      diff --git a/docs/types/Controller.html b/docs/types/Controller.html index 0d08c7d..1582b35 100644 --- a/docs/types/Controller.html +++ b/docs/types/Controller.html @@ -1 +1 @@ -Controller | @mr-mkz/axon

      Type Alias Controller

      Controller: ((req: Request, res: Response) => Promise<any>)
      +Controller | @mr-mkz/axon

      Type Alias Controller

      Controller: ((req: Request, res: Response) => Promise<any>)
      diff --git a/docs/types/Middleware.html b/docs/types/Middleware.html index 3be38b5..2bddbb4 100644 --- a/docs/types/Middleware.html +++ b/docs/types/Middleware.html @@ -1 +1 @@ -Middleware | @mr-mkz/axon

      Type Alias Middleware

      Middleware: ((req: Request, res: Response, next: nextFn) => Promise<any>)
      +Middleware | @mr-mkz/axon

      Type Alias Middleware

      Middleware: ((req: Request, res: Response, next: nextFn) => Promise<any>)
      diff --git a/docs/types/nextFn.html b/docs/types/nextFn.html index 432e998..8477e33 100644 --- a/docs/types/nextFn.html +++ b/docs/types/nextFn.html @@ -1 +1 @@ -nextFn | @mr-mkz/axon

      Type Alias nextFn

      nextFn: (() => Promise<any>)
      +nextFn | @mr-mkz/axon

      Type Alias nextFn

      nextFn: (() => Promise<any>)
      diff --git a/examples/index.js b/examples/index.js index 6652323..6a5877d 100644 --- a/examples/index.js +++ b/examples/index.js @@ -16,6 +16,9 @@ core.loadConfig({ LOGGER_VERBOSE: false, // default false RESPONSE_MESSAGES: { notFound: "route '{path}' not found" + }, + CORS: { + origin: 'https://github.com' } }) diff --git a/examples/index.ts b/examples/index.ts index 645dc32..8209659 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -15,6 +15,9 @@ core.loadConfig({ LOGGER_VERBOSE: false, // default false RESPONSE_MESSAGES: { notFound: "route '{path}' not found" + }, + CORS: { + origin: 'https://github.com' } }) diff --git a/src/core/AxonCore.ts b/src/core/AxonCore.ts index 67ad7ce..d791f8d 100644 --- a/src/core/AxonCore.ts +++ b/src/core/AxonCore.ts @@ -3,7 +3,7 @@ import { Controller, HttpMethods, JsonResponse, Middleware } from "../types" import * as http from "http"; import { routeDuplicateException } from "./CoreExceptions"; import addRoutePrefix from "./utils/routePrefixHandler"; -import { AxonCoreConfig } from "./coreTypes"; +import { AxonCoreConfig, AxonCorsConfig } from "./coreTypes"; import { logger } from "./utils/coreLogger"; import { colors } from "@spacingbat3/kolor" import getRequestBody from "./utils/getRequestBody"; @@ -20,6 +20,12 @@ const defaultResponses = { methodNotAllowed: "Method {method} not allowed" } +const defaultCors: AxonCorsConfig = { + origin: '*', + methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', + preflightContinue: false +} + export default class AxonCore { private routes: HttpMethods; private globalMiddlewares: Middleware[]; @@ -46,7 +52,8 @@ export default class AxonCore { DEBUG: false, LOGGER: true, LOGGER_VERBOSE: false, - RESPONSE_MESSAGES: defaultResponses + RESPONSE_MESSAGES: defaultResponses, + CORS: defaultCors }; this.configsLoaded = false; @@ -79,6 +86,7 @@ export default class AxonCore { this.config.LOGGER = config.LOGGER; this.config.LOGGER_VERBOSE = config.LOGGER_VERBOSE || false this.config.RESPONSE_MESSAGES = { ...config.RESPONSE_MESSAGES } + this.config.CORS = { ...config.CORS } if (this.config.DEBUG) { logger.level = "debug" @@ -208,15 +216,13 @@ export default class AxonCore { let controller: Controller = route.getController(); - const axonCors = await AxonCors.middlewareWrapper(); // this function gives custom config. - - // TODO: AxonCors is ready and I need to add cors config to AxonConfing option. + const axonCors = await AxonCors.middlewareWrapper(this.config.CORS); return this.handleMiddleware(req, res, async () => { return await this.handleMiddleware(req, res, async () => { return await this.handleMiddleware(req, res, async () => { await controller(req, res); - + // log incoming requests if (this.config.LOGGER_VERBOSE) { logger.request({ @@ -229,8 +235,8 @@ export default class AxonCore { }, "new http request") } else { logger.request(`${req.socket.remoteAddress} - ${req.method} ${req.url} ${res.statusCode} - ${req.headers["user-agent"]}`) - } - + } + }, middlewares); }, this.globalMiddlewares); }, [axonCors]); @@ -325,7 +331,7 @@ export default class AxonCore { }, "new http request") } else { logger.request(`${req.socket.remoteAddress} - ${req.method} ${req.url} ${res.statusCode} - ${req.headers["user-agent"]}`) - } + } return res.status(data.responseCode).body(data.body) } diff --git a/src/core/coreTypes.ts b/src/core/coreTypes.ts index 4fc32f0..281824b 100644 --- a/src/core/coreTypes.ts +++ b/src/core/coreTypes.ts @@ -1,21 +1,116 @@ interface AxonCoreConfig { + /** + * AxonCore debug mode. + */ DEBUG?: boolean; + /** + * AxonCore logger. + */ LOGGER?: boolean; + /** + * Verboose mode of logger. + */ LOGGER_VERBOSE?: boolean; + /** + * Configuration for AxonCore custom response messages. + */ RESPONSE_MESSAGES?: AxonResponseMessage; + /** + * Cors configuration for AxonCore. + */ + CORS?: AxonCorsConfig; +} + +/** + * Cors configuration for AxonCore. + */ +type AxonCorsConfig = { + /** + * Configures the Access-Control-Allow-Origin CORS header. + * + * Possible values: + * + * * Boolean - set origin to true to reflect the request origin, as defined by `req.header('Origin')`, or set it to false to disable CORS. + * + * * String - set origin to a specific origin. For example if you set it to `"http://example.com"` only requests from "http://example.com" will be allowed. + * + * * RegExp - set origin to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com". + * + * * Array - set origin to an array of valid origins. Each origin can be a String or a RegExp. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com". + * + * * Function - set origin to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature err [object], allow [bool]) as the second. + */ + origin?: boolean | string | Array | Function; + /** + * Configures the Access-Control-Allow-Methods CORS header. + * + * Possible values: + * + * * String - exprects a comma-delimited `'GET,POST,DELETE'` + * + * * Array - `['GET', 'POST', 'DELETE']` + */ + methods?: string | string[]; + /** + * Configures the Access-Control-Allow-Headers CORS header. + * + * Possible values: + * + * * String - exprects a comma-delimited `'Content-Type,Authorization'` + * + * * Array - `['Content-Type', 'Authorization']` + * + * If not specified, defaults to reflecting the headers specified in the request's Access-Control-Request-Headers header. + */ + allowedHeaders?: string | string[]; + /** + * Configures the Access-Control-Expose-Headers CORS header. + * + * Possible values: + * + * * String - exprects a comma-delimited `'Content-Range,X-Content-Range'` + * + * * Array - `['Content-Range', 'X-Content-Range']` + * + * If not specified, no custom headers are exposed. + */ + exposedHeaders?: string | string[]; + /** + * Configures the Access-Control-Allow-Credentials CORS header. + * + * Set to `true` to pass the header, otherwise it is omitted. + */ + credentials?: boolean; + /** + * Configures the Access-Control-Max-Age CORS header. + * + * Set to an `integer` to pass the header, otherwise it is omitted. + */ + maxAge?: number; + /** + * Pass the CORS preflight response to the next handler. + */ + preflightContinue?: boolean; + /** + * Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`. + */ + optionsSuccessStatus?: number; } +/** + * Configuration for AxonCore custom response messages. + */ interface AxonResponseMessage { /** * response error message for 404 not found response from core * * use `{path}` to show request method. */ - notFound?: string; + notFound?: string; /** * response error message for 500 internal server error response from core */ - serverError?: string; + serverError?: string; /** * response error message for 405 method not allowed response from core * @@ -31,5 +126,6 @@ interface AxonResponseMessage { export { AxonCoreConfig, - AxonResponseMessage + AxonResponseMessage, + AxonCorsConfig } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index c8dc23d..02521db 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ import { Controller, Middleware , nextFn} from "./types"; import { AxonCoreConfig } from "./core/coreTypes"; import * as http from "http" import AxonResponse from "./core/AxonResponse"; -import { AxonResponseMessage } from "./core/coreTypes"; +import { AxonResponseMessage, AxonCorsConfig } from "./core/coreTypes"; import { AxonPlugin } from "./types/AxonPlugin"; const Router = () => { @@ -46,6 +46,7 @@ export { Router, AxonCoreConfig, AxonResponseMessage, + AxonCorsConfig, Request, Response, Headers,