nestjs-multi-provider v0.3.2
NestJS patch for multi provider pattern
This package patches the Nest.js Module decorator so that you can
somewhat straightforwardly use the multi-provider pattern. This package lets you specify
the multi flag to providers. You can then collect these providers into an array using
the collect function in the imports attribute of a target module, and inject the
collected array of provided values anywhere in the target module.
Installation
npm install nestjs-multi-providerUsage
A full example is available here.
On the first line of your root module file (most likely src/app.module.ts), import the
package to activate the patch:
import 'nestjs-multi-provider';Note: This package monkey-patches the Module decorator, if for some reason you
can't, see the failsafe method.
1. Provide
Simply use any of the provider patterns NestJS supports, and add the multi property. You
can do this from any module, any amount of times. All the providers will ultimately be
available under the same token as an array of provided values.
@Module({
providers: [
{provide: SOME_TOKEN, useClass: SomeService, multi: true},
{provide: SOME_TOKEN, useClass: SomeServiceWithDeps, multi: true, standalone: false},
]
})Important: If your provider has dependencies, you must set standalone to false.
2. Collect
To access all your providers, use the collect function:
@Module({
imports: [collect(SOME_TOKEN)]
})
export class CollectingModule {}3. Inject
You can now inject your array of providers anywhere inside of CollectingModule:
export class SomeServiceInCollectingModule {
constructor(@Inject(SOME_TOKEN) collection: any[]) {
console.log("Collected:", collection)
// This will print `Collected: [SomeService {}, SomeServiceWithDeps {}]`
}
}Using the failsafe decorator
Instead of using the patched Module decorator, you can also decorate any modules that
provide multi-providers with the ModuleWithMulti decorator:
import { ModuleWithMulti } from "nestjs-multi-provider";
@ModuleWithMulti({
providers: [{provide: "something", useValue: 1, multi: true}]
})
export class MyModule {}During testing
I have noticed during testing that the monkey patch doesn't always function because certain statements may be hoisted above the patch. You can overcome this by creating a statement that itself will be hoisted. For example, for Jest:
import { ModuleWithMulti } from "nestjs-multi-provider";
jest.mock('@nestjs/common', () => {
const nestjsCommon = jest.requireActual('@nestjs/common');
return {
...nestjsCommon,
Module: ModuleWithMulti,
};
});Important notes
- Your providers are not available unless you use
collect. collectcreates aDynamicModuleand therefor must be placed in theimportsproperty.- Your providers are by default considered
standalone(not having any dependencies), and are not actually provided by the module they are declared in, but by the collectingDynamicModule. This is done to avoid creating needless dependencies between modules. - If your provider has dependencies, set
standalonetofalseto have access to the declaring module's providers. Doing this will result in aforwardRefof the declaring module by the collecting module. - Multi providers are not supported in
DynamicModules.