3.0.2 • Published 2 years ago

@umecode/di-container v3.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

DI container

It's very simple DI Container without injection into class with meta-data with typesript

Injection into object param through proxy

Install

 cnpm i @umecode/di-container -S
 npm i @umecode/di-container --save
 yarn add @umecode/di-container

API

Container

constructor({injectPrefix?: string = '$'})
register(name: ContainerName<T>, (Proxy<params>) => any, options: RegistrationOptions)
get(name: ContainerName<T>, params?: Record<string, any>)
inject(value: (Proxy<params>) => T, params?: Record<string, any>): T 
unregister(name: ContainerName<T>)

type ContainerName

containerName<ReturnType, ParametersType> = string | symbol<ReturnType, ParametersType>

type RegistrationOptions

{
  singleton?: boolean = false, //On first get it will stored and after return stored value
  aliases?: Iterable<string | Symbol<T>>, //Any aliases for get
  inject?: boolean = true, // If true, container will try map params name to registered items
  params?: Record<string, any> //this object will pass into class constructor or function call, ignored for other value types
}

Usage

Create container

import { Container, ContainerName } from '@umecode/di-container'

const container = new Container()

You can use Symbols or strings as keys, but only with Symbols result will auto typed

// Use Symbols keys for auto typing result
const someKey = Symbol() as ContainerName<ISomeClass>

container.register(someKey, () => new SomeClass())
// Somewhere...
const instance: ISomeClass = container.get(someKey) // It's autotyped for ISomeClass becouse of Symbol key

// Or use string keys but return type need set manually
container.register('something', () => 'anything')
// Somewhere...
const test: string = container.get<string>('something') // anything

Typing callback params into symbol name

// Use Symbols keys for auto typing result
const someKey = Symbol() as ContainerName<ISomeClass, {name: string, service?: ISomeService}>

container.register(someKey, (params: {name: string, service?: ISomeService}) => new SomeClass(params))
// Somewhere...
const instance: ISomeClass = container.get(someKey, {name: '222'}) // It's autotyped for ISomeClass and for params type too

Register as singletons

const filesystem = Symbol() as ContainerName<IFileSystem>

container.register(filesystem, () => new SomeFileSystemClass(), {singleton: true})

const SomeClassInstance: IFileSystem = container.get(filesystem)
const SomeClassInstance2: IFileSystem = container.get(filesystem)

SomeClassInstance === SomeClassInstance2 // true

Inject by params keys Proxy(params) allow get by keys registered containers from params object

import {Container, ContainerKey} from '@umecode/di-container'

const container = new Container()

const key = Symbol() as ContainerKey<ISomeClass>
// Register anything with string keys or aliases
container.register(key, params => new SomeClass(), {aliases:['someClass']})
container.register('someClass2', params => new SomeClass2())

// Manual inject into param functions
// Params object is Proxy on params with getters for someClass and someClass2:
const res = container.inject(({someClass: ISomeClass}) => {
  // someClass is container.get('someClass')
})

const res2 = container.inject(({someClass: ISomeClass, ...other}) => {
  // someClass is container.get('someClass')
  // other is {param1: '1', param2: 2}
}, {param1: '1', param2: 2})

// Auto inject into param functions will be for any container.get()

class TestClass {
  constructor({}: {someClass: ISomeClass, someClass2: ISomeClass2}) {
    
  }
}

const test = container.inject(params => new TestClass(params))
// Same as const test: TestClass = new TestClass({someClass: new SomeClass(), someClass2: new SomeClass2()})

// If you use only Symbol keys it can be like this
const test2 = container.inject(params => new TestClass(params), {someClass: key})
// Same as const test2: TestClass = new TestClass({someClass: container.get(key), someClass2: new SomeClass2()})

// Or you can register TestClass too
container.register('testClass', params => TestClass(params))

const test3 = container.get<TestClass>('testClass')
// Same as const test3: TestClass = new TestClass({someClass: new SomeClass(), someClass2: new SomeClass2()})

You can set up injectPrefix for props

const container = new Container({injectPrefix: '$'})
  
...

class Test {
  constructor({$service, service}: {$service: SomeService, service: number[]}) {
  }
}

const test = container.inject(params => new Test(params), {service: [1, 2, 3, 4]})
// const test: Test = new Test({$service: container.get('service'), service: [1, 2, 3, 4]})

Be careful: It can be unhandled (you need handle it manually) RangeError circular throw error, if you call circular injection like this

class SomeClass {
  constructor({prop}: {prop: SomeClass}) {}
}

Develop

  1. npm run dev
  2. npm run build
  3. npm run test
3.0.2

2 years ago

3.0.1

2 years ago

3.0.0

2 years ago

2.1.4

2 years ago

2.1.3

2 years ago

2.1.2

2 years ago

2.1.1

2 years ago

2.1.0

2 years ago

2.0.2

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.3.0

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.0

2 years ago