dependory
v1.0.1
Published
A simple, yet powerful framework to add dependency injection to your TypeScript project.
Downloads
3
Maintainers
Readme
Dependory
A very simple, yet powerful tool to add and integrate dependency injection
to your TypeScript projects using decorators.
Prerequisites
tsconfig.json
To use TypeScript decorators, you have to enable them in your tsconfig.json
:
{
"compilerOptions": {
...
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
...
}
}
experimentalDecorators
allows you to use decorators in your TypeScript code and emitDecoratorMetadata
allows the framework to get the metadata needed for dependency injection (like types) during runtime.
Installation
Simply install this package over npm:
$ npm i dependory
Usage
Singletons
To make use of the provided features of dependency injection, just add the decorator @Singleton()
to a class:
import { Singleton } from "dependory";
@Singleton()
export class OtherClass {
public foo: string;
constructor() {
this.foo = "bar";
}
}
In another class, where you want to inject OtherClass
, to the same:
import { Singleton } from "dependory";
import { OtherClass } from "./otherClass";
@Singleton()
export class MyClass {
constructor(a: OtherClass) {
console.log(a.foo);
}
}
The framework will create singletons of both classes, and inject the singleton of OtherClass
into the constructor of MyClass
during its creation. To make use of this in an existing project, just refactor all classes to use the decorators and point node
to your entry-file, the framework will create everything for you.
Transients ("Non-Singletons")
If you want to inject classes as non-singletons/transients instead of singletons, so a new instance gets created upon each injection, you can use the @Transient()
-decorator.
import { Transient, Singleton } from "dependory";
// An instance gets created upon each injection
@Transient()
export class MyClass {
private foo: string;
constructor() {
this.foo = "bar";
}
}
// Only one instance will get created for all injections
@Singleton()
class Test {
// 2 different instances get injected
constructor(a: MyClass, b: MyClass) {
console.log(a === b); // false
}
}
Note: The injection in the constructor of the decorated classes will still happen.
Custom Registry
If you want to use a custom registry (not the default one), you can specify it in the decorator:
import { Singleton, Registry } from "dependory";
const myRegistry = new Registry();
@Singleton({
registry: myRegistry
})
export class MyClass {
private foo: string;
constructor() {
this.foo = "bar";
}
}
@Transient({
registry: myRegistry
})
export class MyOtherClass {
private clazz: MyClass;
constructor(clazz: MyClass) {
this.clazz = clazz;
}
}
Doing this, this class will be stored in your custom registry and not the the default one. This it also allows you, to scope your injections per module.
Inject class properties
If you only want to inject certain properties of a class, you can apply the @Inject()
decorator to this properties.
@Inject()
takes an optional parameter, which current allows you to specify the registry, from which the value to inject shall be taken from.
import { Singleton, Inject, Registry } from "dependory";
// Create an own registry for scoping our injections
const myRegistry = new Registry();
@Singleton({
registry: myRegistry
})
class MyTestClass {
public foo = "bar";
}
class MyClass {
@Inject({
registry: myRegistry
})
public test: MyTestClass;
}
const myInstance = new MyClass();
console.log(myInstance.test.foo); // "bar"
If registry
is not provided, it will default to the general library, which gets used by the framework by default.
Inject constructor parameters
If you want to inject concrete parameters from specific registries into the constructor, you can achieve this with @Inject()
aswell. Just decorate the parameter in the constructor:
import { Singleton, Inject, Registry } from "dependory";
const myRegistry = new Registry();
// We chain the decorators, so we create 2 different singletons in 2 different registries
// See "Decorator-Chaining" for details about this
@Singleton({
registry: myRegistry
})
@Singleton()
class MyTestClass {
public foo = Math.random();
}
// Inject the general constructor parameters from the default registry
@Singleton()
class MyClass {
constructor(
a: MyTestClass,
// Inject the second parameter from another registry
@Inject({
registry: myRegistry
})
b: MyTestClass
) {
console.log(a.foo === b.foo); // false
}
}
Note: The concretely injected parameters override the parameters, that get automatically injected by the framework!
Inject via custom key
If you want to register and inject properties or parameters via custom keys, you can specify them in via the injection properties:
@Singleton({
key: "myInjectionKey"
})
class MyClass {
//
}
@Singleton()
class MyOtherClass {
@Inject({
key: "myInjectionKey"
})
private value: any;
}
Note: The custom key will always overwrite the class hash (the default value for a class to be injected with).
Decorator-Chaining
By default, you can chain the decorators in combination with different registries, to store classes both as singletons and as transients.
import { Singleton, Transient, Inject, Registry } from "dependory";
const myRegistry = new Registry();
@Transient({
registry: myRegistry
})
@Singleton()
class MyClass {
public value: numer;
constructor() {
this.value = Math.random();
}
}
@Singleton({
registry: myRegistry
})
class MyOtherClass {
@Inject()
private a: MyClass;
@Inject()
private b: MyClass;
constructor(c: MyClass, d: MyClass) {
console.log(this.a.value === this.b.value); // true
console.log(c.value === d.value); // false
}
}