noicejs is a dependency injection library, loosely inspired by Google’s Guice library, with no runtime dependencies - bundled or otherwise.
It has full support for async constructors and factories, and uses decorators to mark fields for injection.
Status
noicejs is actively maintained and mostly stable. There are a few features I would like to add still, especially around field injection, but the core API has been consistent since v2 was released in early 2018. Most of the breaking changes since have been related to NodeJS version support and adoption of new Typescript features.
Example
noicejs starts with a DI container, which uses modules to provide the dependencies being injected. Modules can bind constructors or provide factories, which allows something like asynchronous constructors.
import { Cache, Filesystem } from './interfaces';
import { LocalModule } from './local';
import { NetworkModule } from './network';
@Inject(Cache, Filesystem)
class Foo {
protected readonly cache: Cache;
protected readonly filesystem: Filesystem;
constructor(options) {
this.cache = options.cache;
this.filesystem = options.filesystem;
}
get(path: string) {
return options.cache.get(path, () => options.filesystem.get(path));
}
}
function module() {
if (process.env['DEBUG'] === 'TRUE') {
return new LocalModule();
} else {
return new NetworkModule();
}
}
function main() {
const container = Container.from(module());
await container.configure();
/* cache and filesystem are created and injected by the container */
const foo = await container.create(Foo);
}
Further Reading
Using dependency injection helps you keep classes loosely coupled and removes the need for ES modules that create and export a singleton, which are extremely difficult to test. In general, DI should make testing easier, as it decouples classes and their consumers and makes mocking easier.