0.0.5 • Published 5 years ago

@bittrd/siccly v0.0.5

Weekly downloads
-
License
ISC
Repository
github
Last release
5 years ago

Siccly - Simple Inversion of Control Container

npm (scoped) Build Status Coverage Status Conventional Commits

Usage

Container

Create your di container file (I like to start simple with a siccly.ts file in the root of my project).

You can put these files wherever works for you though if you want more structure.

// "src/siccly.ts"
import { Kernel } from '@bittrd/siccly';
import { TYPES } from './types';
import { MyClass } from './my-class';
import { MyInterfaceImplementation } from './my-interface-implementation';
export const container = new Kernel();

container.bind(TYPES.MyInterface).toSingleton(MyInterfaceImplementation);
container.bind(MyClass).toClass(MyClass);

Types

In addition to the container, you need a place to handle interfaces as they are not value types in javascript the way objects are. (I usually create a types.ts file next to siccly.ts)

// "src/types.ts"
import { Type } from '@bittrd/siccly';
import { MyInterface } from './my-interface';
export const TYPES = {
  MyInterface: Type<MyInterface>('MyInterface'),
};

Interfaces

Interfaces are easy, create them as you normally would. They get annotated using the Type<T> helper function inside of "src/types.ts" see Types

// "src/my-interface.ts"
export interface MyInterface {
  isAwesome(): boolean;
}

Classes

Classes are just as easy, and need no extra annotation. They can be passed directly into the bind methods on the kernel as-is.

// "src/my-class.ts"
export class MyClass {
  isNifty(): boolean {
    return true;
  }
}

Injection

In order to use injection in your class, create it as you normally would. Then add a static inject = [] with an array of the types in order that you want injected into your constructor.

// "src/my-interface-implementation.ts"
import { MyInterface } from './my-interface';
import { MyClass } from './my-class';
export class MyInterfaceImplementation implements MyInterface {
  static inject = [MyClass];
  constructor(private readonly nifty: MyClass) {}
  public isAwesome(): boolean {
    return this.nifty.isNifty();
  }
}

Binding

In order for a class or interface to be usable from the DI container, you have to bind your interfaces/classes to their implementations.

Transient

To bind a class in transient scope, use one of the following methods.

import { Kernel } from '@bittrd/siccly';
import { MyClass } from './my-class';
import { MyInterface } from './my-interface';
import { TYPES } from './types';
const container = new Kernel();

// Default bind call with interface as first argument and implementation class as second.
container.bind(MyClass, MyClass);
// Method chaining with interface as argument to bind and implementation as argument to toClass
container.bind(MyClass).toClass(MyClass);
// With interface example.
container.bind(TYPES.MyInterface, MyClass);
container.bind(TYPES.MyInterface).toClass(MyClass);

Singleton

To bind a class in singleton scope, use one of the following methods.

import { Kernel } from '@bittrd/siccly';
import { MyClass } from './my-class';
import { MyInterface } from './my-interface';
import { TYPES } from './types';
const container = new Kernel();

// Method chaining with interface as argument to bind and instance of the object as argument to toSingleton
container.bind(MyClass).toSingleton(new MyClass());
// With interface example.
container.bind(TYPES.MyInterface).toSingleton(new MyClass());