dependency-injection-cat
Dependency Injection Cat is a TypeScript-only library which allows you to implement
the Dependency Inversion pattern with Dependency Injection
Installation
Yarn
yarn add dependency-injection-cat
NPM
npm install dependency-injection-cat
Config options
interface TransformerConfig {
diConfigPattern?: string;
ignorePatterns?: string[];
}
Configuration with Webpack
Dependency Injection Cat supports transpileOnly mode for faster builds! More Info
With Webpack, You can use any TypeScript-related loader that supports custom transformers, e.g. awesome-typescript-loader or ts-loader
webpack.config.js
const dependencyInjectionCatTransformer = require('dependency-injection-cat/transformer').default;
module.exports = {
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
transpileOnly: true,
compiler: 'ttypescript',
getCustomTransformers: program => ({
before: [
dependencyInjectionCatTransformer(program),
],
}),
},
},
],
},
};
With custom options
In webpack.config.js you can pass a second parameter to the transformer:
before: [
dependencyInjectionCatTransformer(program, {
diConfigPattern: '**/config/**/*.diconfig.ts'
})
]
Configuration with ttypescript
Check out ttypescript's README for more information
tsconfig.json
{
"compilerOptions": {
"plugins": [
{
"transform": "dependency-injection-cat/transformer"
}
]
}
}
With custom options
{
"compilerOptions": {
"plugins": [
{
"transform": "dependency-injection-cat/transformer",
"diConfigPattern": "**/config/**/*.diconfig.ts"
}
]
}
}
Usage
import { Bean, Qualifier } from 'dependency-injection-cat';
import { IRequester } from '../IRequester';
import { Requester } from '../Requester';
import { ILogger } from '../ILogger';
export class Requesters {
@Bean
requester(logger: ILogger): IRequester {
return new Requester(logger);
}
requester = Bean<IRequester>(Requester);
}
import { Bean } from 'dependency-injection-cat';
import { ILogger } from '../ILogger';
import { Logger } from '../Logger';
export class Loggers {
@Bean
logger(): ILogger {
return new Logger();
}
@Bean
logger = Bean<ILogger>(Logger);
}
import { container } from 'dependency-injection-cat';
import { IRequester } from './IRequester';
const requester = container.get<IRequester>();
requester.makeRequest();
Bean
Rules
- Bean should be a class member (property or method)
- Beans should not have cyclic dependencies (it will throw compilation error)
- Beans should not have duplicate declarations
- Beans can be used only in diconfig.ts files (or files with another pattern declared in transformer config)
- Bean type should not be empty (it will throw compilation error)
- Bean type should not be primitive (it will throw compilation error)
- All bean dependencies should be typed, and type should not be primitive
Syntax
Beans support 2 kinds of syntax
First
import { Bean } from 'dependency-injection-cat';
class SuperClass {
@Bean
someMethod(): Interface {
return new ImplementationOfInterface();
}
@Bean
someMethod(
dependency1: InterfaceOfDependency1,
dependency2: InterfaceOfDependency2,
): Interface {
return new ImplementationOfInterface(dependency1, dependency2);
}
@Bean({ qualifier: 'someCoolImpl', scope: 'prototype' })
someMethod(
dependency1: InterfaceOfDependency1,
dependency2: InterfaceOfDependency2,
): Interface {
return new ImplementationOfInterface(dependency1, dependency2);
}
@Bean
someMethod = (): Interface => new ImplementationOfInterface();
@Bean
someMethod(): number | string | any {
return new ImplementationOfInterface();
}
@Bean
someMethod(
dependency1: InterfaceOfDependency1,
): Interface {
return new ImplementationOfInterface(dependency1);
}
@Bean
someMethod2(
dependency1: Interface,
): InterfaceOfDependency1 {
return new ImplementationOfDependency(dependency1);
}
}
Second
import { Bean } from 'dependency-injection-cat';
class SuperClass {
someBeanProperty = Bean<Interface>(ImplementationOfInterface);
someBeanProperty = Bean<Interface>(ImplementationOfInterface, { qualifier: 'someCoolImpl' });
}
Bean configuration object
interface BeanConfiguration {
scope?: 'prototype' | 'singleton';
qualifier?: string;
}
Qualifier
What is it?
In fact, Qualifier it's just a name of Bean
You can use it, if you have a few different implementations of interface
Rules
- Qualifier should be a string
- Qualifier should not be empty string
- Qualifier should not be dynamically calculated (no template strings, or references to constants/object properties)
Syntax
import { Bean, Qualifier } from 'dependency-injection-cat';
class SuperClass {
@Bean
someMethod(
@Qualifier('someQualifier') dependency1: InterfaceOfDependency1,
): Interface {
return new ImplementationOfInterface();
}
}
import { Bean, Qualifier } from 'dependency-injection-cat';
const superQualifierName = 'superQualifierNameValue';
class SuperClass {
@Bean
someMethod(
@Qualifier(superQualifierName) dependency1: InterfaceOfDependency1,
): Interface {
return new ImplementationOfInterface();
}
@Bean
someMethod(
@Qualifier('') dependency1: InterfaceOfDependency1,
): Interface {
return new ImplementationOfInterface();
}
}
Container
Container has only one method "get"
Rules
- You should pass type as generic in get method of Container
Syntax
import { container } from 'dependency-injection-cat';
const someBean = container.get<Interface>();
const someBean = container.get<Interface>('someQualifier');
Author
License
This project is under the MIT License