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

microinject

v0.12.0

Published

A Tiny, standalone, library-friendly dependency injection.

Downloads

15

Readme

node-microinject

Microinject

A Tiny, standalone, library-friendly dependency injection container.

[Quick Start](/docs/Getting Started.md)

Background

This was made out of a requirement to use dependency injection for a complex middleware library. The primary driving force is to allow a library to use dependency injection locally without forcing changes to any upstream users of the library. This means:

  • No requirements for the invoking library to initialize reflect-metadata.
  • Support dependency injection when used on classes derived from non-DI-aware classes.
  • No monkey patching anything external to the library.
  • Minimum overhead.
  • Works if multiple libraries independently try to use it.
  • Works if npm installs multiple copies of the library.

Originally, I had used InversifyJS. However, it failed against the first three requirements. The original incarnation of this library was born as an api-compatible replacement to the subset of InversifyJS my projects were using. Despite this, microinject is not a fork. It has been written from the ground up, and borrows InversifyJS conventions where appropriate.

Design philosophy

This library intends to remain minimalist while still covering a decent set of use cases for dependency injection. As this is intended to be used transparently by middleware libraries, it will not receive features intended for application-level IoC.

Common features with InversifyJS

  • container.bind.to.
  • container.bind.toSelf.
  • container.bind.toConstantValue.
  • container.bind.toDynamicValue.
  • container.bind.toFactory identical to container.bind.toDynamicValue.
  • container.bind.*.inSingletonScope.
  • container.bind.*.inTransientScope.
  • container.get.
  • container.getAll.
  • ContainerModule(bind => {...}) - Only bind argument is supported.
  • container.load.
  • @injectable().
  • @inject(identifier) - Constructor and Property injection supported. Identifier must be specified; inject-by-type not supported.
  • @optional modifier for @inject.
  • @injectAll() = @inject(identifier, {all: true}).
  • child containers as childContainer.parent = parentContainer;;

New features over InversifyJS

  • Custom scopes: container.bind.[toScope | inScope] - create services shared based on other objects further up the chain.
  • Per-request parameters: Supply per-request options to constructed instance in addition to traditional bindings.
    • Constructor parameter injection: constructor(@injectParam("MyParam") myParam: string)
    • Supply parameters during object request: container.get(MyObjectIdentifier, {MyParam: "hello world"})
  • Decorator based binding: container.bind(ClassConstructor) will read annotations on the object:
    • Binding aliases: @provides(identifier).
    • As a singleton: @singleton.
    • Inside a custom scope: @inScope.
    • Defining a custom scope: @asScope.
    • Can be overridden by standard binding api.
  • Instantiate objects dynamically without bindings: container.create()
  • Provide a single binding for multiple identifiers (using @provides and bind().provides())
    • Simplify code by providing a single implementation while still keeping seperation of concerns with seperate identifiers.
  • No monkey patching required to extend NodeJS or third party classes.
  • No requirement for the root node application to call reflect-metadata. No risk of interfering with other modules that also use it.
  • Minimialist API: No redundant functions for varying names of the same behavior.
  • Lighter weight

Missing features from InversifyJS

  • unbinding / rebinding
  • tagged binding
    • Binding aliases (bind().provides()) provides a more flexible solution to this use case.
  • debug tools
  • async modules
  • async resolution
    • Use async provider objects instead: class FooProvider { async getFoo() { ... }}
  • snapshotting
  • Auto injection based on typescript typings
    • This requires using reflect-metadata and will not be supported.

Alternatives

  • InversifyJS - Typescript-based full featured Dependency Injection.
  • Electrolyte - A commonjs-centric dependency injection mechanism that functions at the module level.
  • typescript-ioc - Single-container global-scoped IOC using Typescript and reflect-metadata.

Which one should I choose?

If you are making a third party library for consumption by others, and want to avoid monkey patching, global state, and other leaky concepts, consider using microinject.

If your application generates a hierarchy of components where some components have multiple instances, and you need to share services within each instance, you may find microinject's scoped bindings useful.

If your application needs to pass instance specific data when generating multiple instances of the same identifier, microinject's parameter injection is what you need.

If you want your DI container to automatically determine your bindings from used types, use InversifyJS.

If you are working with older environments, or want to stay closer to the commonjs module format, use Electrolyte.

JS Environment Compatibility

The primary target of this library is NodeJS v10 and up. However, it will work with modern browsers or babel so long as Symbol and Map are supported.