← Back to archive

Repo of the Day

jeffijoe/awilix

Published: Jun 29, 2024

Open repository ↗

Extremely powerful Inversion of Control (IoC) container for Node.JS

Summary

Awilix is a dependency injection container for Node.js and the browser, written in TypeScript. It lets you register classes, factory functions, or plain values, then resolve them with explicit lifetime management (transient, scoped, or singleton).

What it is useful for

Awilix helps wire up application dependencies without special annotations on classes or functions. Concrete scenarios from the README include:

  • Building testable services. Classes and functions receive their dependencies through a proxy or named parameters, so unit tests can pass plain objects without invoking the container.
  • Per-request dependency scoping in web apps. A scoped container created per request holds request-specific values like currentUser, and Lifetime.SCOPED registrations reuse the same instance within that scope.
  • Bulk registration and cleanup. loadModules registers many modules from glob patterns, and container.dispose() runs registered disposers (such as a database pool's end() method) to release pooled resources.

How engineers can use it

Install with npm install awilix or yarn add awilix. Then create a container and register modules:

const awilix = require('awilix')
const container = awilix.createContainer({ strict: true })
container.register({
  userService: awilix.asClass(UserService).scoped(),
  connectionString: awilix.asValue(process.env.CONN_STR),
})
const userService = container.cradle.userService

For web frameworks, create a child scope in middleware via container.createScope(), register request-specific values, and resolve scoped services from the per-request scope.

Documented caveats:

  • InjectionMode.CLASSIC reads parameter names from function signatures, so it breaks when the code is minified; the README recommends PROXY (the default) in such environments.
  • loadModules relies on glob and does not work with bundlers like Webpack, Rollup, or Browserify.
  • A singleton that depends on a transient registration captures the first value permanently, so dependencies should generally not outlive what they depend on. Strict mode can throw an AwilixResolutionError at runtime when this happens.