UNPKG

@daisugi/kado

Version:

Kado is a minimal and unobtrusive inversion of control container.

416 lines (277 loc) β€’ 7.5 kB
# @daisugi/kado [![version](https://img.shields.io/npm/v/@daisugi/kado.svg)](https://www.npmjs.com/package/@daisugi/kado) ![npm downloads](https://img.shields.io/npm/dm/@daisugi/kado) [![bundlephobia](https://badgen.net/bundlephobia/minzip/@daisugi/kado)](https://bundlephobia.com/result?p=@daisugi/kado) This project is part of the [@daisugi](https://github.com/daisugiland/daisugi) monorepo. **Kado** is a minimal and unobtrusive inversion of control (IoC) container. --- ## 🌟 Features - πŸ’‘ Minimal size overhead ([see details](https://bundlephobia.com/result?p=@daisugi/kado)) - ⚑️ Written in TypeScript - πŸ“¦ Uses only trusted dependencies - πŸ”¨ Powerful and agnostic to your code - πŸ§ͺ Well-tested - 🀝 Used in production - πŸ”€ Supports both ES Modules and CommonJS --- ## πŸ“¦ Installation Using npm: ```sh npm install @daisugi/kado ``` Using pnpm: ```sh pnpm install @daisugi/kado ``` [:top: Back to top](#-table-of-contents) --- ## πŸš€ Usage ```js 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'); ``` [:top: Back to top](#-table-of-contents) --- ## πŸ“– Table of Contents - [@daisugi/kado](#daisugikado) - [🌟 Features](#-features) - [πŸ“¦ Installation](#-installation) - [πŸš€ Usage](#-usage) - [πŸ“– Table of Contents](#-table-of-contents) - [🎯 Motivation](#-motivation) - [βœ… Key Requirements](#-key-requirements) - [πŸ“œ API](#-api) - [`#register(manifestItems)`](#registermanifestitems) - [Example:](#example) - [`#resolve(token)`](#resolvetoken) - [Example:](#example-1) - [`#get(token)`](#gettoken) - [Example:](#example-2) - [`token`](#token) - [`useClass`](#useclass) - [Example:](#example-3) - [`useValue`](#usevalue) - [Example:](#example-4) - [`useFnByContainer`](#usefnbycontainer) - [Example:](#example-5) - [`useFn`](#usefn) - [Example:](#example-6) - [`scope`](#scope) - [Example:](#example-7) - [`meta`](#meta) - [Example:](#example-8) - [`params`](#params) - [Example:](#example-9) - [`#list()`](#list) - [Example:](#example-10) - [`Kado.value`](#kadovalue) - [Example:](#example-11) - [`Kado.map`](#kadomap) - [Example:](#example-12) - [`Kado.flatMap`](#kadoflatmap) - [Example:](#example-13) - [πŸ”· TypeScript Support](#-typescript-support) - [Example:](#example-14) - [🎯 Goal](#-goal) - [🌸 Etymology](#-etymology) - [🌍 Other Projects](#-other-projects) - [πŸ“œ License](#-license) [:top: Back to top](#-table-of-contents) --- ## 🎯 Motivation 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](https://github.com/di-ninja/di-ninja) or [tsyringe](https://github.com/microsoft/tsyringe) might be worth exploring. ### βœ… Key Requirements - 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](https://github.com/daisugiland/javascript-style-guide)). - Works with pure JavaScript (does not require TypeScript). - Keeps the API simple yet powerful. [:top: Back to top](#-table-of-contents) --- ## πŸ“œ API ### `#register(manifestItems)` Registers dependencies in the container. #### Example: ```js container.register([{ token: 'Foo' }]); ``` --- ### `#resolve(token)` Resolves a registered dependency. #### Example: ```js const foo = await container.resolve('Foo'); ``` --- ### `#get(token)` Retrieves a registered manifest item by token. #### Example: ```js const manifestItem = container.get('Foo'); ``` --- ### `token` A unique identifier for registered dependencies. --- ### `useClass` Defines a class as a dependency. #### Example: ```js container.register([ { token: 'Foo', useClass: Foo, params: ['Bar'] }, { token: 'Bar', useClass: Bar } ]); ``` --- ### `useValue` Registers a constant value. #### Example: ```js container.register([{ token: 'foo', useValue: 'text' }]); ``` --- ### `useFnByContainer` Passes the container to a factory function. #### Example: ```js function bar(c) { return c.resolve('Foo'); } container.register([ { token: 'Foo', useClass: Foo }, { token: 'bar', useFnByContainer: bar } ]); ``` --- ### `useFn` Passes specified parameters to a factory function. #### Example: ```js function bar(foo) { return foo; } container.register([ { token: 'Foo', useClass: Foo }, { token: 'bar', useFn: bar, params: ['Foo'] } ]); ``` --- ### `scope` Defines the lifecycle of dependencies. - **`Singleton`** (default) - Reuses the same instance. - **`Transient`** - Creates a new instance each time. #### Example: ```js container.register([ { token: 'Foo', useClass: Foo, scope: 'Transient' } ]); ``` --- ### `meta` Stores arbitrary metadata. #### Example: ```js container.register([{ token: 'Foo', meta: { isFoo: true } }]); ``` --- ### `params` Specifies constructor arguments. #### Example: ```js container.register([ { token: 'Foo', useClass: Foo, params: [{ useValue: 'text' }] } ]); ``` --- ### `#list()` Returns a list of registered dependencies. #### Example: ```js const manifestItems = container.list(); ``` --- ### `Kado.value` Helper for injecting values. #### Example: ```js container.register([ { token: 'Foo', useClass: Foo, params: [Kado.value('text')] } ]); ``` --- ### `Kado.map` Helper for resolving arrays. #### Example: ```js container.register([ { token: 'bar', useValue: 'text' }, { token: 'Foo', useClass: Foo, params: [Kado.map(['bar'])] } ]); ``` --- ### `Kado.flatMap` Similar to `Kado.map`, but flattens the result. #### Example: ```js container.register([ { token: 'bar', useValue: ['text'] }, { token: 'Foo', useClass: Foo, params: [Kado.flatMap(['bar'])] } ]); ``` [:top: Back to top](#-table-of-contents) --- ## πŸ”· TypeScript Support Kado is fully written in TypeScript. #### Example: ```ts 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'); ``` [:top: Back to top](#-table-of-contents) --- ## 🎯 Goal Kado aims to provide a simple yet effective IoC solution with minimal overhead. [:top: Back to top](#-table-of-contents) --- ## 🌸 Etymology *Kado* (華道) is the Japanese art of flower arrangement, emphasizing form, lines, and balanceβ€”similar to how Kado structures dependencies. [:top: Back to top](#-table-of-contents) --- ## 🌍 Other Projects Explore the [@daisugi](../../README.md) ecosystem. [:top: Back to top](#-table-of-contents) --- ## πŸ“œ License [MIT](../../LICENSE) [:top: Back to top](#-table-of-contents)