autocontainer

0.1.3 • Public • Published

autocontainer

autocontainer is an IoC container and DI framework for TypeScript that relies on a custom transformer pass to be able to use type information at runtime.

Because of the reliance on a custom transformer, it is required that the user uses ttypescript replacement executables instead of the native TypeScript tsc/tsserver executables.

Configuration

{
  "compilerOptions": {
    "plugins": [
      { "transform": "autocontainer/dist/transformer.js" }
    ]
  }
}

Usage

Let's start with some vanilla TypeScript declarations.

import { Database } from "some-database-library";

// A perfectly normal TypeScript interface
interface UserRepository {
  getUsers(): AsyncIterable<User>;
}

// A class dependent on the interface
class UserController {
  readonly #repo: UserRepository;
  // ...
}

// An implementation of the interface using a third-party class
class DatabaseUserRepository implements UserRepository {
  readonly #database: Database;
  // ...
}

Given the above code, here's how we can use autocontainer to resolve the dependency graph.

First, we create an instance of the container:

import { Container } from "autocontainer";

const container = Container.create();

We can provide implementations for arbitrary types. Here we're providing a singleton binding, meaning the same instance will be reused anytime someone injects the type.

import { Database } from "some-database-library";
container.provide<Database>(
  () => new Database("db://connection-string"),
  { singleton: true },
);

We can make a binding from an abstract type to a concrete one, by using the bind method.

container.bind<UserRepository, DatabaseUserRepository>();

Now, we can use the make method to create an instance of UserController, which recursively makes instances of all the dependencies of that class.

const controller = container.make<UserController>();

Note how, as long as TypeScript knows the type argument provided to make, the transformer is able to generate the correct code. So, thanks to the flow analysis of the TypeScript compiler, we're sometimes able to omit the type argument. Here's an example.

async function startServer(controller: UserController) {
  // ...
}

await startServer(container.make());

Readme

Keywords

none

Package Sidebar

Install

npm i autocontainer

Weekly Downloads

1

Version

0.1.3

License

none

Unpacked Size

61.8 kB

Total Files

27

Last publish

Collaborators

  • emilniklas