katagami 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/docs/README.de.md +19 -0
- package/docs/README.es.md +19 -0
- package/docs/README.fr.md +19 -0
- package/docs/README.ja.md +39 -0
- package/docs/README.ko.md +19 -0
- package/docs/README.zh-CN.md +19 -0
- package/docs/README.zh-TW.md +19 -0
- package/docs/choosing-di.md +134 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,64 @@ No service interface or explicit generic argument is needed here. Literal string
|
|
|
37
37
|
unique symbols and class tokens can all be used. See [type guarantees](./docs/type-safety.md)
|
|
38
38
|
for the difference between accumulated registrations and a predeclared type map.
|
|
39
39
|
|
|
40
|
+
## Why Katagami
|
|
41
|
+
|
|
42
|
+
Katagami combines **registration-derived types, compile-time scope restrictions and zero runtime
|
|
43
|
+
dependencies** in an ordinary TypeScript factory API.
|
|
44
|
+
|
|
45
|
+
- **Types grow with your registrations.** Literal keys and unique symbols carry their inferred
|
|
46
|
+
service types into subsequent factories; required tokens outside that set are compile-time errors.
|
|
47
|
+
- **Request state stays explicit.** Singleton and transient factories cannot resolve scoped tokens
|
|
48
|
+
through their supplied typed resolver. You can find this mistake before starting the application.
|
|
49
|
+
- **No decorator setup.** No `experimentalDecorators`, `emitDecoratorMetadata` or Reflect polyfill
|
|
50
|
+
is needed for DI. Constructors and factories stay ordinary TypeScript.
|
|
51
|
+
- **Import the capabilities you use.** Core DI, `katagami/disposable` and `katagami/lazy` are separate
|
|
52
|
+
entry points. ESM exports and `sideEffects: false` support tree shaking; optional cleanup integrates
|
|
53
|
+
with `await using` and the host's disposal symbols.
|
|
54
|
+
|
|
55
|
+
These checks assume narrow tokens and preserved registration types; see the
|
|
56
|
+
[class-token, mutation and predeclared-map boundaries](./docs/type-safety.md).
|
|
57
|
+
|
|
58
|
+
### Library comparison
|
|
59
|
+
|
|
60
|
+
Reviewed **2026-09-11**, against the npm `latest` versions below and official documentation.
|
|
61
|
+
The tables describe the built-in APIs; add-ons and application-specific wrappers can change the
|
|
62
|
+
trade-offs. [Version sources and detailed comparison notes](./docs/choosing-di.md#comparison-sources)
|
|
63
|
+
explain the distinctions.
|
|
64
|
+
|
|
65
|
+
| Library / reviewed version | Dependency typing and missing registrations | Scoped-dependency handling | DI setup |
|
|
66
|
+
| --- | --- | --- | --- |
|
|
67
|
+
| **Katagami 3.0.2** | **Accumulated literal/unique-symbol tokens; missing required tokens rejected** | **Scoped tokens excluded from singleton/transient factory resolvers** | **No decorators or metadata; zero runtime dependencies** |
|
|
68
|
+
| [InversifyJS 8.2.3](https://inversify.io/docs/fundamentals/binding/) | Typed identifiers and bindings; binding existence checked at runtime | Declared binding scopes; not a scope-filtered resolver type | Metadata-based class injection; explicit value/factory bindings also available |
|
|
69
|
+
| [tsyringe 4.10.0](https://github.com/microsoft/tsyringe#readme) | Class/generic resolution types; registrations checked at runtime | Runtime lifetime settings; factory receives the container | Decorators and a Reflect metadata polyfill for class injection |
|
|
70
|
+
| [TypeDI 0.10.0](https://github.com/typestack/typedi/tree/v0.10.0) | Class and `Token<T>` types; registrations checked at runtime | Shared/transient services and named containers | Decorators and `reflect-metadata` in the TypeScript setup |
|
|
71
|
+
| [Awilix 13.0.5](https://github.com/jeffijoe/awilix#readme) | Registration-derived cradle types; broad `resolve` overload still accepts unknown names | `strict: true` checks lifetime leaks at runtime | No decorators or metadata |
|
|
72
|
+
| [NestJS 12.0.1](https://docs.nestjs.com/fundamentals/custom-providers) | Typed providers; module/provider graph resolved at runtime | Request scope propagates to dependent providers | Framework modules and metadata-based class injection |
|
|
73
|
+
| [Effect 3.22.2](https://effect.website/docs/v3/requirements-management/layers) | Service requirements tracked in `Effect` / `Layer` types | Typed `Scope` requirements and resource finalizers; a different lifetime model | No decorators or metadata; Effect's service/layer model |
|
|
74
|
+
| [typed-inject 5.0.0](https://github.com/nicojs/typed-inject#readme) | Accumulated string tokens and checked `inject` tuples | Singleton/transient providers and child injectors; no separate scoped lifetime | No decorators or metadata; zero runtime dependencies |
|
|
75
|
+
|
|
76
|
+
Awilix's inferred `cradle` and typed-inject's registration types are real compile-time features.
|
|
77
|
+
Katagami's distinction is the combination of accumulated registration checks with **scope-filtered
|
|
78
|
+
factory resolvers**, using direct `r.resolve(token)` calls. Effect also checks unsatisfied service
|
|
79
|
+
requirements, within its broader effect and resource model.
|
|
80
|
+
|
|
81
|
+
| Library | Lifetimes / scope model | Asynchronous services | Resource cleanup |
|
|
82
|
+
| --- | --- | --- | --- |
|
|
83
|
+
| **Katagami** | **Singleton, transient, scoped; nested scopes** | **Inferred `Promise<T>`; explicitly await dependencies** | **`Symbol.dispose` / `Symbol.asyncDispose` via `disposable()`; `await using`** |
|
|
84
|
+
| InversifyJS | Singleton, transient, request (one resolution graph); container hierarchy | Async bindings via `getAsync` / `getAllAsync`; awaits dependencies | Singleton deactivation handlers |
|
|
85
|
+
| tsyringe | Singleton, transient, resolution-scoped, container-scoped | Factories can return Promise-valued services; consumer handles the Promise | `container.dispose()` for constructed disposable instances |
|
|
86
|
+
| TypeDI | Shared or transient services; named containers | Promise-valued services; consumer handles the Promise | `reset()` / removal can call `destroy()`; returned Promise is not awaited |
|
|
87
|
+
| Awilix | Singleton, transient, scoped | Promise-valued factories; consumer handles the Promise | Registered disposers for cached singleton/scoped values |
|
|
88
|
+
| NestJS | Singleton, transient, HTTP request; scope propagation | Async providers are awaited before dependent construction | Application lifecycle hooks; not called for request-scoped classes |
|
|
89
|
+
| Effect | Memoized layers and explicit resource scopes | Effectful acquisition, including async effects | Scope finalizers and `acquireRelease` |
|
|
90
|
+
| typed-inject | Singleton, transient; disposable child injectors | Promise-valued factories with inferred return types | `injector.dispose()` awaits owned instances' `dispose()` |
|
|
91
|
+
|
|
92
|
+
“Request” is not identical across libraries: InversifyJS uses a resolution graph, while NestJS can
|
|
93
|
+
use an HTTP request. Katagami and Awilix let you create an explicit scope per request.
|
|
94
|
+
Returning a Promise and automatically awaiting dependencies are also different capabilities.
|
|
95
|
+
See [composition, optional/multiple resolution and tooling](./docs/choosing-di.md#composition-and-tooling)
|
|
96
|
+
for the rest of the feature comparison.
|
|
97
|
+
|
|
40
98
|
## Why Katagami for AI-assisted development?
|
|
41
99
|
|
|
42
100
|
Give coding agents a concrete feedback loop: edit dependency wiring, run the TypeScript checker,
|
package/docs/README.de.md
CHANGED
|
@@ -25,6 +25,25 @@ const greeting: string = createScope(container).resolve('greeting');
|
|
|
25
25
|
console.log(greeting);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## Warum Katagami? Bibliotheksvergleich
|
|
29
|
+
|
|
30
|
+
Katagami verbindet **aus Registrierungen abgeleitete Typen, Scope-Prüfungen zur Compile-Zeit und keine Laufzeitabhängigkeiten** mit gewöhnlichen TypeScript-Factories. Decorators und Metadaten sind nicht nötig. Ressourcenfreigabe und Lazy Resolution haben eigene Einstiegspunkte.
|
|
31
|
+
|
|
32
|
+
**Geprüft am 2026-09-11**, anhand stabiler npm-Versionen und offizieller Quellen. Siehe [Versionen und Quellen](./choosing-di.md#comparison-sources) sowie den [vollständigen Vergleich mit Async-Verhalten und Ressourcenfreigabe](../README.md#library-comparison).
|
|
33
|
+
|
|
34
|
+
| Bibliothek / Version | Abhängigkeitstypen und Registrierungsprüfung | Scope-Verhalten |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| **Katagami 3.0.2** | **Sammelt Literal-/unique-symbol-Tokens; fehlende erforderliche Tokens sind Typfehler** | **Scoped-Tokens im Resolver von Singleton-/Transient-Factories ausgeschlossen** |
|
|
37
|
+
| InversifyJS 8.2.3 | Typisierte Bindings; Existenzprüfung zur Laufzeit | Konfigurierte Binding-Lebensdauer |
|
|
38
|
+
| tsyringe 4.10.0 | Klassen-/generische Typen; Registrierungsprüfung zur Laufzeit | Lebensdauer und Kindcontainer |
|
|
39
|
+
| TypeDI 0.10.0 | Klassen und `Token<T>`; Registrierungsprüfung zur Laufzeit | Geteilte/Transient-Services, benannte Container |
|
|
40
|
+
| Awilix 13.0.5 | Abgeleitete Cradle-Typen; breites `resolve` akzeptiert unbekannte Namen | Laufzeitprüfung von Lebensdauern mit `strict: true` |
|
|
41
|
+
| NestJS 12.0.1 | Typisierte Provider; Abhängigkeitsgraph zur Laufzeit | Request-Scope überträgt sich auf abhängige Provider |
|
|
42
|
+
| Effect 3.22.2 | Service-Anforderungen in `Effect`-/`Layer`-Typen | Typisierter `Scope` und Finalizer |
|
|
43
|
+
| typed-inject 5.0.0 | Gesammelte String-Tokens, geprüfte `inject`-Tupel | Singleton, Transient, Kindinjectoren |
|
|
44
|
+
|
|
45
|
+
Auch Awilix, Effect und typed-inject bieten Typprüfungen. Katagami kombiniert Registrierungs- und Scope-Prüfungen mit direkten `r.resolve(token)`-Aufrufen. Die [Grenzen für Tokentypen, Klassen und veränderliche Referenzen](./type-safety.md) gelten weiterhin.
|
|
46
|
+
|
|
28
47
|
## Mit KI-Coding-Agenten arbeiten
|
|
29
48
|
|
|
30
49
|
Der Agent ändert die Abhängigkeiten, führt den TypeScript-Checker aus und korrigiert den Code anhand der Diagnosen. Explizite Factories zeigen Abhängigkeiten als gewöhnlichen TypeScript-Code.
|
package/docs/README.es.md
CHANGED
|
@@ -25,6 +25,25 @@ const greeting: string = createScope(container).resolve('greeting');
|
|
|
25
25
|
console.log(greeting);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## Por qué elegir Katagami: comparación
|
|
29
|
+
|
|
30
|
+
Katagami combina **tipos derivados del registro, restricciones de ámbito en compilación y cero dependencias de ejecución** en factorías de TypeScript normales. No requiere decoradores ni metadatos. La liberación de recursos y la resolución diferida tienen puntos de entrada separados.
|
|
31
|
+
|
|
32
|
+
**Revisado el 2026-09-11**, con versiones estables de npm y fuentes oficiales. Consulta las [versiones y fuentes](./choosing-di.md#comparison-sources) y la [comparación completa de asincronía y liberación de recursos](../README.md#library-comparison).
|
|
33
|
+
|
|
34
|
+
| Biblioteca / versión | Tipos y comprobación de registros | Política de ámbitos |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| **Katagami 3.0.2** | **Acumula tokens literales/unique symbol; rechaza tokens requeridos sin registrar** | **Excluye tokens Scoped del resolver de factorías Singleton/Transient** |
|
|
37
|
+
| InversifyJS 8.2.3 | Bindings tipados; existencia comprobada en ejecución | Ciclo de vida configurado por binding |
|
|
38
|
+
| tsyringe 4.10.0 | Tipos de clase/genéricos; registros comprobados en ejecución | Ciclos de vida y contenedores hijos |
|
|
39
|
+
| TypeDI 0.10.0 | Clases y `Token<T>`; registros comprobados en ejecución | Servicios compartidos/Transient y contenedores con nombre |
|
|
40
|
+
| Awilix 13.0.5 | Infiere el cradle del registro; el `resolve` amplio acepta nombres desconocidos | `strict: true` comprueba fugas de ciclo de vida en ejecución |
|
|
41
|
+
| NestJS 12.0.1 | Providers tipados; grafo resuelto en ejecución | Request se propaga a los providers dependientes |
|
|
42
|
+
| Effect 3.22.2 | Requisitos de servicios en los tipos `Effect`/`Layer` | `Scope` tipado y finalizadores |
|
|
43
|
+
| typed-inject 5.0.0 | Acumula tokens de cadena y comprueba tuplas `inject` | Singleton, Transient e injectores hijos |
|
|
44
|
+
|
|
45
|
+
Awilix, Effect y typed-inject también ofrecen comprobaciones de tipos. Katagami combina las de registro y ámbito con llamadas directas a `r.resolve(token)`. Se aplican los [límites de tokens, clases y referencias mutables](./type-safety.md).
|
|
46
|
+
|
|
28
47
|
## Uso con agentes de programación de IA
|
|
29
48
|
|
|
30
49
|
El agente modifica las dependencias, ejecuta el comprobador de TypeScript y corrige el código a partir de los diagnósticos. Las fábricas explícitas muestran las dependencias en código TypeScript normal.
|
package/docs/README.fr.md
CHANGED
|
@@ -25,6 +25,25 @@ const greeting: string = createScope(container).resolve('greeting');
|
|
|
25
25
|
console.log(greeting);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## Pourquoi choisir Katagami ? Comparaison
|
|
29
|
+
|
|
30
|
+
Katagami associe **types déduits des enregistrements, restrictions de portée à la compilation et aucune dépendance d'exécution** dans des fabriques TypeScript ordinaires. Aucun décorateur ni métadonnée n'est nécessaire. La libération des ressources et la résolution différée ont des points d'entrée distincts.
|
|
31
|
+
|
|
32
|
+
**Vérifié le 2026-09-11**, à partir des versions stables npm et des sources officielles. Consultez les [versions et sources](./choosing-di.md#comparison-sources) et le [comparatif complet sur l'asynchronisme et la libération des ressources](../README.md#library-comparison).
|
|
33
|
+
|
|
34
|
+
| Bibliothèque / version | Types et vérification des enregistrements | Politique de portée |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| **Katagami 3.0.2** | **Accumule les tokens littéraux/unique symbol ; rejette les tokens requis non enregistrés** | **Exclut les tokens Scoped du résolveur des fabriques Singleton/Transient** |
|
|
37
|
+
| InversifyJS 8.2.3 | Bindings typés ; existence vérifiée à l'exécution | Durée de vie configurée par binding |
|
|
38
|
+
| tsyringe 4.10.0 | Types de classe/génériques ; enregistrements vérifiés à l'exécution | Durées de vie et conteneurs enfants |
|
|
39
|
+
| TypeDI 0.10.0 | Classes et `Token<T>` ; enregistrements vérifiés à l'exécution | Services partagés/Transient, conteneurs nommés |
|
|
40
|
+
| Awilix 13.0.5 | Cradle déduit des enregistrements ; `resolve` accepte aussi des noms inconnus | `strict: true` vérifie les fuites de durée de vie à l'exécution |
|
|
41
|
+
| NestJS 12.0.1 | Providers typés ; graphe résolu à l'exécution | La portée Request se propage aux providers dépendants |
|
|
42
|
+
| Effect 3.22.2 | Services requis suivis dans les types `Effect`/`Layer` | `Scope` typé et finaliseurs |
|
|
43
|
+
| typed-inject 5.0.0 | Tokens chaînes accumulés et tuples `inject` vérifiés | Singleton, Transient, injecteurs enfants |
|
|
44
|
+
|
|
45
|
+
Awilix, Effect et typed-inject proposent aussi des vérifications de types. Katagami associe celles des enregistrements et des portées avec des appels directs à `r.resolve(token)`. Les [limites des tokens, classes et références mutables](./type-safety.md) s'appliquent.
|
|
46
|
+
|
|
28
47
|
## Travailler avec des agents de programmation IA
|
|
29
48
|
|
|
30
49
|
L’agent modifie les dépendances, exécute le vérificateur TypeScript, puis corrige le code à partir des diagnostics. Les fabriques explicites rendent les dépendances visibles dans du code TypeScript ordinaire.
|
package/docs/README.ja.md
CHANGED
|
@@ -25,6 +25,45 @@ const greeting: string = createScope(container).resolve('greeting');
|
|
|
25
25
|
console.log(greeting);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## Katagamiを選ぶ理由
|
|
29
|
+
|
|
30
|
+
Katagamiの強みは、**登録からの型推論・コンパイル時のスコープ制約・ランタイム依存ゼロ**を、通常のTypeScriptファクトリで組み合わせられることです。
|
|
31
|
+
|
|
32
|
+
- **登録した型がそのまま使える。** リテラルキーやunique symbolの型を保てば、登録集合にない必須トークンは型エラーになります。
|
|
33
|
+
- **リクエストの状態を型で分離できる。** Singleton・Transientのファクトリに渡されるresolverからは、Scopedのトークンを解決できません。
|
|
34
|
+
- **デコレータ設定が不要。** DIのための`experimentalDecorators`・`emitDecoratorMetadata`・Reflectポリフィルを追加する必要がありません。
|
|
35
|
+
- **必要な機能だけ取り込める。** コア・`katagami/disposable`・`katagami/lazy`を別々にインポートできます。ESMと`sideEffects: false`でツリーシェイキングに対応し、破棄はホストのdisposalシンボルと`await using`に連携します。
|
|
36
|
+
|
|
37
|
+
### 他ライブラリとの比較
|
|
38
|
+
|
|
39
|
+
**2026-09-11確認。** npmの`latest`安定版と公式資料をもとに、標準APIの動作を比較しています。[対象バージョン・出典・詳細な注記](./choosing-di.md#comparison-sources)も参照してください。
|
|
40
|
+
|
|
41
|
+
| ライブラリ/確認した版 | 依存の型付けと登録漏れ | スコープの扱い | DIの導入設定 |
|
|
42
|
+
| --- | --- | --- | --- |
|
|
43
|
+
| **Katagami 3.0.2** | **リテラル・unique symbolの登録型を蓄積し、未登録の必須トークンを拒否** | **Singleton・TransientのresolverからScopedを型で除外** | **デコレータ・メタデータ不要、ランタイム依存ゼロ** |
|
|
44
|
+
| InversifyJS 8.2.3 | 型付きの識別子・binding。登録の有無は実行時に確認 | bindingのスコープ指定。resolverの型では分離しない | クラス注入はメタデータ方式。明示的な値・ファクトリbindingも可能 |
|
|
45
|
+
| tsyringe 4.10.0 | クラス・ジェネリックの型を利用。登録の有無は実行時に確認 | 実行時のライフタイム設定。ファクトリにはコンテナを渡す | クラス注入にデコレータとReflectメタデータのポリフィル |
|
|
46
|
+
| TypeDI 0.10.0 | クラス・`Token<T>`の型を利用。登録の有無は実行時に確認 | 共有・Transientと名前付きコンテナ | TypeScriptの導入手順はデコレータと`reflect-metadata`を使用 |
|
|
47
|
+
| Awilix 13.0.5 | 登録からcradleの型を推論。`resolve`の広いオーバーロードは未登録名も許可 | `strict: true`でライフタイム漏れを実行時に検出 | デコレータ・メタデータ不要 |
|
|
48
|
+
| NestJS 12.0.1 | 型付きprovider。モジュールとproviderの依存グラフは実行時に解決 | Requestスコープが依存元へ伝播 | フレームワークのモジュールとメタデータ方式のクラス注入 |
|
|
49
|
+
| Effect 3.22.2 | `Effect`・`Layer`の型で必要なサービスを追跡 | 型付き`Scope`とfinalizer。DIコンテナとは異なるライフタイムモデル | デコレータ・メタデータ不要。Effectのサービス・Layerを使用 |
|
|
50
|
+
| typed-inject 5.0.0 | 文字列トークンを蓄積し、`inject`タプルも検査 | Singleton・Transientと子injector。独立したScoped登録はない | デコレータ・メタデータ不要、ランタイム依存ゼロ |
|
|
51
|
+
|
|
52
|
+
Awilixのcradle推論、typed-injectの登録検査、Effectのサービス要求の型検査も、それぞれコンパイル時の機能です。Katagamiは、**登録集合とスコープ制約を、直接`r.resolve(token)`を呼べるファクトリAPIで組み合わせられる**点を重視しています。[型の保証範囲](./type-safety.md)にあるクラストークン・事前宣言・変更可能な参照の条件も適用されます。
|
|
53
|
+
|
|
54
|
+
| ライブラリ | ライフタイム/スコープ | 非同期サービス | リソース破棄 |
|
|
55
|
+
| --- | --- | --- | --- |
|
|
56
|
+
| **Katagami** | **Singleton・Transient・Scoped、ネストしたスコープ** | **`Promise<T>`を推論。依存は明示的にawait** | **`disposable()`でdisposalシンボルと`await using`に連携** |
|
|
57
|
+
| InversifyJS | Singleton・Transient・Request(1回の解決グラフ)、コンテナ階層 | `getAsync`・`getAllAsync`が依存の完了を待機 | Singletonのdeactivation handler |
|
|
58
|
+
| tsyringe | Singleton・Transient・ResolutionScoped・ContainerScoped | Promiseを返すファクトリを登録可能。利用側で処理 | 構築したDisposableを`container.dispose()`で破棄 |
|
|
59
|
+
| TypeDI | 共有・Transient、名前付きコンテナ | Promiseをサービス値として扱い、利用側で処理 | reset・削除時に`destroy()`を呼べるが、戻り値のPromiseは待機しない |
|
|
60
|
+
| Awilix | Singleton・Transient・Scoped | Promiseを返すファクトリを登録可能。利用側で処理 | キャッシュしたSingleton・Scopedに登録済みdisposerを適用 |
|
|
61
|
+
| NestJS | Singleton・Transient・HTTPリクエスト、スコープ伝播 | 依存providerの非同期初期化を待ってから構築 | アプリのライフサイクルフック。Requestスコープのクラスは対象外 |
|
|
62
|
+
| Effect | メモ化されたLayerと明示的なリソーススコープ | 非同期処理を含むEffectによる取得 | Scopeのfinalizerと`acquireRelease` |
|
|
63
|
+
| typed-inject | Singleton・Transient、破棄可能な子injector | ファクトリが返すPromiseの型も推論 | 所有するインスタンスの`dispose()`をawait |
|
|
64
|
+
|
|
65
|
+
InversifyJSのRequestは1回の解決グラフであり、HTTPリクエストとは異なります。また、Promiseを値として返せることと、依存のPromiseを自動的に待って注入することは別の機能です。[モジュール合成・複数解決・拡張機能の比較](./choosing-di.md#composition-and-tooling)も掲載しています。
|
|
66
|
+
|
|
28
67
|
## AIエージェントによるコーディングで役立つ理由
|
|
29
68
|
|
|
30
69
|
エージェントが依存関係を変更し、TypeScriptの型チェックを実行し、診断をもとに修正する。この手順に、登録漏れやライフタイムの誤用を検出する具体的なチェックを組み込めます。依存関係は通常のTypeScriptのファクトリとして記述します。
|
package/docs/README.ko.md
CHANGED
|
@@ -25,6 +25,25 @@ const greeting: string = createScope(container).resolve('greeting');
|
|
|
25
25
|
console.log(greeting);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## Katagami를 선택하는 이유와 라이브러리 비교
|
|
29
|
+
|
|
30
|
+
**등록에서 추론한 타입, 컴파일 시점의 스코프 제한, 런타임 의존성 없음**을 일반 TypeScript 팩터리에서 함께 사용할 수 있습니다. 데코레이터나 메타데이터 설정이 필요 없으며, 리소스 정리와 지연 해석은 별도 진입점으로 가져옵니다.
|
|
31
|
+
|
|
32
|
+
**2026-09-11 확인.** npm의 안정 버전과 공식 자료를 비교했습니다. [버전과 출처](./choosing-di.md#comparison-sources), [비동기·정리 기능까지 포함한 전체 비교](../README.md#library-comparison)를 참고하세요.
|
|
33
|
+
|
|
34
|
+
| 라이브러리 / 버전 | 의존성 타입과 등록 확인 | 스코프 정책 |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| **Katagami 3.0.2** | **리터럴·unique symbol 등록을 누적하고 미등록 필수 토큰 거부** | **Singleton·Transient 팩터리에서 Scoped 토큰을 타입으로 제외** |
|
|
37
|
+
| InversifyJS 8.2.3 | 타입이 있는 binding, 등록 여부는 런타임 확인 | binding의 라이프타임 설정 |
|
|
38
|
+
| tsyringe 4.10.0 | 클래스·제네릭 타입, 등록 여부는 런타임 확인 | 라이프타임 설정과 자식 컨테이너 |
|
|
39
|
+
| TypeDI 0.10.0 | 클래스·`Token<T>`, 등록 여부는 런타임 확인 | 공유·Transient 서비스와 이름 있는 컨테이너 |
|
|
40
|
+
| Awilix 13.0.5 | 등록에서 cradle 추론. 넓은 `resolve`는 미등록 이름도 허용 | `strict: true`로 런타임 라이프타임 검사 |
|
|
41
|
+
| NestJS 12.0.1 | 타입이 있는 provider, 런타임 의존성 그래프 | Request 스코프가 의존하는 쪽으로 전파 |
|
|
42
|
+
| Effect 3.22.2 | `Effect`·`Layer` 타입으로 필요한 서비스 추적 | 타입이 있는 `Scope`와 finalizer |
|
|
43
|
+
| typed-inject 5.0.0 | 문자열 토큰 누적과 `inject` 튜플 검사 | Singleton·Transient, 자식 injector |
|
|
44
|
+
|
|
45
|
+
Awilix, Effect, typed-inject에도 컴파일 시점 기능이 있습니다. Katagami는 등록 확인과 스코프 제한을 직접 `r.resolve(token)`을 호출하는 API로 결합합니다. [토큰 타입·클래스·변경 가능한 참조의 조건](./type-safety.md)이 적용됩니다.
|
|
46
|
+
|
|
28
47
|
## AI 코딩 에이전트와 함께 사용하기
|
|
29
48
|
|
|
30
49
|
에이전트가 의존 관계를 수정하고 TypeScript 검사기를 실행한 뒤 진단에 따라 수정하는 흐름을 만듭니다. 팩터리에 의존 관계가 일반 TypeScript 코드로 드러납니다.
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -25,6 +25,25 @@ const greeting: string = createScope(container).resolve('greeting');
|
|
|
25
25
|
console.log(greeting);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## 为什么选择 Katagami:库对比
|
|
29
|
+
|
|
30
|
+
Katagami 在普通 TypeScript 工厂中结合了**从注册推导类型、编译时作用域限制、零运行时依赖**。无需装饰器或元数据配置,资源清理和延迟解析可通过独立入口按需导入。
|
|
31
|
+
|
|
32
|
+
**核查日期:2026-09-11。** 对照 npm 稳定版和官方资料;参见[版本与来源](./choosing-di.md#comparison-sources)及[包含异步和清理功能的完整对比](../README.md#library-comparison)。
|
|
33
|
+
|
|
34
|
+
| 库/版本 | 依赖类型与注册检查 | 作用域策略 |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| **Katagami 3.0.2** | **累积字面量、unique symbol 的注册类型,拒绝未注册的必需 token** | **从 Singleton、Transient 工厂的 resolver 类型中排除 Scoped token** |
|
|
37
|
+
| InversifyJS 8.2.3 | 有类型的 binding;运行时检查是否已绑定 | binding 的生命周期设置 |
|
|
38
|
+
| tsyringe 4.10.0 | 类与泛型类型;运行时检查注册 | 生命周期设置与子容器 |
|
|
39
|
+
| TypeDI 0.10.0 | 类与 `Token<T>`;运行时检查注册 | 共享、Transient 服务与命名容器 |
|
|
40
|
+
| Awilix 13.0.5 | 从注册推导 cradle;宽泛的 `resolve` 仍接受未知名称 | `strict: true` 在运行时检查生命周期泄漏 |
|
|
41
|
+
| NestJS 12.0.1 | 有类型的 provider;运行时解析依赖图 | Request 作用域向依赖方传播 |
|
|
42
|
+
| Effect 3.22.2 | 通过 `Effect`、`Layer` 类型追踪所需服务 | 有类型的 `Scope` 与 finalizer |
|
|
43
|
+
| typed-inject 5.0.0 | 累积字符串 token,检查 `inject` 元组 | Singleton、Transient 与子 injector |
|
|
44
|
+
|
|
45
|
+
Awilix、Effect、typed-inject 也有编译时检查能力。Katagami 的特点是通过直接调用 `r.resolve(token)` 的 API 结合注册检查与作用域限制。[窄 token 类型、类和可变引用的边界](./type-safety.md)仍然适用。
|
|
46
|
+
|
|
28
47
|
## 配合 AI 编程智能体使用
|
|
29
48
|
|
|
30
49
|
让智能体修改依赖关系,运行 TypeScript 检查,再根据诊断修复。显式工厂让依赖关系直接体现在普通 TypeScript 代码中。
|
package/docs/README.zh-TW.md
CHANGED
|
@@ -25,6 +25,25 @@ const greeting: string = createScope(container).resolve('greeting');
|
|
|
25
25
|
console.log(greeting);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
## 為什麼選擇 Katagami:函式庫比較
|
|
29
|
+
|
|
30
|
+
Katagami 在一般 TypeScript 工廠中結合了**從註冊推導型別、編譯時作用域限制、零執行期依賴**。不需要裝飾器或中繼資料設定,資源清理與延遲解析可透過獨立入口按需匯入。
|
|
31
|
+
|
|
32
|
+
**查核日期:2026-09-11。** 對照 npm 穩定版與官方資料;請參閱[版本與來源](./choosing-di.md#comparison-sources)及[包含非同步與清理功能的完整比較](../README.md#library-comparison)。
|
|
33
|
+
|
|
34
|
+
| 函式庫/版本 | 依賴型別與註冊檢查 | 作用域策略 |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| **Katagami 3.0.2** | **累積字面值、unique symbol 的註冊型別,拒絕未註冊的必要 token** | **從 Singleton、Transient 工廠的 resolver 型別中排除 Scoped token** |
|
|
37
|
+
| InversifyJS 8.2.3 | 具型別的 binding;執行時檢查是否已綁定 | binding 的生命週期設定 |
|
|
38
|
+
| tsyringe 4.10.0 | 類別與泛型型別;執行時檢查註冊 | 生命週期設定與子容器 |
|
|
39
|
+
| TypeDI 0.10.0 | 類別與 `Token<T>`;執行時檢查註冊 | 共用、Transient 服務與具名容器 |
|
|
40
|
+
| Awilix 13.0.5 | 從註冊推導 cradle;寬泛的 `resolve` 仍接受未知名稱 | `strict: true` 在執行時檢查生命週期洩漏 |
|
|
41
|
+
| NestJS 12.0.1 | 具型別的 provider;執行時解析依賴圖 | Request 作用域向依賴方傳播 |
|
|
42
|
+
| Effect 3.22.2 | 透過 `Effect`、`Layer` 型別追蹤所需服務 | 具型別的 `Scope` 與 finalizer |
|
|
43
|
+
| typed-inject 5.0.0 | 累積字串 token,檢查 `inject` 元組 | Singleton、Transient 與子 injector |
|
|
44
|
+
|
|
45
|
+
Awilix、Effect、typed-inject 也有編譯時檢查能力。Katagami 的特色是透過直接呼叫 `r.resolve(token)` 的 API 結合註冊檢查與作用域限制。[窄 token 型別、類別與可變參照的邊界](./type-safety.md)仍然適用。
|
|
46
|
+
|
|
28
47
|
## 與 AI 程式設計代理搭配使用
|
|
29
48
|
|
|
30
49
|
讓代理修改依賴關係,執行 TypeScript 檢查,再根據診斷修正。明確的工廠讓依賴關係直接呈現在一般 TypeScript 程式碼中。
|
package/docs/choosing-di.md
CHANGED
|
@@ -1,30 +1,143 @@
|
|
|
1
1
|
# Choosing a TypeScript dependency injection approach
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Katagami is a strong fit when you want **registration-derived types, explicit request scopes and
|
|
4
|
+
ordinary TypeScript factories without decorators or runtime dependencies**. The
|
|
5
|
+
[README comparison](../README.md#library-comparison) covers all eight libraries, including their
|
|
6
|
+
typing, setup, lifetimes, asynchronous behavior and cleanup. This guide records the evidence and
|
|
7
|
+
the features that need more explanation than a table cell.
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
## What distinguishes Katagami
|
|
10
|
+
|
|
11
|
+
The default registration chain accumulates the tokens visible to each factory. With literal keys
|
|
12
|
+
or unique symbols preserved, a missing required token is rejected before execution. Singleton and
|
|
13
|
+
transient factories receive a resolver that excludes scoped tokens. Async results stay visible as
|
|
14
|
+
Promises. This combination gives a coding agent actionable TypeScript errors while keeping the
|
|
15
|
+
wiring in ordinary factory functions.
|
|
16
|
+
|
|
17
|
+
Accumulation alone is not unique to Katagami: typed-inject checks accumulated tokens and injection
|
|
18
|
+
tuples, and Awilix 13 infers cradle types from registrations. Effect tracks required services in its
|
|
19
|
+
effect and layer types. Katagami adds a specific scope restriction to its factory resolver API.
|
|
20
|
+
See [the guarantee examples](./type-safety.md) for narrow-token requirements, structural class
|
|
21
|
+
typing, mutable aliases and predeclared-map boundaries.
|
|
22
|
+
|
|
23
|
+
| Approach | A reason to choose it |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| Ordinary constructor/function parameters | Few dependencies; direct wiring remains easy to maintain |
|
|
26
|
+
| Katagami | Registration checks and explicit scoped DI in standard TypeScript factories |
|
|
27
|
+
| InversifyJS | Class-oriented binding, contextual constraints, container modules and snapshots |
|
|
28
|
+
| tsyringe | Constructor injection with decorators, child containers and resolution interceptors |
|
|
29
|
+
| TypeDI | An existing application built around its decorators, typed tokens and named containers |
|
|
30
|
+
| Awilix | Proxy/classic injection, inferred cradles, module loading and runtime lifetime checks |
|
|
31
|
+
| NestJS | The app already benefits from Nest modules, request handling and framework integrations |
|
|
32
|
+
| Effect | Service composition belongs with typed errors, effectful execution and scoped resources |
|
|
33
|
+
| typed-inject | Accumulated string-token checks with explicit injection tuples and child injectors |
|
|
34
|
+
|
|
35
|
+
## Comparison sources
|
|
36
|
+
|
|
37
|
+
Reviewed **2026-09-11**. Competitor versions are the npm `latest` dist-tag versions observed on that date,
|
|
38
|
+
not prerelease versions or unreleased features from repository default branches. TypeDI refers to
|
|
39
|
+
the `typedi` package maintained under TypeStack, not similarly named forks. NestJS's version is
|
|
40
|
+
the version of `@nestjs/core`. The comparison uses Effect **3** documentation explicitly. Katagami 3.0.2 is this documentation
|
|
41
|
+
release; its runtime and public APIs are unchanged from the reviewed 3.0.1 package.
|
|
42
|
+
|
|
43
|
+
| Package | Reviewed version and registry metadata | Primary documentation / shipped API |
|
|
7
44
|
| --- | --- | --- |
|
|
8
|
-
|
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
45
|
+
| Katagami | [3.0.1](https://registry.npmjs.org/katagami/3.0.1) | [Type guarantees](./type-safety.md), [API guide](./guide.md) |
|
|
46
|
+
| InversifyJS | [8.2.3](https://registry.npmjs.org/inversify/8.2.3) | [8.x setup](https://inversify.io/docs/introduction/getting-started/), [bindings](https://inversify.io/docs/fundamentals/binding/), [container API](https://inversify.io/docs/api/container/) |
|
|
47
|
+
| tsyringe | [4.10.0](https://registry.npmjs.org/tsyringe/4.10.0) | [Release README](https://github.com/microsoft/tsyringe/blob/e033769d97cfb6cc4a8569e2b50eb32015453302/README.md), [container types](https://github.com/microsoft/tsyringe/blob/e033769d97cfb6cc4a8569e2b50eb32015453302/src/types/dependency-container.ts) |
|
|
48
|
+
| TypeDI | [0.10.0](https://registry.npmjs.org/typedi/0.10.0) | [Release source](https://github.com/typestack/typedi/tree/v0.10.0), [container implementation](https://github.com/typestack/typedi/blob/v0.10.0/src/container-instance.class.ts) |
|
|
49
|
+
| Awilix | [13.0.5](https://registry.npmjs.org/awilix/13.0.5) | [Release README](https://github.com/jeffijoe/awilix/blob/f72d175ddb950c3f13ef41e8be98b24471d59900/README.md), [container types/implementation](https://github.com/jeffijoe/awilix/blob/f72d175ddb950c3f13ef41e8be98b24471d59900/src/container.ts) |
|
|
50
|
+
| NestJS | [12.0.1](https://registry.npmjs.org/@nestjs%2fcore/12.0.1) | [Providers](https://docs.nestjs.com/fundamentals/custom-providers), [scopes](https://docs.nestjs.com/fundamentals/injection-scopes), [async providers](https://docs.nestjs.com/fundamentals/async-providers), [lifecycle](https://docs.nestjs.com/fundamentals/lifecycle-events) |
|
|
51
|
+
| Effect | [3.22.2](https://registry.npmjs.org/effect/3.22.2) | [v3 layers](https://effect.website/docs/v3/requirements-management/layers), [v3 scope](https://effect.website/docs/v3/resource-management/scope) |
|
|
52
|
+
| typed-inject | [5.0.0](https://registry.npmjs.org/typed-inject/5.0.0) | [Release README](https://github.com/nicojs/typed-inject/blob/5d3c0276e65ade1d683239346488708b7a11e443/README.md), [injector types](https://github.com/nicojs/typed-inject/blob/5d3c0276e65ade1d683239346488708b7a11e443/src/api/Injector.ts) |
|
|
53
|
+
|
|
54
|
+
Versioned npm tarballs were also inspected. A focused TypeScript 5.9.3 check confirmed that
|
|
55
|
+
Awilix 13.0.5 infers registered cradle properties and rejects an unknown cradle property, while
|
|
56
|
+
`resolve('missing')` still compiles through its broad overload. The same check confirmed that
|
|
57
|
+
typed-inject 5.0.0 and Katagami 3.0.1 reject an unknown literal token, and that Awilix and
|
|
58
|
+
typed-inject infer a Promise returned by a factory. This is a type check, not a performance benchmark
|
|
59
|
+
or an exhaustive runtime compatibility test.
|
|
60
|
+
|
|
61
|
+
## Reading the comparison
|
|
62
|
+
|
|
63
|
+
### Registration types and scope restrictions
|
|
64
|
+
|
|
65
|
+
A typed return value is different from proving that the container has a registration. InversifyJS,
|
|
66
|
+
tsyringe and TypeDI expose class/generic-token APIs without accumulating the set of registered keys
|
|
67
|
+
into the container's type. Awilix has both inferred cradle access and a broad string/symbol `resolve`
|
|
68
|
+
overload. Its opt-in strict mode checks lifetime leaks at runtime. These observations come from the
|
|
69
|
+
published APIs linked above, not from treating all of these libraries as “untyped.”
|
|
70
|
+
|
|
71
|
+
NestJS handles request-scoped dependencies by propagating request scope up the dependency chain.
|
|
72
|
+
That is a different policy from Katagami rejecting scoped access in a singleton factory. Effect's
|
|
73
|
+
`Scope` requirement ensures resource acquisition has a scope; it does not use Katagami's
|
|
74
|
+
singleton/transient/scoped categories. typed-inject has disposable child injectors, but its provider
|
|
75
|
+
scope enum offers singleton and transient, not a separate scoped registration policy.
|
|
13
76
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
77
|
+
### Setup and bundles
|
|
78
|
+
|
|
79
|
+
Katagami, Awilix, Effect and typed-inject do not require decorator metadata for their DI APIs.
|
|
80
|
+
The documented TypeScript class-injection paths for InversifyJS, tsyringe and TypeDI use metadata;
|
|
81
|
+
explicit factory/value bindings should not be described as requiring decorators on every service.
|
|
82
|
+
NestJS provides framework modules and metadata-based injection as well as custom providers.
|
|
83
|
+
|
|
84
|
+
Katagami and typed-inject have no runtime dependency packages. TypeDI's manifest also has no
|
|
85
|
+
`dependencies`, but its TypeScript setup asks the application to install `reflect-metadata`.
|
|
86
|
+
Awilix's Node package lists `fast-glob`; its browser build excludes filesystem-based module loading.
|
|
87
|
+
“No decorators” therefore does not mean “no dependency packages.”
|
|
88
|
+
|
|
89
|
+
Katagami publishes ESM, CommonJS, subpath exports and `sideEffects: false`. Effect also exposes
|
|
90
|
+
ESM/subpath exports and a side-effect declaration, and TypeDI declares `sideEffects: false`.
|
|
91
|
+
The other libraries should not receive an automatic “no tree shaking” mark. Actual output size
|
|
92
|
+
depends on the entry point, imports, bundler and application; no comparative bundle-size benchmark
|
|
93
|
+
was run for this table.
|
|
94
|
+
|
|
95
|
+
### Async and cleanup
|
|
96
|
+
|
|
97
|
+
Katagami exposes `Promise<T>` for async factories: dependent factories explicitly await that value.
|
|
98
|
+
Awilix, typed-inject and the generic factory/value APIs in tsyringe and TypeDI can also carry a
|
|
99
|
+
Promise-valued service. This is different from InversifyJS's async resolution or NestJS's async
|
|
100
|
+
providers, which await dependencies before constructing their consumers. Effect models acquisition
|
|
101
|
+
as an effect. A binary “async factories: no” would conceal these distinctions.
|
|
102
|
+
|
|
103
|
+
Katagami's `disposable()` owns container singletons or scope instances and calls disposal-symbol
|
|
104
|
+
methods. Its [compatibility requirements](./guide.md#compatibility) still apply. InversifyJS has
|
|
105
|
+
[singleton deactivation handlers](https://inversify.io/docs/fundamentals/lifecycle/deactivation/); tsyringe and typed-inject support disposable constructed instances;
|
|
106
|
+
Awilix disposes cached scoped/singleton values through registered disposers. TypeDI can call
|
|
107
|
+
`destroy()` during reset/removal but does not await its return. NestJS's application lifecycle hooks
|
|
108
|
+
are not invoked for request-scoped classes. Effect scopes run registered finalizers. These are
|
|
109
|
+
different ownership and shutdown models, not interchangeable cleanup guarantees.
|
|
110
|
+
|
|
111
|
+
## Composition and tooling
|
|
112
|
+
|
|
113
|
+
This table restores the broader feature comparison using concrete APIs. “Compose” means ordinary
|
|
114
|
+
application code can implement the pattern; it does not claim a dedicated container feature.
|
|
115
|
+
|
|
116
|
+
| Library | Optional / multiple resolution | Composition, discovery and extension |
|
|
117
|
+
| --- | --- | --- |
|
|
118
|
+
| Katagami | `tryResolve`, `resolveAll`, `tryResolveAll` | `use()` copies registrations; opt-in `lazy()`; ordinary higher-order factories |
|
|
119
|
+
| InversifyJS | Optional get/inject, `getAll`, `getAllAsync` | Container modules/hierarchy, autobinding, contextual constraints, activation/deactivation, snapshot/restore |
|
|
120
|
+
| tsyringe | Optional inject, `injectAll`, `resolveAll` | `@registry`, child containers, before/after resolution interceptors, `delay()` |
|
|
121
|
+
| TypeDI | `has` before `get`; `getMany` with multiple registrations | Named containers, factory configuration and service decorators |
|
|
122
|
+
| Awilix | `allowUnregistered`; compose collections as values/factories | `loadModules`, child scopes, local injections and proxy/classic injection |
|
|
123
|
+
| NestJS | Optional injection/provider dependencies; compose array providers | Modules/dynamic modules, provider overrides, discovery service and lazy modules |
|
|
124
|
+
| Effect | [`serviceOption`](https://effect.website/docs/v3/requirements-management/services#optional-services); compose collection-valued services | Layer composition, service substitution and scoped acquisition |
|
|
125
|
+
| typed-inject | Required tokens checked statically; compose optional values/collections | Child injectors, provider replacement/decoration and explicit injection tuples |
|
|
18
126
|
|
|
19
|
-
|
|
20
|
-
|
|
127
|
+
Katagami does not implement filesystem auto-discovery or snapshot/restore, and its runtime
|
|
128
|
+
containers are mutable. `use()` and fresh test containers provide explicit composition and test
|
|
129
|
+
substitution. Factory wrappers are an application pattern, not a middleware/interceptor API.
|
|
130
|
+
Similarly, a lazy module loader is not the same feature as a proxy that constructs one service on
|
|
131
|
+
first property access, and a resolution graph scope is not an HTTP request scope.
|
|
21
132
|
|
|
22
|
-
|
|
133
|
+
Start with the [runnable starter](../examples/request-scope/README.md) and
|
|
134
|
+
[composition guide](./guide.md#composition-and-test-substitution). For a project already built on
|
|
135
|
+
NestJS or Effect, adopting its existing DI model can be simpler than maintaining a second container.
|
|
23
136
|
|
|
24
|
-
|
|
25
|
-
- [InversifyJS getting started](https://inversify.io/docs/introduction/getting-started/).
|
|
26
|
-
- [TypeScript type compatibility](https://www.typescriptlang.org/docs/handbook/type-compatibility).
|
|
137
|
+
## Updating the comparison
|
|
27
138
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
139
|
+
Preserve a comparison and Katagami's supported advantages in the README when editing positioning.
|
|
140
|
+
Refresh the date, npm dist-tag versions and official sources together. Check published declarations
|
|
141
|
+
when a claim involves inference or registration guarantees, and distinguish built-in features from
|
|
142
|
+
wrappers, configuration and framework behavior. Keep localized summaries aligned with the English
|
|
143
|
+
comparison. Do not infer a feature's absence from its omission in a quick-start guide.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "katagami",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Type-safe dependency injection for TypeScript, with inferred types and scope checks for AI-assisted development. No decorators or reflect-metadata.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|