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

@ukitgroup/ioc

v1.1.6

Published

Declarative and simple IoC container

Downloads

14

Readme

IoC-container

Declarative and simple IoC container for node.js applications

Travis Coverage Status Greenkeeper badge node npm

GitHub top language GitHub code size in bytes David David

license GitHub last commit semantic-release

Usage

import { IoCContainer } from '@ukitgroup/ioc';

class ServiceA {}

// First of all you have to define DI config:
const moduleManifest = {
 moduleName: 'module',
 providers: [
   {
	 isPublic: true,
	 token: 'serviceA',
	 useClass: ServiceA,
   },
 ],
};


// Then in your composition root just create container
const container = new IoCContainer();
container.loadManifests([moduleManifest]);
container.compile();

Provider types

You can provide by concrete realization with several ways:

class ServiceA {
  constructor(serviceB) {
   this.serviceB = serviceB;
  }
}

// Dependencies will be resolved and injected to instance automatically
const providerByClass = {
	token: 'serviceA',
	useClass: ServiceA,
	dependencies: ['ServiceB']
};

// You can provide constant value
const providerByValue = {
	token: 'connectionUri',
	useValue: 'mongodb://uri',
};

// You can provide by factory function
// Also resolved dependencies will be resolved automatically
const providerByFactory = {
	token: 'ServiceA',
	useFactory: (serviceB) => {
	  return new ServiceA(serviceB)
	},
	dependencies: ['ServiceB']
};

Public/Private scope

By default all providers define in private scope. If you want to use provider from another module you should define this provider as public

const moduleAManifest = {
  moduleName: 'moduleA',
  providers: [
	{
	  isPublic: true,
	  token: 'ServiceA',
	  useClass: ServiceA,
	},
  ],
};

const moduleBManifest = {
  moduleName: 'moduleB',
  providers: [
	{
	  isPublic: true,
	  token: 'ServiceC',
	  useClass: ServiceC,
	  dependencies: [
		// You should define which module this provider from
		['ServiceA', { fromModule: 'moduleA' }],
	  ],
	},
  ],
};

Class Factory (AutoFactory)

There are some cases when you want create instances in code i.e: Entities, Command pattern

It's very simple if your class doesn't have dependencies so you can create instance just in you code:

class Entity {
  constructor(name) {
    this.name = name;
  }
}

class Example {
  doSomething() {
    const a = new Entity('test');
    // ...
  }
}

But there are some cases when this class has dependencies and you can't just create object because you have to transmit resolved provider. Fortunately we are codding with Javascript and so we can follow js way :)

class Entity {
  constructor(service, name) {
    this.service = service;
    this.name = name;
  }
}

class Example {
  // You can inject Constructor with resolved dependencies
  constructor(Entity) {
    this.Entity = Entity;
  }
  
  doSomething() {
    // Now you still have to provide rest arguments
    // And all dependencies has already resolved
    const a = new this.Entity('test');
    // ...
  }
}

// Of course there are some config parameters to make this magic work :)
const moduleManifest = {
  moduleName: 'moduleB',
	providers: [
	  {
		isPublic: true,
		token: 'Entity',
		useClass: Entity,
		dependencies: [
		  // You should define which module this provider from
		  ['ServiceA', { autoFactory: true }],
		],
	  },
	  {
	    token: 'ServiceA',
	    // To make it clear you should define in both "autoFactory: true"
	    autoFactory: true,
	    useClass: ServiceA,
	  }
	],
}

Composition root

Usually you have composition root in you application. It's the only place where you can use container.get

const moduleManifest = {
 moduleName: 'moduleA',
 providers: [
   //... other providers
   {
	 isPublic: true,
	 token: 'httpPort',
	 useValue: 3000,
   },
 ],
};

const container = new IoCContainer();
container.loadManifests([moduleManifest]);
container.compile();

// You can get only public providers
const port = container.get('moduleA', 'httpPort');
http.listen(port);

Testing

We provide a comfortable way for testing

import { TestIoCContainer } from '@ukitgroup/ioc';
describe('Unit test', () => {
	const ctx = {}
	
	beforeEach(() => {
		ctx.container = TestIoCContainer.createTestModule([
		  //... providers definition with mocks
		])
		ctx.container.compile();
	});
	
	it('test case', () => {
	  // Here you can just get provider by token
	  // You don't have to transmit module name
	  const provider = ctx.container.get('providerToken');
	});
})

IDE will help you

if you don't use typescript, type hinting still can help you: example

Just be sure that you use type definitions only from ./public-interfaces. Internal types can be changed not in major release

More examples you can find in integration tests

TODO:

  • support decorators with typescript
  • TestIoCContainer for integration tests
  • Get public providers by tag