This project is part of the @daisugi monorepo.
Kado is a minimal and unobtrusive inversion of control (IoC) container.
- 💡 Minimal size overhead (see details)
- ⚡️ Written in TypeScript
- 📦 Uses only trusted dependencies
- 🔨 Powerful and agnostic to your code
- 🧪 Well-tested
- 🤝 Used in production
- 🔀 Supports both ES Modules and CommonJS
Using npm:
npm install @daisugi/kado
Using pnpm:
pnpm install @daisugi/kado
import { Kado } from '@daisugi/kado';
const { container } = new Kado();
class Foo {
constructor(bar) {
this.bar = bar;
}
}
class Bar {}
container.register([
{ token: 'Foo', useClass: Foo, params: ['Bar'] },
{ token: 'Bar', useClass: Bar }
]);
const foo = await container.resolve('Foo');
- @daisugi/kado
Kado was created to address limitations found in other IoC libraries. If these requirements align with your needs, Kado may be a good fit. Otherwise, alternatives like di-ninja or tsyringe might be worth exploring.
- Allows multiple container instances without global state.
- Decouples dependency injection (DI) configuration from base code.
- Supports easy dependency decoration (useful for telemetry, debugging, etc.).
- Avoids annotation-based decorators (see style guide).
- Works with pure JavaScript (does not require TypeScript).
- Keeps the API simple yet powerful.
Registers dependencies in the container.
container.register([{ token: 'Foo' }]);
Resolves a registered dependency.
const foo = await container.resolve('Foo');
Retrieves a registered manifest item by token.
const manifestItem = container.get('Foo');
A unique identifier for registered dependencies.
Defines a class as a dependency.
container.register([
{ token: 'Foo', useClass: Foo, params: ['Bar'] },
{ token: 'Bar', useClass: Bar }
]);
Registers a constant value.
container.register([{ token: 'foo', useValue: 'text' }]);
Passes the container to a factory function.
function bar(c) {
return c.resolve('Foo');
}
container.register([
{ token: 'Foo', useClass: Foo },
{ token: 'bar', useFnByContainer: bar }
]);
Passes specified parameters to a factory function.
function bar(foo) {
return foo;
}
container.register([
{ token: 'Foo', useClass: Foo },
{ token: 'bar', useFn: bar, params: ['Foo'] }
]);
Defines the lifecycle of dependencies.
-
Singleton
(default) - Reuses the same instance. -
Transient
- Creates a new instance each time.
container.register([
{ token: 'Foo', useClass: Foo, scope: 'Transient' }
]);
Stores arbitrary metadata.
container.register([{ token: 'Foo', meta: { isFoo: true } }]);
Specifies constructor arguments.
container.register([
{ token: 'Foo', useClass: Foo, params: [{ useValue: 'text' }] }
]);
Returns a list of registered dependencies.
const manifestItems = container.list();
Helper for injecting values.
container.register([
{ token: 'Foo', useClass: Foo, params: [Kado.value('text')] }
]);
Helper for resolving arrays.
container.register([
{ token: 'bar', useValue: 'text' },
{ token: 'Foo', useClass: Foo, params: [Kado.map(['bar'])] }
]);
Similar to Kado.map
, but flattens the result.
container.register([
{ token: 'bar', useValue: ['text'] },
{ token: 'Foo', useClass: Foo, params: [Kado.flatMap(['bar'])] }
]);
Kado is fully written in TypeScript.
import {
Kado,
type KadoManifestItem,
type KadoContainer,
type KadoToken,
type KadoScope,
} from '@daisugi/kado';
const { container } = new Kado();
class Foo {}
const myContainer: KadoContainer = container;
const token: KadoToken = 'Foo';
const scope: KadoScope = Kado.scope.Transient;
const manifestItems: KadoManifestItem[] = [
{
token,
useClass: Foo,
scope,
}
];
myContainer.register(manifestItems);
const foo = await myContainer.resolve<Foo>('Foo');
Kado aims to provide a simple yet effective IoC solution with minimal overhead.
Kado (華道) is the Japanese art of flower arrangement, emphasizing form, lines, and balance—similar to how Kado structures dependencies.
Explore the @daisugi ecosystem.