diff --git a/lib/createHandler.ts b/lib/createHandler.ts index a8a42ada..57099a25 100644 --- a/lib/createHandler.ts +++ b/lib/createHandler.ts @@ -9,6 +9,7 @@ import { parseRequestUrl } from './internals/parseRequestUrl'; * Prepares a router for the given class. * * @param cls Router class + * @param builder Router instance builder * * @example * ```ts @@ -24,15 +25,22 @@ import { parseRequestUrl } from './internals/parseRequestUrl'; * export default createHandler(Events); * ``` */ -export function createHandler(cls: new (...args: any[]) => any): NextApiHandler { - const instance = new cls(); +export function createHandler( + cls: new (...args: any[]) => T, + builder: () => T | Promise = () => new cls() +): NextApiHandler { + let instance: any; const [directory, fileName] = getCallerInfo(); - return (req: NextApiRequest, res: NextApiResponse) => { + return async (req: NextApiRequest, res: NextApiResponse) => { if (!req.url || !req.method) { return notFound(req, res); } + if (!instance) { + instance = await builder(); + } + const path = parseRequestUrl(req, directory, fileName); const [keys, match, method] = findRoute(cls, req.method, path); if (!method) { diff --git a/package.json b/package.json index 5084e08c..2f143562 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "express": "^4.17.1", "express-rate-limit": "^6.0.4", "husky": "8.0.3", + "inversify": "5.1.1", "jest": "26.6.3", "lint-staged": "13.1.0", "multer": "^1.4.2", diff --git a/test/e2e-ioc.test.ts b/test/e2e-ioc.test.ts new file mode 100644 index 00000000..b4d0521a --- /dev/null +++ b/test/e2e-ioc.test.ts @@ -0,0 +1,56 @@ +import 'reflect-metadata'; +import { Container, injectable } from 'inversify'; +import request from 'supertest'; +import { createHandler, Get } from '../lib'; +import { setupServer } from './setupServer'; + +// Create service +const container = new Container({ + autoBindInjectable: true +}); + +interface TestData { + test: string; +} + +@injectable() +export class TestService { + public getTest(): TestData { + return { + test: 'successful' + }; + } +} + +// Create handler with injection +@injectable() +class TestHandler { + public constructor(private readonly service: TestService) {} + + @Get() + public testData() { + return this.service.getTest(); + } +} + +describe('E2E - ioc', () => { + let server: ReturnType; + beforeAll(() => (server = setupServer(createHandler(TestHandler, () => container.get(TestHandler))))); + afterAll(() => { + if ('close' in server && typeof server.close === 'function') { + server.close(); + } + }); + + it('Should successfully return data from service', () => + request(server) + .get('/') + .expect(200) + .then(res => + expect(res).toMatchObject({ + body: { + test: 'successful' + } + }) + )); +}); diff --git a/yarn.lock b/yarn.lock index 1432f649..d7f99ec0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4264,6 +4264,11 @@ into-stream@^6.0.0: from2 "^2.3.0" p-is-promise "^3.0.0" +inversify@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.1.1.tgz#6fbd668c591337404e005a1946bfe0d802c08730" + integrity sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ== + ip-regex@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"