@maca134/async-syringe
v3.0.1
Published
Lightweight dependency injection container for TypeScript with async support
Downloads
2
Maintainers
Readme
AsyncSyringe
Based on tsyringe but with support for async factories/init and does not use any global variables.
Installation
Install by npm
npm install --save @maca134/async-syringe
or install with yarn
yarn add @maca134/async-syringe
Modify your tsconfig.json
to include the following settings
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
Add a polyfill for the Reflect API (examples below use reflect-metadata). You can use:
The Reflect polyfill import should only be added once, and before before DI is used:
// main.ts
import 'reflect-metadata';
// Your code here...
Examples
Working examples can be found in the root folder. Here is the code:
Simple
import 'reflect-metadata';
import { injectable, StandardKernel } from '../..';
import { inject } from '../../decorators/inject';
import { singleton } from '../../decorators/singleton';
(async () => {
class Foo1 {}
// indicates only 1 instances of this class will be created
@singleton()
class Foo2 {}
// injectable decorator is only needed when there are constructor parameters
@injectable()
class Bar {
constructor(
public foo1: Foo1,
public foo2: Foo2,
@inject('value') public foobarFromValue: string,
@inject('factory') public foobarFromFactoryValue: string,
@inject('token') public foobarFromTokenFactoryValue: string
) {}
}
const container = new StandardKernel();
container.registerValue('value', 'foobarValue');
container.registerFactory('factory', (kernel) => kernel.resolve('value'));
container.registerToken('token', 'factory');
// A token can be resolved without being registered if it is a class constructor
console.log(await container.resolve(Bar));
/*
Bar {
foo1: Foo1 {},
foo2: Foo2 {},
foobarFromValue: 'foobarValue',
foobarFromFactoryValue: 'foobarValue',
foobarFromTokenFactoryValue: 'foobarValue'
}
*/
})();
Class Initializing
import 'reflect-metadata';
import { injectable, StandardKernel } from '../..';
(async () => {
// to use initialize properly the decorator needs to be typed.
// the initialize function can be a promise
@injectable<Bar>({ initialize: (instance) => instance.init() })
class Bar {
init(): Promise<any> {
return new Promise((resolve) => setTimeout(() => resolve(), 4000));
}
}
@injectable()
class Foo {
constructor(public bar: Bar) {}
}
const container = new StandardKernel();
console.log(await container.resolve(Foo));
/*
...4s...
Foo { bar: Bar {} }
*/
})();
Factories
import 'reflect-metadata';
import { injectable, StandardKernel } from '../..';
import { autoFactory } from '../../decorators/autoFactory';
import { Factory } from '../../Factory';
(async () => {
@injectable()
class Foo {
constructor(
public bar: string,
public foobar: number
) {}
}
@injectable()
class Bar {
constructor(@autoFactory(Foo) public fooFactory: Factory<typeof Foo>) {}
}
const container = new StandardKernel();
const bar = await container.resolve(Bar);
console.log(await bar.fooFactory.create('bar', 1337));
/*
Foo { bar: 'bar', foobar: 1337 }
*/
})();