From 5a1e169bd6fc8467514e60fc5e9c49dd025e61b7 Mon Sep 17 00:00:00 2001 From: riflowth Date: Fri, 20 May 2022 20:16:17 +0700 Subject: [PATCH 1/5] feat: add middleware abstract class --- lib/controllers/Middleware.js | 21 +++++++++++++++++++++ lib/springpress.js | 2 ++ 2 files changed, 23 insertions(+) create mode 100644 lib/controllers/Middleware.js diff --git a/lib/controllers/Middleware.js b/lib/controllers/Middleware.js new file mode 100644 index 0000000..3e9e0d4 --- /dev/null +++ b/lib/controllers/Middleware.js @@ -0,0 +1,21 @@ +'use strict'; + +class Middleware { + + constructor() { + if (this.constructor == Middleware) { + throw new Error("Abstract classes can't be instantiated."); + } + } + + getHandler() { + throw new Error("Method 'getHandler()' must be implemented."); + } + + getRegisterCondition(routeMetadata) { + return true; + } + +} + +module.exports = Middleware; diff --git a/lib/springpress.js b/lib/springpress.js index 1e09acb..415d1ab 100644 --- a/lib/springpress.js +++ b/lib/springpress.js @@ -8,6 +8,7 @@ require('reflect-metadata'); const Controller = require('./controllers/Controller'); const ControllerRegistry = require('./controllers/ControllerRegistry'); const Methods = require('./controllers/Methods'); +const Middleware = require('./controllers/Middleware'); const ControllerDecorator = require('./decorators/ControllerDecorator'); const RequestDecorator = require('./decorators/RequestDecorator'); @@ -29,6 +30,7 @@ const Springpress = require('./server/Server'); exports.Controller = Controller; exports.ControllerRegistry = ControllerRegistry; exports.Methods = Methods; +exports.Middleware = Middleware; exports.RouteUtil = RouteUtil; exports.Springpress = Springpress; From c25c0f8402a5260435835573a4c03fc6fbeb8eee Mon Sep 17 00:00:00 2001 From: riflowth Date: Fri, 20 May 2022 20:17:03 +0700 Subject: [PATCH 2/5] feat: add register global middleware method --- index.d.ts | 44 +++++++++++++++------------ lib/controllers/ControllerRegistry.js | 14 ++++++--- test/mock/MockMiddleware.ts | 27 ++++++++++------ 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/index.d.ts b/index.d.ts index 256eb09..d0154bf 100644 --- a/index.d.ts +++ b/index.d.ts @@ -12,27 +12,26 @@ export abstract class Controller { */ getPath(): string; /** - * Returns the router structure with handler and metadata of the controller + * Returns the router structure with handler and metadata of the controller. * for converting to the modular express router. * @returns The router structure (array of {@link Route}) */ getRouter(): Route[]; } -export interface Middleware { +export abstract class Middleware { /** * Returns a function that have access to the request object, * the response object, and the next middleware function. * @param routeMetadata - A route metadata */ - getHandler(routeMetadata: RouteMetadata): RouteHandler; + abstract getHandler(routeMetadata: RouteMetadata): RouteHandler; /** - * Returns a boolean represent to the middleware register condition - * @param routeMethod - A route method for conditioning - * @param routeMetadata - A route metadata for conditioning - * @returns True if a route matches the middleware register condition, otherwise returns false - */ - getRegisterCondition(routeMethod: Methods, routeMetadata: RouteMetadata): boolean; + * Returns a boolean represent to the middleware register condition + * @param routeMetadata - A route metadata for conditioning + * @returns True if a route matches the middleware register condition, otherwise returns false + */ + getRegisterCondition(routeMetadata: RouteMetadata): boolean; } export class ControllerRegistry { @@ -42,12 +41,17 @@ export class ControllerRegistry { * into the controller registry for routing system. * * @remarks - * The middlewares run in the sequence as passed in the parameter. + * The middleware run in the sequence as passed in the array. * * @param controller - A controller instance - * @param middlewares - A single middleware or a group of middleware + * @param middleware - An array of middleware + */ + register(controller: Controller, middleware?: Middleware[]): void; + /** + * Registers global middleware in the application routing. + * @param middleware - A middleware or an array of middleware to register globally */ - register(controller: Controller, ...middlewares: Middleware[]): void; + registerGlobalMiddleware(middleware: Middleware | Middleware[]): void; /** * @returns A count of registered controller */ @@ -83,19 +87,19 @@ export abstract class HttpException extends Error { /** * Throws a http response code 400 */ -export class BadRequestException extends HttpException {} +export class BadRequestException extends HttpException { } /** * Throws a http response code 403 */ -export class ForbiddenException extends HttpException {} +export class ForbiddenException extends HttpException { } /** * Throws a http response code 404 */ -export class NotFoundException extends HttpException {} +export class NotFoundException extends HttpException { } /** * Throws a http response code 401 */ -export class UnauthorizedException extends HttpException {} +export class UnauthorizedException extends HttpException { } /** * Accepted http request methods @@ -120,15 +124,15 @@ export type Route = { metadata: RouteMetadata, }; -export interface Request extends ExpressRequest {} +export interface Request extends ExpressRequest { } -export interface Response extends ExpressResponse {} +export interface Response extends ExpressResponse { } -export interface NextFunction extends ExpressNextFunction {} +export interface NextFunction extends ExpressNextFunction { } export class RouteUtil { /** - * Add data into the route metadata + * Add data into the route metadata. * @param data - A key-value pairs of data to merge into the route metadata */ static addRouteMetadata(data: Record): MethodDecorator; diff --git a/lib/controllers/ControllerRegistry.js b/lib/controllers/ControllerRegistry.js index 1e1917c..259b004 100644 --- a/lib/controllers/ControllerRegistry.js +++ b/lib/controllers/ControllerRegistry.js @@ -12,7 +12,7 @@ class ControllerRegistry { this.#app = app; } - register(controller, ...middlewares) { + register(controller, middleware = []) { const router = Router(); const controllerPath = controller.getPath(); const routes = controller.getRouter(); @@ -24,13 +24,13 @@ class ControllerRegistry { routes.forEach((route) => { const routeMetadata = route.metadata; - const routeMethod = routeMetadata.method.toLowerCase(); + const routeMethod = routeMetadata.method; const routePath = routeMetadata.path; - const routerFunction = router[routeMethod]; + const routerFunction = router[routeMethod.toLowerCase()]; const registerMiddleware = (middleware) => { const canRegisterMiddleware = middleware - .getRegisterCondition(routeMethod, routeMetadata); + .getRegisterCondition(routeMetadata); if (canRegisterMiddleware) { return middleware.getHandler(routeMetadata); @@ -38,7 +38,7 @@ class ControllerRegistry { }; const routeSubStack = [ - ...middlewares.map(registerMiddleware).filter(Boolean), + ...middleware.map(registerMiddleware).filter(Boolean), route.handler, ].map(this.#interceptError); @@ -50,6 +50,10 @@ class ControllerRegistry { this.#controllers.push(controllerPath); } + registerGlobalMiddleware(middleware) { + this.#app.use(middleware.getHandler()); + } + size() { return this.#controllers.length; } diff --git a/test/mock/MockMiddleware.ts b/test/mock/MockMiddleware.ts index 6012164..ce13695 100644 --- a/test/mock/MockMiddleware.ts +++ b/test/mock/MockMiddleware.ts @@ -1,29 +1,36 @@ -import { Methods, Middleware, RouteHandler, RouteMetadata } from '../..'; +import { Middleware, RouteHandler, RouteMetadata } from '../..'; -export class MockMiddleware implements Middleware { +export class MockMiddleware extends Middleware { - public getHandler(): RouteHandler { + public getHandler(routeMetadata: RouteMetadata): RouteHandler { return async (req, res, next) => { next(); }; } - public getRegisterCondition(routeMethod: Methods, routeMetadata: RouteMetadata): boolean { - return true; - } - } -export class MockConditionalMiddleware implements Middleware { +export class MockConditionalMiddleware extends Middleware { - public getHandler(): RouteHandler { + public getHandler(routeMetadata: RouteMetadata): RouteHandler { return async (req, res, next) => { next(); }; } - public getRegisterCondition(routeMethod: Methods, routeMetadata: RouteMetadata): boolean { + public getRegisterCondition(routeMetadata: RouteMetadata): boolean { return routeMetadata.path === '/test2'; } } + +export class PingPongMiddleware extends Middleware { + + public getHandler(routeMetadata: RouteMetadata): RouteHandler { + return async (req, res, next) => { + res.header('ping', 'pong'); + next(); + }; + } + +} From 7644bc7fa05e8de11194a5140f306ca356b3688d Mon Sep 17 00:00:00 2001 From: riflowth Date: Fri, 20 May 2022 20:17:16 +0700 Subject: [PATCH 3/5] refactor: fix typo in constructor --- lib/exceptions/HttpException.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/exceptions/HttpException.js b/lib/exceptions/HttpException.js index 3372add..ecec467 100644 --- a/lib/exceptions/HttpException.js +++ b/lib/exceptions/HttpException.js @@ -7,7 +7,7 @@ class HttpException extends Error { this.name = this.constructor.name; if (this.constructor == HttpException) { - throw new Error("Abstract classes can't be instandtiated."); + throw new Error("Abstract classes can't be instantiated."); } } From 124bc6ee6e1e8f76dc7e506efa3518d1f997bb5c Mon Sep 17 00:00:00 2001 From: riflowth Date: Fri, 20 May 2022 20:17:46 +0700 Subject: [PATCH 4/5] test: add new middleware registration test --- package.json | 4 +- test/controller.test.ts | 17 +++-- yarn.lock | 142 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 151 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 51afa7e..cb37f8b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "main": "index.js", "types": "index.d.ts", "scripts": { - "test": "jest" + "test": "jest --verbose" }, "files": [ "LICENSE", @@ -35,7 +35,9 @@ }, "devDependencies": { "@types/jest": "^27.4.1", + "@types/supertest": "^2.0.12", "jest": "^27.5.1", + "supertest": "^6.2.3", "ts-jest": "^27.1.4", "typescript": "^4.6.3" } diff --git a/test/controller.test.ts b/test/controller.test.ts index 4aeb260..633fdcf 100644 --- a/test/controller.test.ts +++ b/test/controller.test.ts @@ -1,7 +1,8 @@ import express, { Express } from 'express'; +import request from 'supertest'; import { ControllerRegistry } from '..'; import { MockIndexController, MockTestController } from './mock/MockController'; -import { MockConditionalMiddleware, MockMiddleware } from './mock/MockMiddleware'; +import { MockConditionalMiddleware, MockMiddleware, PingPongMiddleware } from './mock/MockMiddleware'; describe('Test the ControllerRegistry class implementation', () => { @@ -48,7 +49,7 @@ describe('Test the ControllerRegistry class implementation', () => { // Unconditional middleware means this middleware should register for all routes. // NOTE: // - Expect 2 means the stack has middleware function and route handler function. - controllerRegistry.register(new MockIndexController(), new MockMiddleware()); + controllerRegistry.register(new MockIndexController(), [new MockMiddleware()]); router = findRouter(expressApp); routes = router[0].handle.stack; routes.forEach((layer: any) => expect(layer.route.stack.length).toBe(2)); @@ -59,7 +60,7 @@ describe('Test the ControllerRegistry class implementation', () => { // - In MockTestController has only 1 route path named 'test2'. // - Expect 1 means the stack has only route handler function. // - Expect 2 means the stack has middleware function and route handler function. - controllerRegistry.register(new MockTestController(), new MockConditionalMiddleware()); + controllerRegistry.register(new MockTestController(), [new MockConditionalMiddleware()]); router = findRouter(expressApp); routes = router[1].handle.stack; expect(routes.find((layer: any) => layer.route.path === '/test').route.stack.length).toBe(1); @@ -68,10 +69,18 @@ describe('Test the ControllerRegistry class implementation', () => { it('should return a registered controller count correctly', () => { controllerRegistry.register(new MockIndexController()); - controllerRegistry.register(new MockTestController(), new MockMiddleware()); + controllerRegistry.register(new MockTestController(), [new MockMiddleware()]); expect(controllerRegistry.size()).toBe(2); }); + it('should contain ping in response header when register middleware globally', async () => { + controllerRegistry.registerGlobalMiddleware(new PingPongMiddleware()); + controllerRegistry.register(new MockIndexController()); + + const response = await request(expressApp).get('/test'); + expect(response.headers['ping']).toBe('pong'); + }); + }); const findRouter = (expressApp: Express) => { diff --git a/yarn.lock b/yarn.lock index a2dcbca..5a3451a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -569,6 +569,11 @@ dependencies: "@types/node" "*" +"@types/cookiejar@*": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" + integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== + "@types/express-serve-static-core@^4.17.18": version "4.17.28" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" @@ -660,6 +665,21 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/superagent@*": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-4.1.15.tgz#63297de457eba5e2bc502a7609426c4cceab434a" + integrity sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ== + dependencies: + "@types/cookiejar" "*" + "@types/node" "*" + +"@types/supertest@^2.0.12": + version "2.0.12" + resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.12.tgz#ddb4a0568597c9aadff8dbec5b2e8fddbe8692fc" + integrity sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ== + dependencies: + "@types/superagent" "*" + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -766,6 +786,11 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= +asap@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1020,6 +1045,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +component-emitter@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1054,6 +1084,11 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookiejar@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" + integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1096,7 +1131,7 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1143,6 +1178,14 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +dezalgo@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= + dependencies: + asap "^2.0.0" + wrappy "1" + diff-sequences@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" @@ -1316,6 +1359,11 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -1360,6 +1408,25 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +formidable@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.0.1.tgz#4310bc7965d185536f9565184dee74fbb75557ff" + integrity sha512-rjTMNbp2BpfQShhFbR3Ruk3qk2y9jKpvMW78nJgx8QKtxjDVrwbZG+wvDOmVbifHyOUOQJXxqEy6r0faRrPzTQ== + dependencies: + dezalgo "1.0.3" + hexoid "1.0.0" + once "1.4.0" + qs "6.9.3" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -1458,6 +1525,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hexoid@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" + integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== + html-encoding-sniffer@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" @@ -1531,7 +1603,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2177,7 +2249,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -methods@~1.1.2: +methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= @@ -2207,6 +2279,11 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -2283,7 +2360,7 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" -once@^1.3.0: +once@1.4.0, once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -2435,13 +2512,18 @@ punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@6.10.3: +qs@6.10.3, qs@^6.10.3: version "6.10.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== dependencies: side-channel "^1.0.4" +qs@6.9.3: + version "6.9.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" + integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -2462,6 +2544,15 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + reflect-metadata@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" @@ -2505,7 +2596,7 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" -safe-buffer@5.2.1: +safe-buffer@5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -2527,7 +2618,7 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -semver@7.x, semver@^7.3.2: +semver@7.x, semver@^7.3.2, semver@^7.3.7: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== @@ -2661,6 +2752,13 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2683,6 +2781,31 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +superagent@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-7.1.3.tgz#783ff8330e7c2dad6ad8f0095edc772999273b6b" + integrity sha512-WA6et4nAvgBCS73lJvv1D0ssI5uk5Gh+TGN/kNe+B608EtcVs/yzfl+OLXTzDs7tOBDIpvgh/WUs1K2OK1zTeQ== + dependencies: + component-emitter "^1.3.0" + cookiejar "^2.1.3" + debug "^4.3.4" + fast-safe-stringify "^2.1.1" + form-data "^4.0.0" + formidable "^2.0.1" + methods "^1.1.2" + mime "^2.5.0" + qs "^6.10.3" + readable-stream "^3.6.0" + semver "^7.3.7" + +supertest@^6.2.3: + version "6.2.3" + resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.2.3.tgz#291b220126e5faa654d12abe1ada3658757c8c67" + integrity sha512-3GSdMYTMItzsSYjnIcljxMVZKPW1J9kYHZY+7yLfD0wpPwww97GeImZC1oOk0S5+wYl2niJwuFusBJqwLqYM3g== + dependencies: + methods "^1.1.2" + superagent "^7.1.3" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -2843,6 +2966,11 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" From aeb0103a2e658dcd544229597a409e7dd5562867 Mon Sep 17 00:00:00 2001 From: riflowth Date: Tue, 31 May 2022 02:57:23 +0700 Subject: [PATCH 5/5] refactor: always warn error on register controller --- lib/controllers/ControllerRegistry.js | 2 +- test/controller.test.ts | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/controllers/ControllerRegistry.js b/lib/controllers/ControllerRegistry.js index 259b004..4885f14 100644 --- a/lib/controllers/ControllerRegistry.js +++ b/lib/controllers/ControllerRegistry.js @@ -17,7 +17,7 @@ class ControllerRegistry { const controllerPath = controller.getPath(); const routes = controller.getRouter(); - if (process.env.NODE_ENV !== 'production' && this.#controllers.includes(controllerPath)) { + if (this.#controllers.includes(controllerPath)) { const controllerName = controller.constructor.name; console.warn(`Register duplicated controller: ${controllerPath} in ${controllerName}`); } diff --git a/test/controller.test.ts b/test/controller.test.ts index 633fdcf..c04f828 100644 --- a/test/controller.test.ts +++ b/test/controller.test.ts @@ -6,20 +6,16 @@ import { MockConditionalMiddleware, MockMiddleware, PingPongMiddleware } from '. describe('Test the ControllerRegistry class implementation', () => { - const originalEnv = process.env; let expressApp: Express; let controllerRegistry: ControllerRegistry; beforeEach(() => { - process.env = { ...originalEnv }; - expressApp = express(); controllerRegistry = new ControllerRegistry(expressApp); }); afterEach(() => { jest.clearAllMocks(); - process.env = originalEnv; }); it('should registered the mock controllers correctly', () => { @@ -30,16 +26,12 @@ describe('Test the ControllerRegistry class implementation', () => { expect(findRouter(expressApp).length).toBe(2); }); - it('should warn an error correctly when register a duplicated controller', () => { + it('should warn an error when register a duplicated controller', () => { jest.spyOn(console, 'warn').mockImplementation(jest.fn()); controllerRegistry.register(new MockIndexController()); controllerRegistry.register(new MockIndexController()); - // It should not warn when NODE_ENV is production - process.env.NODE_ENV = 'production' - controllerRegistry.register(new MockIndexController()); - expect(console.warn).toBeCalledTimes(1); });