npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@umecode/di-container

v3.0.2

Published

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

Downloads

17

Readme

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