katagami 3.0.2 → 3.0.3
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 +82 -37
- package/docs/README.de.md +1 -1
- package/docs/README.es.md +1 -1
- package/docs/README.fr.md +1 -1
- package/docs/README.ja.md +60 -27
- package/docs/README.ko.md +1 -1
- package/docs/README.zh-CN.md +1 -1
- package/docs/README.zh-TW.md +1 -1
- package/docs/choosing-di.md +30 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,43 +57,88 @@ These checks assume narrow tokens and preserved registration types; see the
|
|
|
57
57
|
|
|
58
58
|
### Library comparison
|
|
59
59
|
|
|
60
|
-
Reviewed **2026-09-11**, against the npm `latest`
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
60
|
+
**27 features across eight libraries.** Reviewed **2026-09-11**, against the npm `latest`
|
|
61
|
+
versions shown below and official documentation. [Versions, sources and detailed notes](./docs/choosing-di.md#comparison-sources).
|
|
62
|
+
|
|
63
|
+
**✅ Built-in support · ⚠️ Conditions, a different model or application composition · ➖ No built-in support for this specific capability.**
|
|
64
|
+
Short labels identify the actual API or limitation.
|
|
65
|
+
|
|
66
|
+
#### Type safety and setup
|
|
67
|
+
|
|
68
|
+
| Feature | **Katagami**<br>**3.0.3** | InversifyJS<br>8.2.3 | tsyringe<br>4.10.0 | TypeDI<br>0.10.0 | Awilix<br>13.0.5 | NestJS<br>12.0.1 | Effect<br>3.22.2 | typed-inject<br>5.0.0 |
|
|
69
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
70
|
+
| **Runtime requirements** | **✅ Standard TypeScript** | ⚠️ Reflect metadata for class DI | ⚠️ Reflect metadata for class DI | ⚠️ Reflect metadata setup | ✅ No DI metadata | ⚠️ Nest modules / metadata | ✅ Effect / Layer APIs | ✅ Standard TypeScript |
|
|
71
|
+
| **Injection style** | **Explicit factories / constructors** | Constructor / property / factory | Constructor / factory | Constructor / property / factory | Proxy / classic / factory | Constructor / property / factory | Functional services / layers | Constructor / factory + `inject` |
|
|
72
|
+
| **Token types** | **Class / string / number / symbol** | Class / string / symbol | Class / string / symbol | Class / string / `Token<T>` | String / symbol | Class / string / symbol | `Context.Tag` | String literals |
|
|
73
|
+
| **Type safety** | **✅ Inferred services + scope checks** | ✅ Typed identifiers / bindings | ✅ Class / generic types | ✅ Class / `Token<T>` | ✅ Inferred cradle | ✅ Typed providers | ✅ Typed service requirements | ✅ Tokens + `inject` tuples |
|
|
74
|
+
| **Registration-derived types** | **✅ Accumulated tokens** | ➖ | ➖ | ➖ | ✅ `register` → cradle | ➖ | ⚠️ Layer requirements | ✅ Accumulated tokens |
|
|
75
|
+
| **Missing required tokens: compile-time check¹** | **✅ Literal / unique-symbol keys** | ➖ Runtime check | ➖ Runtime check | ➖ Runtime check | ⚠️ Cradle only | ➖ Runtime graph | ✅ Unsatisfied requirements | ✅ Literal keys |
|
|
76
|
+
| **Scoped access from singleton/transient factories: compile-time check¹** | **✅ Scoped tokens excluded** | ➖ | ➖ | ➖ | ⚠️ Runtime strict mode | ⚠️ Request-scope propagation | ⚠️ Different `Scope` model | ➖ No scoped lifetime |
|
|
77
|
+
| **Zero runtime dependency packages²** | **✅** | ➖ | ➖ | ⚠️ Reflect polyfill installed separately | ⚠️ Browser entry differs | ➖ | ➖ | ✅ |
|
|
78
|
+
| **Tree-shaking support²** | **✅ ESM / subpaths / `sideEffects: false`** | ⚠️ ESM; `sideEffects: true` | ⚠️ ESM build | ✅ ESM / `sideEffects: false` | ⚠️ ESM / browser builds | ⚠️ ESM / framework setup | ✅ ESM / subpaths / side-effect declaration | ⚠️ ESM build |
|
|
79
|
+
|
|
80
|
+
#### Lifetimes, async services and cleanup
|
|
81
|
+
|
|
82
|
+
| Feature | **Katagami**<br>**3.0.3** | InversifyJS<br>8.2.3 | tsyringe<br>4.10.0 | TypeDI<br>0.10.0 | Awilix<br>13.0.5 | NestJS<br>12.0.1 | Effect<br>3.22.2 | typed-inject<br>5.0.0 |
|
|
83
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
84
|
+
| **Lifetimes** | **✅ Singleton / Transient / Scoped** | ✅ Singleton / Transient / Request | ✅ Singleton / Transient / Resolution / Container | ✅ Shared / Transient | ✅ Singleton / Transient / Scoped | ✅ Singleton / Transient / Request | ⚠️ Memoized / fresh layers + scopes | ✅ Singleton / Transient |
|
|
85
|
+
| **Request / scoped lifetime³** | **✅ Explicit per-request scope** | ⚠️ One resolution graph | ✅ Container / resolution scoped | ⚠️ Named containers | ✅ Explicit per-request scope | ✅ HTTP request scope | ⚠️ Resource scopes | ⚠️ Child injectors; no Scoped provider |
|
|
86
|
+
| **Child containers / nested scopes³** | **✅ Nested scopes** | ✅ Container hierarchy | ✅ Child containers | ⚠️ Named containers | ✅ Child scopes | ⚠️ Module / request contexts | ⚠️ Nested resource scopes | ✅ Child injectors |
|
|
87
|
+
| **Async factories** | **✅ Promise-valued factories** | ✅ Async bindings | ✅ Promise-valued factories | ✅ Promise-valued services | ✅ Promise-valued factories | ✅ Async providers | ✅ Effectful acquisition | ✅ Promise-valued factories |
|
|
88
|
+
| **Async result type tracking** | **✅ Inferred `Promise<T>`** | ✅ `getAsync<T>` | ⚠️ Promise-valued service type | ⚠️ Promise-valued service type | ✅ Inferred `Promise<T>` | ⚠️ Provider / consumer types | ✅ Effect result / error / requirements | ✅ Inferred `Promise<T>` |
|
|
89
|
+
| **Automatically await async dependencies⁴** | **➖ Explicit `await`** | ✅ `getAsync` / `getAllAsync` | ➖ Consumer awaits | ➖ Consumer awaits | ➖ Consumer awaits | ✅ Before consumer construction | ✅ Effect composition | ➖ Consumer awaits |
|
|
90
|
+
| **Resource cleanup⁵** | **✅ Disposal symbols / `await using`** | ⚠️ Singleton deactivation | ✅ Constructed disposables | ⚠️ `destroy()` on reset / removal | ⚠️ Cached values + disposer | ⚠️ App lifecycle hooks | ✅ Scope finalizers | ✅ Owned disposable instances |
|
|
91
|
+
| **Await asynchronous cleanup⁵** | **✅ `Symbol.asyncDispose`** | ✅ Async deactivation | ✅ `container.dispose()` | ➖ `destroy()` is not awaited | ✅ `container.dispose()` | ⚠️ App hooks; not request-scoped classes | ✅ Effect finalizers | ✅ `injector.dispose()` |
|
|
92
|
+
|
|
93
|
+
#### Composition and advanced features
|
|
94
|
+
|
|
95
|
+
| Feature | **Katagami**<br>**3.0.3** | InversifyJS<br>8.2.3 | tsyringe<br>4.10.0 | TypeDI<br>0.10.0 | Awilix<br>13.0.5 | NestJS<br>12.0.1 | Effect<br>3.22.2 | typed-inject<br>5.0.0 |
|
|
96
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
97
|
+
| **Optional resolution** | **✅ `tryResolve` / `tryResolveAll`** | ✅ Optional get / inject | ✅ Optional injection | ⚠️ `has` then `get` | ✅ `allowUnregistered` | ✅ Optional injection | ✅ `serviceOption` | ⚠️ Compose optional values |
|
|
98
|
+
| **Multi-binding** | **✅ `resolveAll`** | ✅ `getAll` / `getAllAsync` | ✅ `injectAll` / `resolveAll` | ✅ `getMany` | ⚠️ Collection-valued service | ⚠️ Array provider | ⚠️ Collection-valued service | ⚠️ Collection-valued service |
|
|
99
|
+
| **Lazy resolution⁶** | **✅ `lazy()`; sync class tokens** | ⚠️ Deferred identifiers / factories | ✅ `delay()` proxy | ⚠️ Deferred type reference | ⚠️ Cradle property access | ⚠️ `LazyModuleLoader` | ⚠️ Lazy effect execution | ⚠️ Inject a factory |
|
|
100
|
+
| **Conditional bindings** | **⚠️ Tokens / factory logic** | ✅ Contextual constraints | ✅ Predicate-aware factory | ⚠️ Factory logic | ⚠️ Local injection / factory logic | ⚠️ Dynamic modules / factories | ⚠️ Select / compose layers | ⚠️ Factory logic |
|
|
101
|
+
| **Auto-loading / discovery⁶** | **➖ Explicit `use()`** | ⚠️ Class autobinding | ➖ Explicit registrations | ➖ Explicit imports | ✅ `loadModules` (Node) | ⚠️ `DiscoveryService` | ➖ Explicit layers | ➖ Explicit providers |
|
|
102
|
+
| **Module system / composition** | **✅ `use()`** | ✅ Container modules | ✅ `@registry` | ⚠️ Group registrations | ✅ `loadModules` / `register` | ✅ Modules / dynamic modules | ✅ Layer composition | ⚠️ Compose provider chains |
|
|
103
|
+
| **Circular dependency detection⁷** | **✅ Runtime cycle path** | ✅ Runtime detection | ⚠️ Constructor error / `delay` | ⚠️ Deferred type references | ✅ Runtime cycle path | ⚠️ Cycle errors / `forwardRef` | ⚠️ Typed Layer requirements | ⚠️ Registration order constrains dependencies |
|
|
104
|
+
| **Middleware / interceptors⁶** | **⚠️ Higher-order factories** | ✅ Activation / deactivation hooks | ✅ Before / after resolution | ⚠️ Factory wrappers | ⚠️ Factory wrappers | ⚠️ Request interceptors, not DI hooks | ⚠️ Effect composition | ⚠️ Provider decoration |
|
|
105
|
+
| **Snapshot / restore⁶** | **➖** | ✅ `snapshot` / `restore` | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ |
|
|
106
|
+
| **Test substitution / isolation** | **✅ Fresh scopes / containers + `use()`** | ✅ Rebind / snapshots | ✅ Child container overrides | ✅ Named containers / reset | ✅ Child scopes / overrides | ✅ `overrideProvider` | ✅ Substitute test layers | ✅ Child injector overrides |
|
|
107
|
+
|
|
108
|
+
**What stands out:** Katagami combines **accumulated registration types, scope-filtered factory
|
|
109
|
+
resolvers, three lifetimes and zero runtime dependencies** with direct `r.resolve(token)` calls.
|
|
110
|
+
Optional/multiple resolution, module composition, lazy class resolution and standards-based cleanup
|
|
111
|
+
stay available without decorator setup. Awilix, Effect and typed-inject also provide meaningful
|
|
112
|
+
compile-time checks, as shown above.
|
|
113
|
+
|
|
114
|
+
<details>
|
|
115
|
+
<summary>Comparison notes: type guarantees, scopes, async behavior and feature boundaries</summary>
|
|
116
|
+
|
|
117
|
+
1. **Type guarantees:** Katagami's missing-token guarantee applies to accumulated literal keys and
|
|
118
|
+
unique symbols with their types preserved. Class tokens, predeclared maps and mutable aliases
|
|
119
|
+
have [documented boundaries](./docs/type-safety.md). Awilix rejects unknown cradle properties,
|
|
120
|
+
but its broad `resolve` overload accepts unknown names. Effect checks service requirements in
|
|
121
|
+
its own model. Scope checks here mean excluding scoped tokens from singleton/transient resolvers.
|
|
122
|
+
2. **Setup and bundles:** Metadata notes describe the documented class-injection path; explicit
|
|
123
|
+
value/factory bindings can avoid decorating individual services. Core Katagami needs no polyfills;
|
|
124
|
+
disposal has [host/compiler requirements](./docs/guide.md#compatibility). ESM and side-effect
|
|
125
|
+
declarations help tree shaking, but these are packaging comparisons, not measured bundle sizes.
|
|
126
|
+
3. **Scopes:** InversifyJS Request means one resolution graph, not an HTTP request. Named containers,
|
|
127
|
+
module contexts, child injectors and Effect resource scopes are not identical lifetime policies.
|
|
128
|
+
4. **Async:** Returning a Promise is distinct from awaiting dependencies before injection.
|
|
129
|
+
Katagami keeps the Promise in the inferred type and leaves `await` explicit.
|
|
130
|
+
5. **Cleanup:** Katagami's opt-in `disposable()` integrates `Symbol.dispose`, `Symbol.asyncDispose`
|
|
131
|
+
and `await using`. Ownership varies by library; InversifyJS deactivation is for singletons,
|
|
132
|
+
Awilix disposers are for cached values, and Nest hooks exclude request-scoped classes.
|
|
133
|
+
6. **Composition versus dedicated APIs:** A service proxy, deferred token and lazy module are
|
|
134
|
+
different features. Autobinding/discovery is not filesystem loading. Katagami's `use()` copies
|
|
135
|
+
registrations; containers are mutable. Factory wrappers are not interceptor APIs, and fresh
|
|
136
|
+
containers are not snapshots. [Composition details](./docs/choosing-di.md#composition-and-tooling).
|
|
137
|
+
7. **Cycles:** Runtime cycle detection, deferred references and static dependency requirements are
|
|
138
|
+
different mechanisms. A ⚠️ entry does not promise a general cycle detector; runtime checks do
|
|
139
|
+
not imply detection of every asynchronous deadlock.
|
|
140
|
+
|
|
141
|
+
</details>
|
|
97
142
|
|
|
98
143
|
## Why Katagami for AI-assisted development?
|
|
99
144
|
|
package/docs/README.de.md
CHANGED
|
@@ -33,7 +33,7 @@ Katagami verbindet **aus Registrierungen abgeleitete Typen, Scope-Prüfungen zur
|
|
|
33
33
|
|
|
34
34
|
| Bibliothek / Version | Abhängigkeitstypen und Registrierungsprüfung | Scope-Verhalten |
|
|
35
35
|
| --- | --- | --- |
|
|
36
|
-
| **Katagami 3.0.
|
|
36
|
+
| **Katagami 3.0.3** | **Sammelt Literal-/unique-symbol-Tokens; fehlende erforderliche Tokens sind Typfehler** | **Scoped-Tokens im Resolver von Singleton-/Transient-Factories ausgeschlossen** |
|
|
37
37
|
| InversifyJS 8.2.3 | Typisierte Bindings; Existenzprüfung zur Laufzeit | Konfigurierte Binding-Lebensdauer |
|
|
38
38
|
| tsyringe 4.10.0 | Klassen-/generische Typen; Registrierungsprüfung zur Laufzeit | Lebensdauer und Kindcontainer |
|
|
39
39
|
| TypeDI 0.10.0 | Klassen und `Token<T>`; Registrierungsprüfung zur Laufzeit | Geteilte/Transient-Services, benannte Container |
|
package/docs/README.es.md
CHANGED
|
@@ -33,7 +33,7 @@ Katagami combina **tipos derivados del registro, restricciones de ámbito en com
|
|
|
33
33
|
|
|
34
34
|
| Biblioteca / versión | Tipos y comprobación de registros | Política de ámbitos |
|
|
35
35
|
| --- | --- | --- |
|
|
36
|
-
| **Katagami 3.0.
|
|
36
|
+
| **Katagami 3.0.3** | **Acumula tokens literales/unique symbol; rechaza tokens requeridos sin registrar** | **Excluye tokens Scoped del resolver de factorías Singleton/Transient** |
|
|
37
37
|
| InversifyJS 8.2.3 | Bindings tipados; existencia comprobada en ejecución | Ciclo de vida configurado por binding |
|
|
38
38
|
| tsyringe 4.10.0 | Tipos de clase/genéricos; registros comprobados en ejecución | Ciclos de vida y contenedores hijos |
|
|
39
39
|
| TypeDI 0.10.0 | Clases y `Token<T>`; registros comprobados en ejecución | Servicios compartidos/Transient y contenedores con nombre |
|
package/docs/README.fr.md
CHANGED
|
@@ -33,7 +33,7 @@ Katagami associe **types déduits des enregistrements, restrictions de portée
|
|
|
33
33
|
|
|
34
34
|
| Bibliothèque / version | Types et vérification des enregistrements | Politique de portée |
|
|
35
35
|
| --- | --- | --- |
|
|
36
|
-
| **Katagami 3.0.
|
|
36
|
+
| **Katagami 3.0.3** | **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
37
|
| InversifyJS 8.2.3 | Bindings typés ; existence vérifiée à l'exécution | Durée de vie configurée par binding |
|
|
38
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
39
|
| TypeDI 0.10.0 | Classes et `Token<T>` ; enregistrements vérifiés à l'exécution | Services partagés/Transient, conteneurs nommés |
|
package/docs/README.ja.md
CHANGED
|
@@ -36,33 +36,66 @@ Katagamiの強みは、**登録からの型推論・コンパイル時のスコ
|
|
|
36
36
|
|
|
37
37
|
### 他ライブラリとの比較
|
|
38
38
|
|
|
39
|
-
**2026-09-11確認。** npm
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
| tsyringe
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
| TypeDI |
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
65
|
-
|
|
39
|
+
**8ライブラリ・27項目の比較。2026-09-11確認。** 表中のnpm `latest`安定版と公式資料をもとにしています。[対象バージョン・出典・詳細な注記](./choosing-di.md#comparison-sources)。
|
|
40
|
+
|
|
41
|
+
**✅ 標準で対応 · ⚠️ 条件付き・異なるモデル・利用側での合成 · ➖ その機能の標準対応なし。** 各セルに具体的なAPIや条件を添えています。
|
|
42
|
+
|
|
43
|
+
#### 型安全性・導入設定
|
|
44
|
+
|
|
45
|
+
| 比較項目 | **Katagami**<br>**3.0.3** | InversifyJS<br>8.2.3 | tsyringe<br>4.10.0 | TypeDI<br>0.10.0 | Awilix<br>13.0.5 | NestJS<br>12.0.1 | Effect<br>3.22.2 | typed-inject<br>5.0.0 |
|
|
46
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
47
|
+
| **ランタイム要件** | **✅ 通常のTypeScript** | ⚠️ クラスDIにReflectメタデータ | ⚠️ クラスDIにReflectメタデータ | ⚠️ Reflectメタデータ設定 | ✅ DIメタデータ不要 | ⚠️ Nestモジュール・メタデータ | ✅ Effect・Layer API | ✅ 通常のTypeScript |
|
|
48
|
+
| **注入方式** | **明示的なファクトリ・コンストラクタ** | コンストラクタ・プロパティ・ファクトリ | コンストラクタ・ファクトリ | コンストラクタ・プロパティ・ファクトリ | Proxy・Classic・ファクトリ | コンストラクタ・プロパティ・ファクトリ | 関数型サービス・Layer | コンストラクタ・ファクトリ+`inject` |
|
|
49
|
+
| **トークンの種類** | **クラス・文字列・数値・symbol** | クラス・文字列・symbol | クラス・文字列・symbol | クラス・文字列・`Token<T>` | 文字列・symbol | クラス・文字列・symbol | `Context.Tag` | 文字列リテラル |
|
|
50
|
+
| **型安全性** | **✅ サービス推論+スコープ検査** | ✅ 型付き識別子・binding | ✅ クラス・ジェネリック | ✅ クラス・`Token<T>` | ✅ cradleの推論 | ✅ 型付きprovider | ✅ サービス要求の型検査 | ✅ トークン+`inject`タプル |
|
|
51
|
+
| **登録からの型の蓄積** | **✅ トークンの型を蓄積** | ➖ | ➖ | ➖ | ✅ `register` → cradle | ➖ | ⚠️ Layerの要求型 | ✅ トークンの型を蓄積 |
|
|
52
|
+
| **未登録の必須トークンをコンパイル時に検出¹** | **✅ リテラル・unique symbol** | ➖ 実行時に検査 | ➖ 実行時に検査 | ➖ 実行時に検査 | ⚠️ cradleでの参照のみ | ➖ 実行時の依存グラフ | ✅ 未充足のサービス要求 | ✅ リテラルキー |
|
|
53
|
+
| **Singleton・TransientからのScoped参照を型で制限¹** | **✅ Scopedトークンを除外** | ➖ | ➖ | ➖ | ⚠️ strictモードで実行時検査 | ⚠️ Requestスコープが伝播 | ⚠️ 異なる`Scope`モデル | ➖ Scopedライフタイムなし |
|
|
54
|
+
| **ランタイム依存パッケージゼロ²** | **✅** | ➖ | ➖ | ⚠️ Reflectポリフィルを別途導入 | ⚠️ ブラウザ版は構成が異なる | ➖ | ➖ | ✅ |
|
|
55
|
+
| **ツリーシェイキング対応²** | **✅ ESM・サブパス・`sideEffects: false`** | ⚠️ ESM・`sideEffects: true` | ⚠️ ESMビルド | ✅ ESM・`sideEffects: false` | ⚠️ ESM・ブラウザビルド | ⚠️ ESM・フレームワーク設定 | ✅ ESM・サブパス・副作用宣言 | ⚠️ ESMビルド |
|
|
56
|
+
|
|
57
|
+
#### ライフタイム・非同期・リソース破棄
|
|
58
|
+
|
|
59
|
+
| 比較項目 | **Katagami**<br>**3.0.3** | InversifyJS<br>8.2.3 | tsyringe<br>4.10.0 | TypeDI<br>0.10.0 | Awilix<br>13.0.5 | NestJS<br>12.0.1 | Effect<br>3.22.2 | typed-inject<br>5.0.0 |
|
|
60
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
61
|
+
| **ライフタイム** | **✅ Singleton・Transient・Scoped** | ✅ Singleton・Transient・Request | ✅ Singleton・Transient・Resolution・Container | ✅ 共有・Transient | ✅ Singleton・Transient・Scoped | ✅ Singleton・Transient・Request | ⚠️ メモ化/fresh Layer+Scope | ✅ Singleton・Transient |
|
|
62
|
+
| **リクエスト/Scopedライフタイム³** | **✅ リクエストごとに明示的なScope** | ⚠️ 1回の解決グラフ | ✅ Container/Resolution単位 | ⚠️ 名前付きコンテナ | ✅ リクエストごとに明示的なScope | ✅ HTTPリクエスト単位 | ⚠️ リソースScope | ⚠️ 子injector。Scoped登録なし |
|
|
63
|
+
| **子コンテナ/ネストしたスコープ³** | **✅ ネストしたScope** | ✅ コンテナ階層 | ✅ 子コンテナ | ⚠️ 名前付きコンテナ | ✅ 子Scope | ⚠️ モジュール/Requestのコンテキスト | ⚠️ ネストしたリソースScope | ✅ 子injector |
|
|
64
|
+
| **非同期ファクトリ** | **✅ Promiseを返すファクトリ** | ✅ 非同期binding | ✅ Promiseを返すファクトリ | ✅ Promise値のサービス | ✅ Promiseを返すファクトリ | ✅ 非同期provider | ✅ Effectによる取得 | ✅ Promiseを返すファクトリ |
|
|
65
|
+
| **非同期の戻り値の型追跡** | **✅ `Promise<T>`を推論** | ✅ `getAsync<T>` | ⚠️ Promise値として型付け | ⚠️ Promise値として型付け | ✅ `Promise<T>`を推論 | ⚠️ provider・利用側の型指定 | ✅ 結果・エラー・要求の型 | ✅ `Promise<T>`を推論 |
|
|
66
|
+
| **非同期の依存を自動的にawait⁴** | **➖ 明示的に`await`** | ✅ `getAsync`・`getAllAsync` | ➖ 利用側でawait | ➖ 利用側でawait | ➖ 利用側でawait | ✅ 依存元の構築前に待機 | ✅ Effectの合成 | ➖ 利用側でawait |
|
|
67
|
+
| **リソース破棄⁵** | **✅ disposalシンボル・`await using`** | ⚠️ Singletonのdeactivation | ✅ 構築したDisposable | ⚠️ reset・削除時の`destroy()` | ⚠️ キャッシュした値+disposer | ⚠️ アプリのライフサイクルフック | ✅ Scopeのfinalizer | ✅ 所有するDisposable |
|
|
68
|
+
| **非同期の破棄完了を待機⁵** | **✅ `Symbol.asyncDispose`** | ✅ 非同期deactivation | ✅ `container.dispose()` | ➖ `destroy()`を待機しない | ✅ `container.dispose()` | ⚠️ アプリのフック。Requestは対象外 | ✅ Effectのfinalizer | ✅ `injector.dispose()` |
|
|
69
|
+
|
|
70
|
+
#### 合成・拡張機能
|
|
71
|
+
|
|
72
|
+
| 比較項目 | **Katagami**<br>**3.0.3** | InversifyJS<br>8.2.3 | tsyringe<br>4.10.0 | TypeDI<br>0.10.0 | Awilix<br>13.0.5 | NestJS<br>12.0.1 | Effect<br>3.22.2 | typed-inject<br>5.0.0 |
|
|
73
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
74
|
+
| **オプショナル解決** | **✅ `tryResolve`・`tryResolveAll`** | ✅ オプショナルget・inject | ✅ オプショナル注入 | ⚠️ `has`で確認して`get` | ✅ `allowUnregistered` | ✅ オプショナル注入 | ✅ `serviceOption` | ⚠️ オプショナル値を合成 |
|
|
75
|
+
| **複数登録・一括解決** | **✅ `resolveAll`** | ✅ `getAll`・`getAllAsync` | ✅ `injectAll`・`resolveAll` | ✅ `getMany` | ⚠️ コレクション値を登録 | ⚠️ 配列provider | ⚠️ コレクション値を登録 | ⚠️ コレクション値を登録 |
|
|
76
|
+
| **遅延解決⁶** | **✅ `lazy()`・同期クラストークン** | ⚠️ 識別子の遅延・ファクトリ | ✅ `delay()`のProxy | ⚠️ 型の遅延参照 | ⚠️ cradleのプロパティ参照 | ⚠️ `LazyModuleLoader` | ⚠️ Effectの遅延実行 | ⚠️ ファクトリを注入 |
|
|
77
|
+
| **条件付きbinding** | **⚠️ トークン分離・ファクトリ内の分岐** | ✅ コンテキスト制約 | ✅ 条件付きファクトリ | ⚠️ ファクトリ内の分岐 | ⚠️ ローカル注入・分岐 | ⚠️ 動的モジュール・ファクトリ | ⚠️ Layerの選択・合成 | ⚠️ ファクトリ内の分岐 |
|
|
78
|
+
| **自動ロード/検出⁶** | **➖ 明示的な`use()`** | ⚠️ クラスの自動binding | ➖ 明示的な登録 | ➖ 明示的なimport | ✅ `loadModules`(Node) | ⚠️ `DiscoveryService` | ➖ 明示的なLayer | ➖ 明示的なprovider |
|
|
79
|
+
| **モジュールシステム・合成** | **✅ `use()`** | ✅ コンテナモジュール | ✅ `@registry` | ⚠️ 登録をまとめる | ✅ `loadModules`・`register` | ✅ モジュール・動的モジュール | ✅ Layerの合成 | ⚠️ providerチェーンの合成 |
|
|
80
|
+
| **循環依存の検出⁷** | **✅ 実行時に循環経路を表示** | ✅ 実行時に検出 | ⚠️ コンストラクタのエラー・`delay` | ⚠️ 型の遅延参照 | ✅ 実行時に循環経路を表示 | ⚠️ 循環エラー・`forwardRef` | ⚠️ Layerの要求型 | ⚠️ 登録順で依存を制限 |
|
|
81
|
+
| **ミドルウェア/インターセプタ⁶** | **⚠️ 高階ファクトリで合成** | ✅ activation・deactivationフック | ✅ 解決前後のフック | ⚠️ ファクトリをラップ | ⚠️ ファクトリをラップ | ⚠️ Request用。DIフックとは異なる | ⚠️ Effectを合成 | ⚠️ providerの装飾 |
|
|
82
|
+
| **スナップショット/復元⁶** | **➖** | ✅ `snapshot`・`restore` | ➖ | ➖ | ➖ | ➖ | ➖ | ➖ |
|
|
83
|
+
| **テスト用の差し替え・分離** | **✅ 新しいScope・コンテナ+`use()`** | ✅ 再binding・スナップショット | ✅ 子コンテナで上書き | ✅ 名前付きコンテナ・reset | ✅ 子Scopeで上書き | ✅ `overrideProvider` | ✅ テスト用Layerに差し替え | ✅ 子injectorで上書き |
|
|
84
|
+
|
|
85
|
+
**Katagamiの強み:登録型の蓄積・ファクトリのスコープ制約・3つのライフタイム・ランタイム依存ゼロ**を、直接`r.resolve(token)`を呼べるAPIで組み合わせられます。オプショナル/複数解決、モジュール合成、クラスの遅延解決、標準のdisposalシンボルによる破棄も、デコレータ設定なしで利用できます。Awilix・Effect・typed-injectにも、表に示したコンパイル時の検査機能があります。
|
|
86
|
+
|
|
87
|
+
<details>
|
|
88
|
+
<summary>比較の注記:型の保証・スコープ・非同期・各機能の対応範囲</summary>
|
|
89
|
+
|
|
90
|
+
1. **型の保証:** Katagamiは、型が保たれたリテラルキー・unique symbolを蓄積する方式で未登録トークンを検出します。クラストークン・事前宣言・変更可能な参照には[保証範囲の条件](./type-safety.md)があります。Awilixは未登録のcradleプロパティを拒否しますが、広い`resolve`オーバーロードは未登録名も許可します。Effectは独自のサービス要求を検査します。スコープ制約の行は、Singleton・TransientのresolverからScopedを型で除外する機能の比較です。
|
|
91
|
+
2. **導入とバンドル:** メタデータの記述は公式のクラス注入手順が対象です。明示的な値・ファクトリの登録では、各サービスへのデコレータを省ける場合があります。Katagamiのコアにポリフィルは不要ですが、破棄機能には[ホスト・コンパイラの要件](./guide.md#compatibility)があります。ESM・副作用宣言はツリーシェイキングを助ける構成であり、バンドルサイズの実測比較ではありません。
|
|
92
|
+
3. **スコープ:** InversifyJSのRequestは1回の解決グラフで、HTTPリクエストとは異なります。名前付きコンテナ・モジュールのコンテキスト・子injector・EffectのリソースScopeも、それぞれ異なる管理方式です。
|
|
93
|
+
4. **非同期:** Promiseを返せることと、注入前に依存の完了を自動的に待つことは別です。KatagamiはPromiseを型に残し、`await`を明示します。
|
|
94
|
+
5. **破棄:** Katagamiは追加の`disposable()`で`Symbol.dispose`・`Symbol.asyncDispose`・`await using`に連携します。所有権と破棄対象はライブラリごとに異なり、InversifyJSのdeactivationはSingleton、Awilixのdisposerはキャッシュした値が対象です。NestのフックはRequestスコープのクラスには適用されません。
|
|
95
|
+
6. **合成と専用API:** サービスの遅延Proxy・型参照の遅延・モジュールの遅延ロードは別の機能です。自動binding・検出も、ファイルの自動ロードとは異なります。Katagamiの`use()`は登録をコピーし、コンテナ自体は変更可能です。ファクトリのラップは専用インターセプタではなく、新しいコンテナでの分離はスナップショットではありません。[合成機能の詳細](./choosing-di.md#composition-and-tooling)。
|
|
96
|
+
7. **循環依存:** 実行時の循環検出・参照の遅延・依存の型検査は異なる仕組みです。⚠️は汎用的な循環検出器の存在を意味しません。また、実行時の検出が、あらゆる非同期デッドロックの検出を保証するわけではありません。
|
|
97
|
+
|
|
98
|
+
</details>
|
|
66
99
|
|
|
67
100
|
## AIエージェントによるコーディングで役立つ理由
|
|
68
101
|
|
package/docs/README.ko.md
CHANGED
|
@@ -33,7 +33,7 @@ console.log(greeting);
|
|
|
33
33
|
|
|
34
34
|
| 라이브러리 / 버전 | 의존성 타입과 등록 확인 | 스코프 정책 |
|
|
35
35
|
| --- | --- | --- |
|
|
36
|
-
| **Katagami 3.0.
|
|
36
|
+
| **Katagami 3.0.3** | **리터럴·unique symbol 등록을 누적하고 미등록 필수 토큰 거부** | **Singleton·Transient 팩터리에서 Scoped 토큰을 타입으로 제외** |
|
|
37
37
|
| InversifyJS 8.2.3 | 타입이 있는 binding, 등록 여부는 런타임 확인 | binding의 라이프타임 설정 |
|
|
38
38
|
| tsyringe 4.10.0 | 클래스·제네릭 타입, 등록 여부는 런타임 확인 | 라이프타임 설정과 자식 컨테이너 |
|
|
39
39
|
| TypeDI 0.10.0 | 클래스·`Token<T>`, 등록 여부는 런타임 확인 | 공유·Transient 서비스와 이름 있는 컨테이너 |
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -33,7 +33,7 @@ Katagami 在普通 TypeScript 工厂中结合了**从注册推导类型、编译
|
|
|
33
33
|
|
|
34
34
|
| 库/版本 | 依赖类型与注册检查 | 作用域策略 |
|
|
35
35
|
| --- | --- | --- |
|
|
36
|
-
| **Katagami 3.0.
|
|
36
|
+
| **Katagami 3.0.3** | **累积字面量、unique symbol 的注册类型,拒绝未注册的必需 token** | **从 Singleton、Transient 工厂的 resolver 类型中排除 Scoped token** |
|
|
37
37
|
| InversifyJS 8.2.3 | 有类型的 binding;运行时检查是否已绑定 | binding 的生命周期设置 |
|
|
38
38
|
| tsyringe 4.10.0 | 类与泛型类型;运行时检查注册 | 生命周期设置与子容器 |
|
|
39
39
|
| TypeDI 0.10.0 | 类与 `Token<T>`;运行时检查注册 | 共享、Transient 服务与命名容器 |
|
package/docs/README.zh-TW.md
CHANGED
|
@@ -33,7 +33,7 @@ Katagami 在一般 TypeScript 工廠中結合了**從註冊推導型別、編譯
|
|
|
33
33
|
|
|
34
34
|
| 函式庫/版本 | 依賴型別與註冊檢查 | 作用域策略 |
|
|
35
35
|
| --- | --- | --- |
|
|
36
|
-
| **Katagami 3.0.
|
|
36
|
+
| **Katagami 3.0.3** | **累積字面值、unique symbol 的註冊型別,拒絕未註冊的必要 token** | **從 Singleton、Transient 工廠的 resolver 型別中排除 Scoped token** |
|
|
37
37
|
| InversifyJS 8.2.3 | 具型別的 binding;執行時檢查是否已綁定 | binding 的生命週期設定 |
|
|
38
38
|
| tsyringe 4.10.0 | 類別與泛型型別;執行時檢查註冊 | 生命週期設定與子容器 |
|
|
39
39
|
| TypeDI 0.10.0 | 類別與 `Token<T>`;執行時檢查註冊 | 共用、Transient 服務與具名容器 |
|
package/docs/choosing-di.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Katagami is a strong fit when you want **registration-derived types, explicit request scopes and
|
|
4
4
|
ordinary TypeScript factories without decorators or runtime dependencies**. The
|
|
5
|
-
[README comparison](../README.md#library-comparison) covers
|
|
6
|
-
typing, setup, lifetimes, asynchronous behavior and
|
|
5
|
+
[README comparison](../README.md#library-comparison) covers 27 features across eight libraries,
|
|
6
|
+
including typing, setup, lifetimes, asynchronous behavior, cleanup and composition. This guide records the evidence and
|
|
7
7
|
the features that need more explanation than a table cell.
|
|
8
8
|
|
|
9
9
|
## What distinguishes Katagami
|
|
@@ -37,7 +37,7 @@ typing, mutable aliases and predeclared-map boundaries.
|
|
|
37
37
|
Reviewed **2026-09-11**. Competitor versions are the npm `latest` dist-tag versions observed on that date,
|
|
38
38
|
not prerelease versions or unreleased features from repository default branches. TypeDI refers to
|
|
39
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.
|
|
40
|
+
the version of `@nestjs/core`. The comparison uses Effect **3** documentation explicitly. Katagami 3.0.3 is this documentation
|
|
41
41
|
release; its runtime and public APIs are unchanged from the reviewed 3.0.1 package.
|
|
42
42
|
|
|
43
43
|
| Package | Reviewed version and registry metadata | Primary documentation / shipped API |
|
|
@@ -117,7 +117,7 @@ application code can implement the pattern; it does not claim a dedicated contai
|
|
|
117
117
|
| --- | --- | --- |
|
|
118
118
|
| Katagami | `tryResolve`, `resolveAll`, `tryResolveAll` | `use()` copies registrations; opt-in `lazy()`; ordinary higher-order factories |
|
|
119
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()` |
|
|
120
|
+
| tsyringe | Optional inject, `injectAll`, `resolveAll` | `@registry`, child containers, before/after resolution interceptors, `delay()`, `predicateAwareClassFactory` |
|
|
121
121
|
| TypeDI | `has` before `get`; `getMany` with multiple registrations | Named containers, factory configuration and service decorators |
|
|
122
122
|
| Awilix | `allowUnregistered`; compose collections as values/factories | `loadModules`, child scopes, local injections and proxy/classic injection |
|
|
123
123
|
| NestJS | Optional injection/provider dependencies; compose array providers | Modules/dynamic modules, provider overrides, discovery service and lazy modules |
|
|
@@ -130,6 +130,30 @@ substitution. Factory wrappers are an application pattern, not a middleware/inte
|
|
|
130
130
|
Similarly, a lazy module loader is not the same feature as a proxy that constructs one service on
|
|
131
131
|
first property access, and a resolution graph scope is not an HTTP request scope.
|
|
132
132
|
|
|
133
|
+
The README retains all 18 original comparison aspects and adds nine more specific checks:
|
|
134
|
+
registration-derived types, missing-token checking, compile-time scope restrictions, dependency
|
|
135
|
+
packages, scoped lifetime behavior, async result typing, automatic awaiting, async cleanup and
|
|
136
|
+
test substitution. Its three feature-by-library matrices use the same columns. ✅ means built-in
|
|
137
|
+
support, ⚠️ marks a condition, different model or application composition, and ➖ means that the
|
|
138
|
+
specific capability has no built-in support. The icons are not a total score.
|
|
139
|
+
|
|
140
|
+
Additional API notes for the expanded rows:
|
|
141
|
+
|
|
142
|
+
- tsyringe's release README documents `predicateAwareClassFactory` for conditional construction
|
|
143
|
+
and `delay()` for a proxy that constructs an instance on first use. Its circular-dependency
|
|
144
|
+
example reports an undefined constructor; that is narrower than a general graph cycle detector.
|
|
145
|
+
- InversifyJS has a dedicated [snapshot API](https://inversify.io/docs/fundamentals/snapshot/).
|
|
146
|
+
Its activation/deactivation hooks are the extension mechanism shown here; the table does not
|
|
147
|
+
claim that the old `applyMiddleware` API exists in version 8. A deferred service identifier
|
|
148
|
+
delays reading a token, which is different from a proxy that delays constructing its service.
|
|
149
|
+
- Effect 3's [layer memoization guide](https://effect.website/docs/v3/requirements-management/layer-memoization)
|
|
150
|
+
documents both shared layer construction and `Layer.fresh`. These are not container
|
|
151
|
+
Singleton/Transient registration flags. Typed requirements are not a claim of a general
|
|
152
|
+
runtime cycle detector.
|
|
153
|
+
- Nest's `forwardRef` and TypeDI's deferred type references address reference timing. Neither
|
|
154
|
+
should be marked as equivalent to Katagami's lazy service proxy. A runtime cycle guard also
|
|
155
|
+
does not establish detection of every asynchronous deadlock.
|
|
156
|
+
|
|
133
157
|
Start with the [runnable starter](../examples/request-scope/README.md) and
|
|
134
158
|
[composition guide](./guide.md#composition-and-test-substitution). For a project already built on
|
|
135
159
|
NestJS or Effect, adopting its existing DI model can be simpler than maintaining a second container.
|
|
@@ -137,6 +161,8 @@ NestJS or Effect, adopting its existing DI model can be simpler than maintaining
|
|
|
137
161
|
## Updating the comparison
|
|
138
162
|
|
|
139
163
|
Preserve a comparison and Katagami's supported advantages in the README when editing positioning.
|
|
164
|
+
Keep the feature-by-library layout, status icons and all existing comparison aspects when refreshing
|
|
165
|
+
it; add detail rather than replacing the matrix with a smaller library-by-library summary.
|
|
140
166
|
Refresh the date, npm dist-tag versions and official sources together. Check published declarations
|
|
141
167
|
when a claim involves inference or registration guarantees, and distinguish built-in features from
|
|
142
168
|
wrappers, configuration and framework behavior. Keep localized summaries aligned with the English
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "katagami",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
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",
|