katagami 2.3.0 → 3.0.1

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.
Files changed (50) hide show
  1. package/README.md +82 -592
  2. package/dist/chunk-J2NYR3SH.js +6 -0
  3. package/dist/container/index.d.cts +108 -0
  4. package/dist/container/index.d.ts +5 -82
  5. package/dist/disposable/index.cjs +16 -25
  6. package/dist/disposable/index.d.cts +69 -0
  7. package/dist/disposable/index.d.ts +16 -8
  8. package/dist/disposable/index.js +1 -1
  9. package/dist/error/index.d.cts +11 -0
  10. package/dist/index.cjs +181 -86
  11. package/dist/index.d.cts +6 -0
  12. package/dist/index.d.ts +6 -6
  13. package/dist/index.js +177 -45
  14. package/dist/internal.d.cts +29 -0
  15. package/dist/internal.d.ts +3 -1
  16. package/dist/lazy/index.cjs +16 -25
  17. package/dist/lazy/index.d.cts +33 -0
  18. package/dist/lazy/index.d.ts +7 -9
  19. package/dist/lazy/index.js +1 -1
  20. package/dist/resolver/index.d.cts +93 -0
  21. package/dist/scope/index.d.cts +120 -0
  22. package/dist/scope/index.d.ts +4 -4
  23. package/docs/README.de.md +65 -0
  24. package/docs/README.es.md +65 -0
  25. package/docs/README.fr.md +65 -0
  26. package/docs/README.ja.md +66 -0
  27. package/docs/README.ko.md +65 -0
  28. package/docs/README.zh-CN.md +65 -0
  29. package/docs/README.zh-TW.md +65 -0
  30. package/docs/ai-coding-agents.md +78 -0
  31. package/docs/articles/ai-coding-agents.ja.md +83 -0
  32. package/docs/articles/ai-coding-agents.md +70 -0
  33. package/docs/articles/request-scope.md +48 -0
  34. package/docs/articles/without-decorators.md +54 -0
  35. package/docs/choosing-di.md +30 -0
  36. package/docs/growth/baseline-2026-09-11.json +68 -0
  37. package/docs/growth/github-metadata.json +13 -0
  38. package/docs/growth/rollout.md +77 -0
  39. package/docs/guide.md +186 -0
  40. package/docs/type-safety.md +126 -0
  41. package/examples/request-scope/README.md +37 -0
  42. package/examples/request-scope/app.ts +31 -0
  43. package/examples/request-scope/demo.ts +10 -0
  44. package/examples/request-scope/tsconfig.json +11 -0
  45. package/llms.txt +16 -0
  46. package/package.json +56 -28
  47. package/dist/index-g50fxds1.js +0 -34
  48. package/dist/index-jx8b52m0.js +0 -4
  49. package/dist/scope/index.cjs +0 -212
  50. package/dist/scope/index.js +0 -153
@@ -0,0 +1,66 @@
1
+ [English](../README.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [繁體中文](./README.zh-TW.md) | [简体中文](./README.zh-CN.md) | [Español](./README.es.md) | [Deutsch](./README.de.md) | [Français](./README.fr.md)
2
+
3
+ # Katagami
4
+
5
+ **TypeScriptの型安全な依存性注入(DI)コンテナ。**
6
+
7
+ AIエージェントが書くコードでも、依存関係の配線を明示し、型で検証できます。Katagamiは登録するたびに型が自動的に積み上がり、ファクトリから参照できる依存と非同期の戻り値を追跡します。デコレータ・reflect-metadata・ランタイム依存パッケージは不要です。
8
+
9
+ [![npm version](https://img.shields.io/npm/v/katagami)](https://www.npmjs.com/package/katagami)
10
+
11
+ ```sh
12
+ npm install katagami
13
+ ```
14
+
15
+ ## クイックスタート
16
+
17
+ ```ts
18
+ import { createContainer, createScope } from 'katagami';
19
+
20
+ const container = createContainer()
21
+ .registerSingleton('name', () => 'Ada')
22
+ .registerScoped('greeting', r => `Hello, ${r.resolve('name')}!`);
23
+
24
+ const greeting: string = createScope(container).resolve('greeting');
25
+ console.log(greeting);
26
+ ```
27
+
28
+ ## AIエージェントによるコーディングで役立つ理由
29
+
30
+ エージェントが依存関係を変更し、TypeScriptの型チェックを実行し、診断をもとに修正する。この手順に、登録漏れやライフタイムの誤用を検出する具体的なチェックを組み込めます。依存関係は通常のTypeScriptのファクトリとして記述します。
31
+
32
+ 例えば、リクエスト固有の状態をSingletonのファクトリから解決しようとすると、型エラーになります。
33
+
34
+ ```ts
35
+ import { createContainer } from 'katagami';
36
+
37
+ createContainer()
38
+ .registerScoped('request', () => ({ id: crypto.randomUUID() }))
39
+ // @ts-expect-error — singleton factories cannot access scoped tokens
40
+ .registerSingleton('handler', r => r.resolve('request'));
41
+ ```
42
+
43
+ この例では、handlerもregisterScopedで登録すると解決できます。@ts-expect-errorは失敗例をCIで検証するための注記です。実際のアプリではエラーを抑制せず、ライフタイムを修正してnpx tsc --noEmitを実行します。
44
+
45
+ ## 型の蓄積方式と保証範囲
46
+
47
+ デフォルトのcreateContainer()では、登録から型が積み上がります。リテラルキーやunique symbolの型を保てば、見えている登録集合に含まれないトークンは型エラーになります。事前にサービスの型マップを書く必要はありません。
48
+
49
+ クラストークンにはTypeScriptの構造的型付けが適用されるため、同じ構造の別クラスを区別できない場合があります。また、createContainer<Services>()で事前宣言したキーは、未登録でも型として見えるようになります。この2つは蓄積方式の通常の登録チェックとは分けて説明しています。
50
+
51
+ Singleton・Transient・Scoped、use()によるモジュール合成、非同期ファクトリ、複数・オプショナル解決、リソース破棄、遅延解決をサポートします。依存が少ない場合は、通常の引数やコンストラクタによる受け渡しでも十分です。
52
+
53
+ ## ガイドと実行可能な例
54
+
55
+ - [AIコーディングガイド(英語)](./ai-coding-agents.md)
56
+ - [型の保証範囲(英語)](./type-safety.md)
57
+ - [API・利用ガイド(英語)](./guide.md)
58
+ - [リクエストスコープのスターター(英語)](../examples/request-scope/README.md)
59
+ - [DIの選び方(英語)](./choosing-di.md)
60
+ - [AIと型に関する日本語記事](./articles/ai-coding-agents.ja.md)
61
+
62
+ サンプルの型チェックと実行テストはCIで検証します。AIの修正成功率やトークン削減効果は未測定であり、性能向上の数値は主張していません。
63
+
64
+ 名前の由来は、伝統的な染色で模様を写す「型紙」です。型紙を重ねるように、登録ごとに型が積み上がります。
65
+
66
+ MIT
@@ -0,0 +1,65 @@
1
+ [English](../README.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [繁體中文](./README.zh-TW.md) | [简体中文](./README.zh-CN.md) | [Español](./README.es.md) | [Deutsch](./README.de.md) | [Français](./README.fr.md)
2
+
3
+ # Katagami
4
+
5
+ **TypeScript를 위한 타입 안전한 의존성 주입(DI) 컨테이너.**
6
+
7
+ AI 코딩 에이전트가 작성한 코드에서도 의존 관계를 명시하고 타입으로 검사하세요. Katagami는 등록할 때마다 타입을 누적하고, 팩터리에서 접근 가능한 토큰과 비동기 반환값을 추적합니다. 데코레이터, reflect-metadata, 런타임 의존 패키지가 필요하지 않습니다.
8
+
9
+ [![npm version](https://img.shields.io/npm/v/katagami)](https://www.npmjs.com/package/katagami)
10
+
11
+ ```sh
12
+ npm install katagami
13
+ ```
14
+
15
+ ## 빠른 시작
16
+
17
+ ```ts
18
+ import { createContainer, createScope } from 'katagami';
19
+
20
+ const container = createContainer()
21
+ .registerSingleton('name', () => 'Ada')
22
+ .registerScoped('greeting', r => `Hello, ${r.resolve('name')}!`);
23
+
24
+ const greeting: string = createScope(container).resolve('greeting');
25
+ console.log(greeting);
26
+ ```
27
+
28
+ ## AI 코딩 에이전트와 함께 사용하기
29
+
30
+ 에이전트가 의존 관계를 수정하고 TypeScript 검사기를 실행한 뒤 진단에 따라 수정하는 흐름을 만듭니다. 팩터리에 의존 관계가 일반 TypeScript 코드로 드러납니다.
31
+
32
+ 예를 들어 Singleton 팩터리에서 요청별 Scoped 상태를 참조하면 타입 오류가 발생합니다.
33
+
34
+ ```ts
35
+ import { createContainer } from 'katagami';
36
+
37
+ createContainer()
38
+ .registerScoped('request', () => ({ id: crypto.randomUUID() }))
39
+ // @ts-expect-error — singleton factories cannot access scoped tokens
40
+ .registerSingleton('handler', r => r.resolve('request'));
41
+ ```
42
+
43
+ handler를 registerScoped로 등록하면 이 오류를 해결할 수 있습니다. @ts-expect-error는 실패 예제를 검증하기 위한 것입니다. 앱에서는 오류를 억제하지 말고 수명을 수정한 뒤 npx tsc --noEmit을 실행하세요.
44
+
45
+ ## 누적 타입과 보장 범위
46
+
47
+ 기본 createContainer()는 등록에서 타입을 누적합니다. 리터럴 키와 unique symbol 타입을 유지하면, 현재 보이는 등록 집합에 없는 토큰은 거부됩니다. 별도의 서비스 타입 맵은 필요하지 않습니다.
48
+
49
+ 클래스 토큰은 구조적 타이핑을 따르므로 구조가 같은 다른 클래스가 허용될 수 있습니다. createContainer<Services>()에 미리 선언한 키 역시 실제 등록이 없어도 타입에 나타납니다.
50
+
51
+ Singleton, Transient, Scoped 수명, use() 모듈 합성, 비동기 팩터리, 선택적·다중 해석, 리소스 정리 및 지연 해석을 지원합니다. 의존성이 적다면 일반 함수나 생성자 매개변수로 충분할 수 있습니다.
52
+
53
+ ## 가이드와 실행 가능한 예제
54
+
55
+ - [AI 코딩 가이드 (영어)](./ai-coding-agents.md)
56
+ - [타입 보장 범위 (영어)](./type-safety.md)
57
+ - [API와 사용 가이드 (영어)](./guide.md)
58
+ - [요청 스코프 스타터 (영어)](../examples/request-scope/README.md)
59
+ - [DI 선택 가이드 (영어)](./choosing-di.md)
60
+
61
+ 타입 예제와 실행 테스트는 CI에서 검사합니다. AI 수정 성공률이나 토큰 절감 효과는 아직 측정하지 않았습니다.
62
+
63
+ 이름은 일본 전통 염색의 형지인 型紙에서 왔습니다. 형지를 겹치듯 등록마다 타입이 누적됩니다.
64
+
65
+ MIT
@@ -0,0 +1,65 @@
1
+ [English](../README.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [繁體中文](./README.zh-TW.md) | [简体中文](./README.zh-CN.md) | [Español](./README.es.md) | [Deutsch](./README.de.md) | [Français](./README.fr.md)
2
+
3
+ # Katagami
4
+
5
+ **适用于 TypeScript 的类型安全依赖注入(DI)容器。**
6
+
7
+ 即使代码由 AI 编程智能体编写,也能显式描述依赖关系并进行类型检查。Katagami 随注册逐步累积类型,检查工厂可访问的依赖,并追踪异步返回值。无需装饰器、reflect-metadata 或运行时依赖包。
8
+
9
+ [![npm version](https://img.shields.io/npm/v/katagami)](https://www.npmjs.com/package/katagami)
10
+
11
+ ```sh
12
+ npm install katagami
13
+ ```
14
+
15
+ ## 快速开始
16
+
17
+ ```ts
18
+ import { createContainer, createScope } from 'katagami';
19
+
20
+ const container = createContainer()
21
+ .registerSingleton('name', () => 'Ada')
22
+ .registerScoped('greeting', r => `Hello, ${r.resolve('name')}!`);
23
+
24
+ const greeting: string = createScope(container).resolve('greeting');
25
+ console.log(greeting);
26
+ ```
27
+
28
+ ## 配合 AI 编程智能体使用
29
+
30
+ 让智能体修改依赖关系,运行 TypeScript 检查,再根据诊断修复。显式工厂让依赖关系直接体现在普通 TypeScript 代码中。
31
+
32
+ 例如,Singleton 工厂访问请求级 Scoped 状态时,会出现类型错误。
33
+
34
+ ```ts
35
+ import { createContainer } from 'katagami';
36
+
37
+ createContainer()
38
+ .registerScoped('request', () => ({ id: crypto.randomUUID() }))
39
+ // @ts-expect-error — singleton factories cannot access scoped tokens
40
+ .registerSingleton('handler', r => r.resolve('request'));
41
+ ```
42
+
43
+ 将 handler 改为 registerScoped 即可修正此例。@ts-expect-error 用于在 CI 中验证失败示例。在应用中应修正生命周期,而非抑制错误,然后运行 npx tsc --noEmit。
44
+
45
+ ## 类型累积与保证范围
46
+
47
+ 默认的 createContainer() 从注册中累积类型。保留字面量键或 unique symbol 类型时,当前可见注册集合之外的令牌会被拒绝,无需手写服务类型映射。
48
+
49
+ 类令牌遵循结构类型规则,因此可能接受结构相同的另一个类。通过 createContainer<Services>() 预先声明的键,即使没有实际注册,也会出现在类型中。
50
+
51
+ 支持 Singleton、Transient、Scoped 生命周期、use() 模块组合、异步工厂、可选及多重解析、资源清理和延迟解析。依赖较少时,普通函数或构造函数参数可能已经足够。
52
+
53
+ ## 指南与可运行示例
54
+
55
+ - [AI 编程指南(英语)](./ai-coding-agents.md)
56
+ - [类型保证范围(英语)](./type-safety.md)
57
+ - [API 与使用指南(英语)](./guide.md)
58
+ - [请求作用域入门示例(英语)](../examples/request-scope/README.md)
59
+ - [DI 选型指南(英语)](./choosing-di.md)
60
+
61
+ 类型示例及运行测试由 CI 验证。尚未测量 AI 修复成功率或令牌节省效果。
62
+
63
+ 名称来自日本传统染色中使用的“型纸”。如同叠加型纸,类型也随注册逐步累积。
64
+
65
+ MIT
@@ -0,0 +1,65 @@
1
+ [English](../README.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [繁體中文](./README.zh-TW.md) | [简体中文](./README.zh-CN.md) | [Español](./README.es.md) | [Deutsch](./README.de.md) | [Français](./README.fr.md)
2
+
3
+ # Katagami
4
+
5
+ **適用於 TypeScript 的型別安全依賴注入(DI)容器。**
6
+
7
+ 即使程式碼由 AI 程式設計代理撰寫,也能明確描述依賴關係並進行型別檢查。Katagami 隨註冊逐步累積型別,檢查工廠可存取的依賴,並追蹤非同步回傳值。不需要裝飾器、reflect-metadata 或執行階段依賴套件。
8
+
9
+ [![npm version](https://img.shields.io/npm/v/katagami)](https://www.npmjs.com/package/katagami)
10
+
11
+ ```sh
12
+ npm install katagami
13
+ ```
14
+
15
+ ## 快速開始
16
+
17
+ ```ts
18
+ import { createContainer, createScope } from 'katagami';
19
+
20
+ const container = createContainer()
21
+ .registerSingleton('name', () => 'Ada')
22
+ .registerScoped('greeting', r => `Hello, ${r.resolve('name')}!`);
23
+
24
+ const greeting: string = createScope(container).resolve('greeting');
25
+ console.log(greeting);
26
+ ```
27
+
28
+ ## 與 AI 程式設計代理搭配使用
29
+
30
+ 讓代理修改依賴關係,執行 TypeScript 檢查,再根據診斷修正。明確的工廠讓依賴關係直接呈現在一般 TypeScript 程式碼中。
31
+
32
+ 例如,Singleton 工廠存取請求層級的 Scoped 狀態時,會出現型別錯誤。
33
+
34
+ ```ts
35
+ import { createContainer } from 'katagami';
36
+
37
+ createContainer()
38
+ .registerScoped('request', () => ({ id: crypto.randomUUID() }))
39
+ // @ts-expect-error — singleton factories cannot access scoped tokens
40
+ .registerSingleton('handler', r => r.resolve('request'));
41
+ ```
42
+
43
+ 將 handler 改為 registerScoped 即可修正此例。@ts-expect-error 用於在 CI 中驗證失敗範例。在應用程式中應修正生命週期,而非抑制錯誤,再執行 npx tsc --noEmit。
44
+
45
+ ## 型別累積與保證範圍
46
+
47
+ 預設的 createContainer() 從註冊中累積型別。保留字面值鍵或 unique symbol 型別時,目前可見註冊集合以外的權杖會被拒絕,不需要手寫服務型別映射。
48
+
49
+ 類別權杖遵循結構型別規則,因此可能接受結構相同的另一個類別。透過 createContainer<Services>() 預先宣告的鍵,即使沒有實際註冊,也會出現在型別中。
50
+
51
+ 支援 Singleton、Transient、Scoped 生命週期、use() 模組組合、非同步工廠、可選及多重解析、資源清理與延遲解析。依賴較少時,一般函式或建構子參數可能已經足夠。
52
+
53
+ ## 指南與可執行範例
54
+
55
+ - [AI 程式設計指南(英文)](./ai-coding-agents.md)
56
+ - [型別保證範圍(英文)](./type-safety.md)
57
+ - [API 與使用指南(英文)](./guide.md)
58
+ - [請求範圍入門範例(英文)](../examples/request-scope/README.md)
59
+ - [DI 選型指南(英文)](./choosing-di.md)
60
+
61
+ 型別範例與執行測試由 CI 驗證。尚未測量 AI 修正成功率或 token 節省效果。
62
+
63
+ 名稱來自日本傳統染色使用的「型紙」。如同疊加型紙,型別也隨註冊逐步累積。
64
+
65
+ MIT
@@ -0,0 +1,78 @@
1
+ # TypeScript dependency injection with AI coding agents
2
+
3
+ Use Katagami's accumulated registration types as feedback while an agent edits dependency wiring.
4
+ This guide describes the v3 API. Check the installed package version before editing an existing app.
5
+
6
+ ## A repeatable workflow
7
+
8
+ 1. Read the composition root, nearby service constructors and tests.
9
+ 2. Define dependencies explicitly in factories. Start with `createContainer()` and preserve inferred types.
10
+ 3. Register a dependency before the factory that uses it. Resolve services through `createScope(container)`.
11
+ 4. Choose a lifetime: singleton for shared infrastructure, scoped for request state, transient for a new instance per resolution.
12
+ 5. Run the application's `npx tsc --noEmit`, then its existing tests.
13
+ 6. Correct registration, lifetime or asynchronous usage based on diagnostics. Repeat until both checks pass.
14
+
15
+ When changing Katagami itself, use `bun run verify` instead; it includes type tests,
16
+ runtime tests, examples, the packed package and documentation checks.
17
+
18
+ ## Minimal working example
19
+
20
+ ```ts
21
+ import { createContainer, createScope } from 'katagami';
22
+
23
+ const container = createContainer()
24
+ .registerSingleton('users', async () => ({ findName: (id: string) => `user-${id}` }))
25
+ .registerScoped('handler', async r => {
26
+ const users = await r.resolve('users');
27
+ return (id: string) => users.findName(id);
28
+ });
29
+
30
+ const scope = createScope(container);
31
+ const handler = await scope.resolve('handler');
32
+ handler('42');
33
+ ```
34
+
35
+ Use the [request-scope starter](../examples/request-scope/README.md) for cleanup,
36
+ concurrent calls and replacement of infrastructure with a fake.
37
+
38
+ ## Diagnose the error before changing code
39
+
40
+ | Diagnostic or symptom | Check | Typical correction |
41
+ | --- | --- | --- |
42
+ | `No overload matches this call` at `resolve`, often mentioning `never` | Is this exact token registered and visible here? | Register it earlier, correct its spelling, or compose the module first |
43
+ | The same error inside a singleton/transient factory after a scoped registration | Does the factory capture request state? | Make the consumer scoped, or pass request data into a method without storing it |
44
+ | A service method does not exist on `Promise<...>` | Is the dependency factory async? | Await the resolution; make the consuming factory async if needed |
45
+ | `resolve` does not exist on `Container` | v3 separates registration from resolution | Call `createScope(container).resolve(token)` |
46
+ | `lazy` rejects a token | Is it an async or PropertyKey token? | Use direct resolution; `lazy` accepts synchronous class tokens |
47
+ | Runtime `Token ... is not registered` despite a passing type check | Predeclared map, compatible class, widened key or assertion? | Register the actual token and review the type-safety guide |
48
+
49
+ The wording of compiler diagnostics varies with TypeScript versions. Check the failing
50
+ expression and the resolver's visible registrations; do not match an error string blindly.
51
+
52
+ ## Project instruction you can copy
53
+
54
+ ```text
55
+ Use the installed Katagami v3 API for dependency wiring. Read
56
+ node_modules/katagami/docs/ai-coding-agents.md and
57
+ node_modules/katagami/docs/type-safety.md first.
58
+ Preserve inferred registration chains and narrow literal/unique-symbol tokens.
59
+ Resolve through createScope. Keep request state scoped and await async dependencies.
60
+ Use explicit factories and inject fakes in tests.
61
+ Fix type errors at their cause; do not silence them with any, assertions,
62
+ @ts-ignore, @ts-expect-error or optional resolution for required dependencies.
63
+ Run this application's type checker and tests after changes.
64
+ ```
65
+
66
+ Add this instruction to the project instructions your agent already reads, or pass it explicitly
67
+ with the task. Installing a dependency does not ensure that an agent reads its documentation.
68
+
69
+ ## Guarantees and evidence
70
+
71
+ Accumulated literal keys and unique symbols provide a finite set of registered tokens.
72
+ Class tokens follow structural compatibility; predeclared service maps can name missing factories.
73
+ See [the complete guarantee and boundary examples](./type-safety.md).
74
+
75
+ The compiler checks and example tests are automated in CI. Agent repair success and token savings
76
+ are hypotheses, not measured product claims. Use the
77
+ [controlled evaluation protocol](https://github.com/hiroiku/katagami/tree/master/benchmarks/agent-wiring)
78
+ before making quantitative comparisons.
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: "AIエージェントが書く依存関係を、TypeScriptの型で検証する"
3
+ emoji: "🧩"
4
+ type: "tech"
5
+ topics: ["typescript", "ai", "di"]
6
+ published: false
7
+ ---
8
+
9
+ # AIエージェントが書く依存関係を、TypeScriptの型で検証する
10
+
11
+ AIとコードを書くときも、変更の正しさを確認する手段が必要です。依存関係の配線なら、
12
+ コードを変更し、TypeScriptを実行し、診断に沿って修正する流れを作れます。
13
+ 私が開発しているDIコンテナのKatagamiは、依存を登録するたびに型を積み上げ、
14
+ ファクトリから参照できる依存を型として表現します。
15
+
16
+ ## 登録から型を積み上げる
17
+
18
+ ```ts
19
+ import { createContainer, createScope } from 'katagami';
20
+
21
+ const container = createContainer()
22
+ .registerSingleton('users', () => ({ find: (id: string) => `user-${id}` }))
23
+ .registerScoped('handler', r => (id: string) => r.resolve('users').find(id));
24
+
25
+ createScope(container).resolve('handler')('42');
26
+ ```
27
+
28
+ この例にサービス一覧のインターフェースはありません。usersを登録すると、次のファクトリで
29
+ usersを参照できる型になります。r.resolve('user')と書き間違えたり、usersの登録を削除したり
30
+ すると、依存を使う側で型エラーが出ます。起動せずに確認できる検査です。
31
+
32
+ ## ライフタイムの誤りを検出する
33
+
34
+ リクエスト固有の状態を、すべてのリクエストで共有するSingletonが保持すると問題になります。
35
+
36
+ ```ts
37
+ import { createContainer } from 'katagami';
38
+
39
+ createContainer()
40
+ .registerScoped('requestId', () => crypto.randomUUID())
41
+ // @ts-expect-error — SingletonのファクトリにはScopedのトークンが見えない
42
+ .registerSingleton('handler', r => r.resolve('requestId'));
43
+ ```
44
+
45
+ この場合、r.resolve('requestId')でNo overload matches this callという診断が出ます。
46
+ handlerがリクエストの状態を保持するなら、registerScopedに変えるのが修正です。
47
+ 状態を保持する必要がなければ、共有サービスのメソッドへrequestIdを引数で渡す設計もできます。
48
+
49
+ @ts-expect-errorは、この記事の失敗例をCIで検証するための注記です。
50
+ 実際のアプリでは注記でエラーを隠さず、依存関係やライフタイムを直します。
51
+
52
+ ## エージェントに渡すもの
53
+
54
+ 現行APIの説明、アプリの依存登録箇所、型チェックとテストのコマンドを渡します。
55
+ エージェントには推論された型を保ち、渡されたファクトリのリゾルバを使ってもらいます。
56
+ 変更後にnpx tsc --noEmitとアプリのテストを実行し、問題があれば修正します。
57
+
58
+ [実行可能なスターター](https://github.com/hiroiku/katagami/tree/master/examples/request-scope)には、
59
+ リクエストごとの状態、テスト用のリポジトリ差し替え、成功・失敗時のリソース破棄を含めました。
60
+ AI向けの利用ガイドもnpmパッケージに同梱します。
61
+
62
+ ## 型で保証できる範囲を分ける
63
+
64
+ デフォルトの蓄積方式では、リテラルキーやunique symbolの型を保つことで、見えている登録集合に
65
+ 含まれないトークンを拒否できます。一方、createContainer<Services>()で事前宣言する方式は、
66
+ 後から登録する依存を参照できる代わりに、全キーの実際の登録までは証明しません。
67
+
68
+ クラストークンには構造的型付けも関係します。同じ構造の別クラスは型として互換でも、
69
+ 実行時には別のトークンです。この区別が必要なら、unique symbolやリテラルキー、
70
+ 個別のprivateメンバーで区別したクラスを使います。
71
+ [保証と例外](https://github.com/hiroiku/katagami/blob/master/docs/type-safety.md)をコード付きで整理しています。
72
+
73
+ 型チェックの例と実行テストは自動検証しています。ただし、AIの修正成功率やトークン消費の改善は
74
+ まだ測定していません。同じ課題・モデル・条件で失敗も含めて記録する評価手順を用意しています。
75
+
76
+ 依存が少なければ、普通の関数やコンストラクタの引数でも十分です。
77
+ 依存の構築・共有・リクエスト単位の管理が増えた場面で、選択肢として試してもらえればと思います。
78
+
79
+ ```sh
80
+ npm install katagami
81
+ ```
82
+
83
+ [KatagamiのREADME](https://github.com/hiroiku/katagami)から、基本例と利用ガイドを読めます。
@@ -0,0 +1,70 @@
1
+ # Type-safe dependency injection for AI coding agents
2
+
3
+ AI-assisted development still needs a way to check the code it produces. For dependency wiring,
4
+ a useful loop is small: edit the composition root, run TypeScript, read the diagnostics, and repair
5
+ the missing dependency or incorrect lifetime. Katagami makes some of those wiring constraints visible
6
+ to the compiler by accumulating types as dependencies are registered.
7
+
8
+ ## Let registration define the available dependencies
9
+
10
+ ```ts
11
+ import { createContainer, createScope } from 'katagami';
12
+
13
+ const container = createContainer()
14
+ .registerSingleton('users', () => ({ find: (id: string) => `user-${id}` }))
15
+ .registerScoped('handler', r => (id: string) => r.resolve('users').find(id));
16
+
17
+ createScope(container).resolve('handler')('42');
18
+ ```
19
+
20
+ There is no manually maintained service interface in this example. The first registration adds
21
+ `users` to the type known by the next factory. The second adds `handler` to the scope's visible set.
22
+ Changing `r.resolve('users')` to `r.resolve('user')` produces a type error. Removing the first
23
+ registration also produces a type error at the consumer.
24
+
25
+ The check is useful for both people and coding agents: the factory's actual dependency is written
26
+ in the same code that TypeScript checks. The compiler can report a problem without starting the app.
27
+
28
+ ## Turn a diagnostic into a repair
29
+
30
+ ```ts
31
+ import { createContainer } from 'katagami';
32
+
33
+ createContainer()
34
+ .registerScoped('requestId', () => crypto.randomUUID())
35
+ // @ts-expect-error — a singleton factory cannot access this scoped dependency
36
+ .registerSingleton('handler', r => r.resolve('requestId'));
37
+ ```
38
+
39
+ The diagnostic includes `No overload matches this call`. Inspect the failing resolution and its
40
+ lifetime: the factory requests state belonging to one request while asking to be shared as a singleton.
41
+ Register the handler as scoped, or pass the request ID into a shared service's method without storing it.
42
+
43
+ `@ts-expect-error` is only present to test this intentionally invalid example. It is not the repair.
44
+ In application code, change the wiring, run `npx tsc --noEmit`, then run behavior tests.
45
+
46
+ ## Make the workflow usable
47
+
48
+ Give the agent the [v3 usage guide](../ai-coding-agents.md), the application's composition root and
49
+ its verification command. Have it use the supplied factory resolver, preserve inferred registration
50
+ types and run the checker after changes. A [runnable request-scope starter](../../examples/request-scope/README.md)
51
+ shows fake injection, concurrent calls and cleanup on both success and failure.
52
+
53
+ Ordinary constructor or function injection is still a useful baseline. It also gets TypeScript's
54
+ parameter checks and can be enough for small applications. Introduce a container when construction,
55
+ sharing, request scope or module composition is otherwise becoming repetitive.
56
+
57
+ ## State the guarantee accurately
58
+
59
+ Accumulated literal keys and unique symbols let the checker reject tokens outside the visible
60
+ registered set. A predeclared `createContainer<Services>()` map instead permits forward references
61
+ and does not establish runtime registration completeness. Class tokens follow TypeScript's
62
+ structural typing, so another compatible class may pass the checker while being a different runtime key.
63
+ See [working examples of these boundaries](../type-safety.md).
64
+
65
+ The compiler cases in this article are tested. We have not measured agent repair success or token
66
+ savings. Those need [controlled repeated trials](https://github.com/hiroiku/katagami/tree/master/benchmarks/agent-wiring),
67
+ including failures and the same tasks, model settings and runtime tests across variants.
68
+
69
+ Install with `npm install katagami`, then start with the
70
+ [quick start](../../README.md#quick-start) or the [request-scope example](../../examples/request-scope/README.md).
@@ -0,0 +1,48 @@
1
+ # Catch request-scope mistakes at compile time in TypeScript
2
+
3
+ A service shared by all requests should not retain state from just one request. A DI container
4
+ can make that mistake easier to express if every factory can resolve every dependency. Katagami's
5
+ typed singleton and transient factories receive a resolver that excludes scoped registrations.
6
+
7
+ ## Reproduce the problem
8
+
9
+ ```ts
10
+ import { createContainer } from 'katagami';
11
+
12
+ createContainer()
13
+ .registerScoped('request', () => ({ id: crypto.randomUUID() }))
14
+ // @ts-expect-error — the request belongs to one scope, not a shared singleton
15
+ .registerSingleton('handler', r => ({ requestId: r.resolve('request').id }));
16
+ ```
17
+
18
+ The checker rejects the resolution of `request`. The fix depends on what the handler should do.
19
+ If it holds request state, give it a scoped lifetime:
20
+
21
+ ```ts
22
+ import { createContainer, createScope } from 'katagami';
23
+
24
+ const container = createContainer()
25
+ .registerScoped('request', () => ({ id: crypto.randomUUID() }))
26
+ .registerScoped('handler', r => ({ requestId: r.resolve('request').id }));
27
+
28
+ const first = createScope(container);
29
+ const second = createScope(container);
30
+ first.resolve('handler').requestId !== second.resolve('handler').requestId; // true
31
+ ```
32
+
33
+ If the service can be stateless and shared, take request data as a method parameter instead.
34
+ Do not close over another request scope to get around the factory resolver.
35
+
36
+ ## Test what types cannot establish
37
+
38
+ Type-check the wiring, then check that concurrent requests have distinct IDs, shared infrastructure
39
+ stays shared, and resources are cleaned on rejection as well as success. The
40
+ [request-scope starter](../../examples/request-scope/README.md) and its tests cover these cases.
41
+
42
+ The compile-time example uses accumulated literal keys. A broad type annotation, predeclared map,
43
+ compatible class token, assertion or captured external resolver can change what is checked.
44
+ The runtime captive-dependency guard also has limits around work resumed after an `await`.
45
+ The [type-safety guide](../type-safety.md) explains the exact scope of the guarantee.
46
+
47
+ Katagami provides Singleton, Transient and Scoped lifetimes without decorator metadata.
48
+ The [API guide](../guide.md) shows composition, async factories and optional disposal.
@@ -0,0 +1,54 @@
1
+ # TypeScript dependency injection without decorators
2
+
3
+ Dependency injection can be ordinary TypeScript: a factory receives a resolver and explicitly
4
+ constructs a service. Katagami uses this model and has no runtime package dependencies, decorator
5
+ compiler flags or reflect-metadata requirement.
6
+
7
+ ```sh
8
+ npm install katagami
9
+ ```
10
+
11
+ ## Start with a factory
12
+
13
+ ```ts
14
+ import { createContainer, createScope } from 'katagami';
15
+
16
+ class Logger {
17
+ log(message: string) { console.log(message); }
18
+ }
19
+ class Greeting {
20
+ constructor(private logger: Logger) {}
21
+ say(name: string) { this.logger.log(`Hello, ${name}!`); }
22
+ }
23
+
24
+ const container = createContainer()
25
+ .registerSingleton(Logger, () => new Logger())
26
+ .registerTransient(Greeting, r => new Greeting(r.resolve(Logger)));
27
+
28
+ createScope(container).resolve(Greeting).say('Ada');
29
+ ```
30
+
31
+ The registration chain determines which class types the next factory can resolve. Class tokens
32
+ are convenient when the classes are structurally distinguishable. Literal keys or unique symbols
33
+ are also supported; see [token identity and type guarantees](../type-safety.md).
34
+
35
+ ## Substitute infrastructure in a test
36
+
37
+ Factories can accept infrastructure as ordinary parameters. The
38
+ [request-scope starter](../../examples/request-scope/README.md) takes a `UserRepository` argument.
39
+ Its tests pass a small fake that returns a known name, then check the greeting. No global container
40
+ or decorator setup is required.
41
+
42
+ For larger compositions, group registrations in a container and copy them with `use()`.
43
+ Apply the fake module before resolving anything. `use()` replaces matching registration entries;
44
+ it is mutable composition, not automatic file loading or a snapshot API.
45
+
46
+ ## Choose only the lifecycle features you need
47
+
48
+ Core imports come from `katagami`. Add cleanup from `katagami/disposable` or synchronous class-based
49
+ lazy resolution from `katagami/lazy` when needed. Those entry points are separate so bundlers can
50
+ omit unused implementations. Cleanup uses the host's disposal symbols; it does not provide a polyfill.
51
+
52
+ For a small application, manual constructor parameters may remain the simplest choice.
53
+ The [DI decision guide](../choosing-di.md) explains when accumulated registration types and request
54
+ scopes are useful and links to other containers' own documentation.
@@ -0,0 +1,30 @@
1
+ # Choosing a TypeScript dependency injection approach
2
+
3
+ Choose based on the application's wiring and lifecycle needs. There is no measured claim here
4
+ that Katagami is faster, safer in every scenario, or more effective for every coding agent.
5
+
6
+ | Approach | Consider it when | What to account for |
7
+ | --- | --- | --- |
8
+ | Ordinary constructor/function parameters | A small number of dependencies is easy to wire by hand | Your code owns construction, sharing and cleanup; TypeScript still checks parameter types |
9
+ | Katagami | You want explicit factories, accumulated registration types and request scopes | Preserve narrow token types; understand structural class identity and predeclared-map limits |
10
+ | Your framework's existing DI | The application already uses a framework container | Its conventions and lifecycle integrations may avoid maintaining a second container |
11
+ | Awilix | Its registration, injection and loading conventions fit your app | Read its own TypeScript and strict-mode documentation for guarantees and configuration |
12
+ | InversifyJS | Its class-oriented binding model and ecosystem fit your app | Follow its current setup instructions, including metadata requirements where applicable |
13
+
14
+ Katagami's concrete distinction is that the default registration chain accumulates a resolver's
15
+ visible token set. For literal keys or unique symbols, a missing token is rejected before execution.
16
+ That is a useful check for both human-written and AI-generated wiring. It does not establish that
17
+ other libraries lack type safety, and it does not eliminate runtime tests.
18
+
19
+ Start with the [runnable starter](../examples/request-scope/README.md),
20
+ [guarantee examples](./type-safety.md) and [composition guide](./guide.md#composition-and-test-substitution).
21
+
22
+ Primary references, reviewed 2026-09-11:
23
+
24
+ - [Awilix's maintained README](https://github.com/jeffijoe/awilix#readme), including TypeScript and strict mode.
25
+ - [InversifyJS getting started](https://inversify.io/docs/introduction/getting-started/).
26
+ - [TypeScript type compatibility](https://www.typescriptlang.org/docs/handbook/type-compatibility).
27
+
28
+ The previous broad feature matrix was replaced with this decision guide. Replacing registrations
29
+ with `use()` is explicit composition; Katagami does not implement automatic module discovery,
30
+ immutable containers or a dedicated snapshot/restore API.