Feature request - Add "scoped" lifetime

#79 · closed · 1 comments

View on GitHub ↗

edosrecki

Next to "singleton", and "transient", add "scoped" lifetime, which resolves to a new instance inside each new child injector. ### Example usage ```ts import { createInjector, Scope, tokens } from 'typed-inject' let counter = 0 function count() { counter++ console.log('called count', counter) } // Root injector registers "count" with "scoped" lifetime const rootInjector = createInjector() .provideFactory('count', count, Scope.Scoped) console.log('rootInjector') // count is a singleton within rootInjector rootInjector.resolve('count') rootInjector.resolve('count') const childInjector1 = rootInjector.createChildInjector() console.log('childInjector1') // count is a singleton within childInjector1 childInjector1.resolve('count') childInjector1.resolve('count') const childInjector2 = rootInjector.createChildInjector() console.log('childInjector2') // count is a singleton within childInjector2 childInjector2.resolve('count') childInjector2.resolve('count') ``` **Expected Output** ``` rootInjector called count 1 childInjector1 called count 2 childInjector2 called count 3 ``` ### Justification Imagine this being used combined with `fastify`. This would allow us to register all dependencies in one place (`rootInjector`) with correct lifetime. Then we could implement `onRequest` hook which creates a new child injector and attaches it to fastify request object. This would allow use to use this child injector in controllers to get a singleton instance scoped to each new request. ```ts const rootInjector = createInjector() .provideFactory('count', count, Scope.Scoped) fastify.decorate('rootInjector', rootInjector) fastify.decorateRequest('scopedInjector', null) // Hook, this code can be inside a plugin fastify.addHook('onRequest', async (request) => { request.scopedInjector = rootInjector.createChildInjector() }) fastify.get('/', opts, (request, reply) => { // we use scoped injector to get new instance for each request request.scopedInjector.resolve('count') // rootInjector can still be used for stuff which doesn't need to be scoped to each request fastify.rootInjector.resolve('foo') }) ``` I would like to implement a plugin for 'typed-inject' similar to `fastify-awilix`, and this would allow people to register the plugin, and then import the rootInjector and register all dependencies on it with correct scope. ### Workaround This is doable with `typed-inject` but would require us to register "scoped" dependencies separately from other dependencies, by registering them inside "onRequest" hook. ```ts fastify.addHook('onRequest', async (request) => { request.scopedInjector = rootInjector.createChildInjector() .provideFactory('count', count, Scope.Singleton) }) ```

Comments

edosrecki

Sorry, I misunderstood how typed-inject works, managed to implement this easily in a nice way.