diff --git a/README.md b/README.md index c516e61..9f66b1a 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,31 @@ await app.ready() For more advanced use cases, check the official [awilix documentation](https://github.com/jeffijoe/awilix). +## Defining awilix dependencies in plugins + +Relying on dependency injection in plugins is problematic, because plugins cannot know upfront how they can resolve dependencies from a fastify application. + +For this purpose there is a helper class available in `@fastify/awilix`: + +```ts +import { FastifyDependencyProvider } from '@fastify/awilix' + +app = fastify({ logger: true }) +await app.register(fastifyAwilixPlugin, { + container: diContainer, +}) +app.diContainer.register({ + maxUserName: asValue('username'), +}) + +// ... + +function plugin (fastify, opts, next) { + const maxUserName = resolveDependencyFromApp(fastify, 'maxUserName') + // 'username' +} +``` + ## License Licensed under [MIT](./LICENSE). diff --git a/lib/fastifyAwilixPlugin.js b/lib/fastifyAwilixPlugin.js index 037e81d..955a5c0 100644 --- a/lib/fastifyAwilixPlugin.js +++ b/lib/fastifyAwilixPlugin.js @@ -100,8 +100,13 @@ const fastifyAwilixPlugin = fp(plugin, { name: '@fastify/awilix' }) +function resolveDependencyFromApp (app, dependencyKey) { + return app.diContainer.resolve(dependencyKey) +} + module.exports = { diContainer: diContainerProxy, + resolveDependencyFromApp, diContainerProxy, diContainerClassic, fastifyAwilixPlugin diff --git a/lib/index.d.ts b/lib/index.d.ts index 3827595..4027ba1 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,5 +1,5 @@ import { AwilixContainer } from 'awilix' -import { FastifyPluginCallback } from 'fastify' +import { FastifyInstance, FastifyPluginCallback } from 'fastify' import { AwilixManager } from 'awilix-manager' export interface Cradle {} @@ -17,6 +17,11 @@ declare module 'fastify' { } } +/** + * Tries to resolve the dependency and throws an error if it fails + */ +export function resolveDependencyFromApp (app: FastifyInstance, dependencyKey: string): T + export type FastifyAwilixOptions = { disposeOnResponse?: boolean disposeOnClose?: boolean diff --git a/test/fastifyAwilixPlugin.test.js b/test/fastifyAwilixPlugin.test.js index b86ec2a..4873090 100644 --- a/test/fastifyAwilixPlugin.test.js +++ b/test/fastifyAwilixPlugin.test.js @@ -6,6 +6,7 @@ const { describe, it, afterEach } = require('node:test') const assert = require('node:assert') const { diContainer, diContainerClassic, fastifyAwilixPlugin } = require('../lib') +const { resolveDependencyFromApp } = require('../lib/fastifyAwilixPlugin') class UserServiceClassic { constructor (userRepository, maxUserName, maxEmail) { @@ -169,4 +170,21 @@ describe('fastifyAwilixPlugin', () => { await assert.rejects(app.ready(), /failed to init/) }) }) + + describe('FastifyDependencyProvider', () => { + it('resolves dependencies', async () => { + app = fastify({ logger: true }) + await app.register(fastifyAwilixPlugin, { + container: diContainer, + }) + app.diContainer.register({ + maxUserName: asValue('username'), + }) + + const maxUserName = resolveDependencyFromApp(app, 'maxUserName') + assert.equal(maxUserName, 'username') + + await app.close() + }) + }) })