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,29 @@
1
+ import type { Registration } from './resolver/index.cjs';
2
+ /**
3
+ * Symbol used by extension modules (scope, disposable) to access container/scope internals.
4
+ *
5
+ * @internal
6
+ */
7
+ export declare const INTERNALS: unique symbol;
8
+ /** Type-only registration state retained by disposable views. No runtime property is emitted. */
9
+ export declare const TYPE_STATE: unique symbol;
10
+ /**
11
+ * Internal state exposed via the INTERNALS symbol.
12
+ *
13
+ * Both Container and Scope implement this interface so that extension modules
14
+ * (scope, disposable) can operate on either without importing the concrete class.
15
+ *
16
+ * @internal
17
+ */
18
+ export interface ContainerInternals {
19
+ /** All registrations (singleton / transient / scoped). Each token maps to an array of registrations. */
20
+ readonly registrations: Map<unknown, Registration[]>;
21
+ /** Singleton cache keyed by Registration object (Container: singletons, Scope: shared with parent). */
22
+ readonly singletonCache: Map<Registration, unknown>;
23
+ /** Instances owned by this container / scope (disposal target), keyed by Registration object. */
24
+ readonly ownCache: Map<Registration, unknown>;
25
+ /** Whether this container / scope has been disposed. */
26
+ isDisposed(): boolean;
27
+ /** Mark this container / scope as disposed. */
28
+ markDisposed(): void;
29
+ }
@@ -1,10 +1,12 @@
1
- import type { Registration } from './resolver';
1
+ import type { Registration } from './resolver/index.js';
2
2
  /**
3
3
  * Symbol used by extension modules (scope, disposable) to access container/scope internals.
4
4
  *
5
5
  * @internal
6
6
  */
7
7
  export declare const INTERNALS: unique symbol;
8
+ /** Type-only registration state retained by disposable views. No runtime property is emitted. */
9
+ export declare const TYPE_STATE: unique symbol;
8
10
  /**
9
11
  * Internal state exposed via the INTERNALS symbol.
10
12
  *
@@ -1,37 +1,28 @@
1
+ "use strict";
1
2
  var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __moduleCache = /* @__PURE__ */ new WeakMap;
6
- var __toCommonJS = (from) => {
7
- var entry = __moduleCache.get(from), desc;
8
- if (entry)
9
- return entry;
10
- entry = __defProp({}, "__esModule", { value: true });
11
- if (from && typeof from === "object" || typeof from === "function")
12
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
- get: () => from[key],
14
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
- }));
16
- __moduleCache.set(from, entry);
17
- return entry;
18
- };
19
6
  var __export = (target, all) => {
20
7
  for (var name in all)
21
- __defProp(target, name, {
22
- get: all[name],
23
- enumerable: true,
24
- configurable: true,
25
- set: (newValue) => all[name] = () => newValue
26
- });
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
27
17
  };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
19
 
29
20
  // src/lazy/index.ts
30
- var exports_lazy = {};
31
- __export(exports_lazy, {
21
+ var lazy_exports = {};
22
+ __export(lazy_exports, {
32
23
  lazy: () => lazy
33
24
  });
34
- module.exports = __toCommonJS(exports_lazy);
25
+ module.exports = __toCommonJS(lazy_exports);
35
26
  function lazy(source, token) {
36
27
  let instance;
37
28
  let resolved = false;
@@ -42,7 +33,7 @@ function lazy(source, token) {
42
33
  }
43
34
  return instance;
44
35
  };
45
- const proxyTarget = Object.create(null);
36
+ const proxyTarget = /* @__PURE__ */ Object.create(null);
46
37
  return new Proxy(proxyTarget, {
47
38
  defineProperty(_, prop, desc) {
48
39
  return Reflect.defineProperty(ensureResolved(), prop, desc);
@@ -0,0 +1,33 @@
1
+ import type { DisposableScope } from '../disposable/index.cjs';
2
+ import type { AbstractConstructor } from '../resolver/index.cjs';
3
+ import type { Scope } from '../scope/index.cjs';
4
+ /**
5
+ * Create a lazy proxy that defers resolution until the first property access.
6
+ *
7
+ * The returned object looks and behaves like `V`, but the underlying instance
8
+ * is not created until a property is read, written, or otherwise accessed.
9
+ * Once resolved the instance is cached — subsequent accesses hit the cache.
10
+ *
11
+ * Only **sync class tokens** are supported. Async tokens and PropertyKey tokens
12
+ * are rejected at the type level.
13
+ *
14
+ * @param source A Scope or DisposableScope
15
+ * @param token A sync class constructor token
16
+ * @returns A proxy that transparently forwards to the lazily-resolved instance
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import { createContainer, createScope } from 'katagami';
21
+ * import { lazy } from 'katagami/lazy';
22
+ *
23
+ * const container = createContainer()
24
+ * .registerSingleton(HeavyService, () => new HeavyService());
25
+ *
26
+ * const scope = createScope(container);
27
+ * const service = lazy(scope, HeavyService);
28
+ * // Instance is NOT created yet
29
+ * service.doSomething(); // resolved here, then cached
30
+ * ```
31
+ */
32
+ export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & (Sync | ScopedSync)): V;
33
+ export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & (Sync | ScopedSync)): V;
@@ -1,7 +1,6 @@
1
- import type { Container } from '../container';
2
- import type { DisposableContainer, DisposableScope } from '../disposable';
3
- import type { AbstractConstructor } from '../resolver';
4
- import type { Scope } from '../scope';
1
+ import type { DisposableScope } from '../disposable/index.js';
2
+ import type { AbstractConstructor } from '../resolver/index.js';
3
+ import type { Scope } from '../scope/index.js';
5
4
  /**
6
5
  * Create a lazy proxy that defers resolution until the first property access.
7
6
  *
@@ -12,24 +11,23 @@ import type { Scope } from '../scope';
12
11
  * Only **sync class tokens** are supported. Async tokens and PropertyKey tokens
13
12
  * are rejected at the type level.
14
13
  *
15
- * @param source A Container, Scope, DisposableContainer, or DisposableScope
14
+ * @param source A Scope or DisposableScope
16
15
  * @param token A sync class constructor token
17
16
  * @returns A proxy that transparently forwards to the lazily-resolved instance
18
17
  *
19
18
  * @example
20
19
  * ```ts
21
- * import { createContainer } from 'katagami';
20
+ * import { createContainer, createScope } from 'katagami';
22
21
  * import { lazy } from 'katagami/lazy';
23
22
  *
24
23
  * const container = createContainer()
25
24
  * .registerSingleton(HeavyService, () => new HeavyService());
26
25
  *
27
- * const service = lazy(container, HeavyService);
26
+ * const scope = createScope(container);
27
+ * const service = lazy(scope, HeavyService);
28
28
  * // Instance is NOT created yet
29
29
  * service.doSomething(); // resolved here, then cached
30
30
  * ```
31
31
  */
32
- export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & Sync): V;
33
32
  export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & (Sync | ScopedSync)): V;
34
- export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: DisposableContainer<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & Sync): V;
35
33
  export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & (Sync | ScopedSync)): V;
@@ -9,7 +9,7 @@ function lazy(source, token) {
9
9
  }
10
10
  return instance;
11
11
  };
12
- const proxyTarget = Object.create(null);
12
+ const proxyTarget = /* @__PURE__ */ Object.create(null);
13
13
  return new Proxy(proxyTarget, {
14
14
  defineProperty(_, prop, desc) {
15
15
  return Reflect.defineProperty(ensureResolved(), prop, desc);
@@ -0,0 +1,93 @@
1
+ export type AbstractConstructor<T = unknown> = abstract new (...args: never[]) => T;
2
+ /**
3
+ * Resolver passed to factory callbacks.
4
+ *
5
+ * @template T PropertyKey-based type map (defined via interface, order-independent)
6
+ * @template Sync Union of registered sync class constructors (order-dependent)
7
+ * @template Async Union of registered async class constructors (order-dependent)
8
+ */
9
+ export interface Resolver<T, Sync extends AbstractConstructor = AbstractConstructor, Async extends AbstractConstructor = never> {
10
+ /**
11
+ * Resolve an instance for the given token.
12
+ *
13
+ * @param token A registered token
14
+ * @returns The instance associated with the token
15
+ */
16
+ resolve<V>(token: AbstractConstructor<V> & Async): Promise<V>;
17
+ resolve<V>(token: AbstractConstructor<V> & Sync): V;
18
+ resolve<K extends keyof T>(token: K): T[K];
19
+ /**
20
+ * Try to resolve an instance for the given token.
21
+ *
22
+ * Returns `undefined` instead of throwing when the token is not registered.
23
+ * Other errors (circular dependency, disposed container) are still thrown.
24
+ *
25
+ * @param token A token to resolve
26
+ * @returns The instance associated with the token, or `undefined` if not registered
27
+ */
28
+ tryResolve<V>(token: AbstractConstructor<V> & Async): Promise<V> | undefined;
29
+ tryResolve<V>(token: AbstractConstructor<V> & Sync): V | undefined;
30
+ tryResolve<K extends keyof T>(token: K): T[K] | undefined;
31
+ tryResolve<V>(token: AbstractConstructor<V>): V | Promise<V> | undefined;
32
+ tryResolve(token: PropertyKey): unknown;
33
+ /**
34
+ * Resolve all instances for the given token.
35
+ *
36
+ * Returns an array of instances from all registrations for the token.
37
+ *
38
+ * @param token A registered token
39
+ * @returns An array of instances associated with the token
40
+ */
41
+ resolveAll<V>(token: AbstractConstructor<V> & Async): Promise<V>[];
42
+ resolveAll<V>(token: AbstractConstructor<V> & Sync): V[];
43
+ resolveAll<K extends keyof T>(token: K): T[K][];
44
+ /**
45
+ * Try to resolve all instances for the given token.
46
+ *
47
+ * Returns `undefined` instead of throwing when the token is not registered.
48
+ * Other errors (circular dependency, disposed container) are still thrown.
49
+ *
50
+ * @param token A token to resolve
51
+ * @returns An array of instances associated with the token, or `undefined` if not registered
52
+ */
53
+ tryResolveAll<V>(token: AbstractConstructor<V> & Async): Promise<V>[] | undefined;
54
+ tryResolveAll<V>(token: AbstractConstructor<V> & Sync): V[] | undefined;
55
+ tryResolveAll<K extends keyof T>(token: K): T[K][] | undefined;
56
+ tryResolveAll<V>(token: AbstractConstructor<V>): (V | Promise<V>)[] | undefined;
57
+ tryResolveAll(token: PropertyKey): unknown;
58
+ }
59
+ /**
60
+ * Lifetime of a registration.
61
+ */
62
+ export type Lifetime = 'singleton' | 'transient' | 'scoped';
63
+ /**
64
+ * Factory registration entry.
65
+ */
66
+ export interface Registration {
67
+ /**
68
+ * Factory function.
69
+ *
70
+ * @param resolver Resolver
71
+ * @returns Instance
72
+ */
73
+ readonly factory: (resolver: Resolver<never, never>) => unknown;
74
+ /**
75
+ * Lifetime of the registration.
76
+ */
77
+ readonly lifetime: Lifetime;
78
+ }
79
+ /**
80
+ * Convert a token to a human-readable string.
81
+ */
82
+ export declare function tokenToString(token: unknown): string;
83
+ /**
84
+ * Build a human-readable circular dependency path from the resolving tokens.
85
+ *
86
+ * Uses the insertion order of Set to extract only the cycle portion.
87
+ * e.g. if resolvingTokens is [X, A, B, C] and token is A, returns "A -> B -> C -> A"
88
+ *
89
+ * @param resolvingTokens The set of tokens currently being resolved
90
+ * @param token The token that caused the circular dependency
91
+ * @returns Formatted cycle path string
92
+ */
93
+ export declare function buildCircularPath(resolvingTokens: Set<unknown>, token: unknown): string;
@@ -0,0 +1,120 @@
1
+ import type { Container } from '../container/index.cjs';
2
+ import type { DisposableContainer, DisposableScope } from '../disposable/index.cjs';
3
+ import { type ContainerInternals, INTERNALS } from '../internal.cjs';
4
+ import type { AbstractConstructor, Registration } from '../resolver/index.cjs';
5
+ /**
6
+ * Create a new scope (child container) from a Container, Scope, or their disposable variants.
7
+ *
8
+ * The scope inherits all registrations from the source.
9
+ * Singleton instances are shared with the parent, while scoped instances are local to the scope.
10
+ *
11
+ * @param source A Container, Scope, DisposableContainer, or DisposableScope to create a child scope from
12
+ * @returns A new Scope instance
13
+ * @throws ContainerError if the source has been disposed
14
+ */
15
+ export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
16
+ export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
17
+ export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: DisposableContainer<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
18
+ export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
19
+ /**
20
+ * Scoped child container.
21
+ *
22
+ * Inherits all registrations from the parent container.
23
+ * Singleton instances are shared with the parent, while scoped instances are local to this scope.
24
+ * Transient instances are always newly created.
25
+ *
26
+ * @template T PropertyKey-based token type map
27
+ * @template Sync Union of registered sync class constructors
28
+ * @template Async Union of registered async class constructors
29
+ * @template ScopedT PropertyKey-based token type map for scoped registrations
30
+ * @template ScopedSync Union of scoped sync class constructors
31
+ * @template ScopedAsync Union of scoped async class constructors
32
+ */
33
+ export declare class Scope<T = Record<never, never>, Sync extends AbstractConstructor = never, Async extends AbstractConstructor = never, ScopedT = Record<never, never>, ScopedSync extends AbstractConstructor = never, ScopedAsync extends AbstractConstructor = never> {
34
+ private readonly registrations;
35
+ private readonly singletonCache;
36
+ private readonly scopedCache;
37
+ private readonly resolvingTokens;
38
+ private singletonDepth;
39
+ private disposed;
40
+ /**
41
+ * Internal state accessor for extension modules (scope, disposable).
42
+ *
43
+ * @internal
44
+ */
45
+ readonly [INTERNALS]: ContainerInternals;
46
+ constructor(registrations: Map<unknown, Registration[]>, singletonCache: Map<Registration, unknown>);
47
+ /**
48
+ * Resolve an instance for the given token.
49
+ *
50
+ * - Singleton: Returns the shared instance from the parent container (creates and caches on first access).
51
+ * - Scoped: Returns an instance local to this scope (creates and caches on first access within the scope).
52
+ * - Transient: Creates a new instance on every call.
53
+ *
54
+ * @param token A registered token
55
+ * @returns The instance associated with the token
56
+ * @throws ContainerError if the token is not registered
57
+ */
58
+ resolve<V>(token: AbstractConstructor<V> & (Async | ScopedAsync)): Promise<V>;
59
+ resolve<V>(token: AbstractConstructor<V> & (Sync | ScopedSync)): V;
60
+ resolve<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K];
61
+ /**
62
+ * Try to resolve an instance for the given token.
63
+ *
64
+ * Returns `undefined` instead of throwing when the token is not registered.
65
+ * Other errors (circular dependency, disposed scope) are still thrown.
66
+ *
67
+ * @param token A token to resolve
68
+ * @returns The instance associated with the token, or `undefined` if not registered
69
+ */
70
+ tryResolve<V>(token: AbstractConstructor<V> & (Async | ScopedAsync)): Promise<V> | undefined;
71
+ tryResolve<V>(token: AbstractConstructor<V> & (Sync | ScopedSync)): V | undefined;
72
+ tryResolve<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K] | undefined;
73
+ tryResolve<V>(token: AbstractConstructor<V>): V | Promise<V> | undefined;
74
+ tryResolve(token: PropertyKey): unknown;
75
+ /**
76
+ * Resolve all instances for the given token.
77
+ *
78
+ * Returns an array of instances from all registered factories for the token,
79
+ * in registration order.
80
+ *
81
+ * @param token A registered token
82
+ * @returns An array of instances associated with the token
83
+ * @throws ContainerError if the token is not registered
84
+ */
85
+ resolveAll<V>(token: AbstractConstructor<V> & (Async | ScopedAsync)): Promise<V>[];
86
+ resolveAll<V>(token: AbstractConstructor<V> & (Sync | ScopedSync)): V[];
87
+ resolveAll<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K][];
88
+ /**
89
+ * Try to resolve all instances for the given token.
90
+ *
91
+ * Returns `undefined` instead of throwing when the token is not registered.
92
+ * Other errors (circular dependency, disposed scope) are still thrown.
93
+ *
94
+ * @param token A token to resolve
95
+ * @returns An array of instances associated with the token, or `undefined` if not registered
96
+ */
97
+ tryResolveAll<V>(token: AbstractConstructor<V> & (Async | ScopedAsync)): Promise<V>[] | undefined;
98
+ tryResolveAll<V>(token: AbstractConstructor<V> & (Sync | ScopedSync)): V[] | undefined;
99
+ tryResolveAll<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K][] | undefined;
100
+ tryResolveAll<V>(token: AbstractConstructor<V>): (V | Promise<V>)[] | undefined;
101
+ tryResolveAll(token: PropertyKey): unknown;
102
+ /**
103
+ * Internal resolution logic shared by resolve and tryResolve.
104
+ * Resolves the last registered factory for the token.
105
+ *
106
+ * @param token Token to resolve
107
+ * @param required If true, throws when the token is not registered. If false, returns undefined.
108
+ * @returns The resolved instance, or undefined if not registered and required is false
109
+ */
110
+ private resolveToken;
111
+ /**
112
+ * Internal resolution logic shared by resolveAll and tryResolveAll.
113
+ * Resolves all registered factories for the token.
114
+ *
115
+ * @param token Token to resolve
116
+ * @param required If true, throws when the token is not registered. If false, returns undefined.
117
+ * @returns An array of resolved instances, or undefined if not registered and required is false
118
+ */
119
+ private resolveAllTokens;
120
+ }
@@ -1,7 +1,7 @@
1
- import type { Container } from '../container';
2
- import type { DisposableContainer, DisposableScope } from '../disposable';
3
- import { type ContainerInternals, INTERNALS } from '../internal';
4
- import type { AbstractConstructor, Registration } from '../resolver';
1
+ import type { Container } from '../container/index.js';
2
+ import type { DisposableContainer, DisposableScope } from '../disposable/index.js';
3
+ import { type ContainerInternals, INTERNALS } from '../internal.js';
4
+ import type { AbstractConstructor, Registration } from '../resolver/index.js';
5
5
  /**
6
6
  * Create a new scope (child container) from a Container, Scope, or their disposable variants.
7
7
  *
@@ -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
+ **Typsichere Dependency Injection für TypeScript.**
6
+
7
+ Mache Abhängigkeiten explizit und prüfbar, auch wenn KI-Coding-Agenten den Code schreiben. Katagami sammelt Typen mit jeder Registrierung, prüft die in einer Factory verfügbaren Tokens und verfolgt asynchrone Rückgaben. Ohne Decorators, reflect-metadata oder Laufzeitabhängigkeiten.
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
+ ## Schnellstart
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
+ ## Mit KI-Coding-Agenten arbeiten
29
+
30
+ 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.
31
+
32
+ Wenn eine Singleton-Factory auf Scoped-Zustand einer Anfrage zugreift, entsteht beispielsweise ein Typfehler.
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
+ Registriere handler in diesem Beispiel mit registerScoped. @ts-expect-error prüft das fehlerhafte Beispiel in CI. Korrigiere im Anwendungscode die Lebensdauer und führe npx tsc --noEmit aus, statt den Fehler zu unterdrücken.
44
+
45
+ ## Gesammelte Typen und Garantien
46
+
47
+ createContainer() sammelt Typen aus Registrierungen. Solange Literalschlüssel und unique-symbol-Typen erhalten bleiben, werden Tokens außerhalb der sichtbaren Registrierungen abgelehnt. Eine manuelle Service-Typzuordnung ist nicht nötig.
48
+
49
+ Klassentokens folgen struktureller Typisierung: Eine andere kompatible Klasse kann akzeptiert werden. Ein in createContainer<Services>() deklarierter Schlüssel ist ebenfalls im Typ sichtbar, auch ohne tatsächliche Registrierung.
50
+
51
+ Unterstützt Singleton, Transient und Scoped, Modulkomposition mit use(), asynchrone Factories, optionale und mehrfache Auflösung, Ressourcenfreigabe und verzögerte Auflösung. Bei wenigen Abhängigkeiten reichen oft normale Parameter.
52
+
53
+ ## Anleitungen und ausführbares Beispiel
54
+
55
+ - [Anleitung für KI-Agenten (Englisch)](./ai-coding-agents.md)
56
+ - [Typgarantien (Englisch)](./type-safety.md)
57
+ - [API und Anwendung (Englisch)](./guide.md)
58
+ - [Starter für Anfrage-Scopes (Englisch)](../examples/request-scope/README.md)
59
+ - [DI auswählen (Englisch)](./choosing-di.md)
60
+
61
+ CI prüft Typbeispiele und Laufzeittests. Verbesserungen der Reparaturquote von Agenten oder Token-Einsparungen wurden noch nicht gemessen.
62
+
63
+ Der Name stammt von 型紙, den Papierschablonen der traditionellen japanischen Färberei. Typen sammeln sich wie übereinandergelegte Schablonen.
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
+ **Inyección de dependencias con seguridad de tipos para TypeScript.**
6
+
7
+ Haz explícitas y verificables las dependencias, incluso cuando el código lo escriben agentes de IA. Katagami acumula tipos con cada registro, comprueba los tokens accesibles en cada fábrica y conserva los resultados asíncronos. Sin decoradores, reflect-metadata ni dependencias en tiempo de ejecución.
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
+ ## Inicio rápido
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
+ ## Uso con agentes de programación de IA
29
+
30
+ 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.
31
+
32
+ Por ejemplo, acceder a un estado Scoped desde una fábrica Singleton produce un error de tipos.
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
+ En este ejemplo, registra handler con registerScoped. @ts-expect-error verifica el ejemplo incorrecto en CI; en la aplicación, corrige el ciclo de vida y ejecuta npx tsc --noEmit sin suprimir el error.
44
+
45
+ ## Tipos acumulados y garantías
46
+
47
+ createContainer() acumula los tipos de los registros. Si se conservan las claves literales y los tipos unique symbol, se rechazan los tokens fuera del conjunto visible de registros. No hace falta un mapa manual de servicios.
48
+
49
+ Los tokens de clase siguen el tipado estructural: otra clase compatible puede ser aceptada. Una clave declarada en createContainer<Services>() también puede estar disponible en los tipos sin tener un registro real.
50
+
51
+ Incluye ciclos de vida Singleton, Transient y Scoped, composición con use(), fábricas asíncronas, resolución opcional y múltiple, limpieza de recursos y resolución diferida. Para pocas dependencias, los parámetros normales pueden ser suficientes.
52
+
53
+ ## Guías y ejemplo ejecutable
54
+
55
+ - [Guía para agentes de IA (inglés)](./ai-coding-agents.md)
56
+ - [Garantías de tipos (inglés)](./type-safety.md)
57
+ - [Guía de uso y API (inglés)](./guide.md)
58
+ - [Ejemplo de ámbitos por petición (inglés)](../examples/request-scope/README.md)
59
+ - [Cómo elegir DI (inglés)](./choosing-di.md)
60
+
61
+ CI comprueba los ejemplos de tipos y las pruebas de ejecución. No se han medido mejoras en la tasa de reparación de agentes ni ahorro de tokens.
62
+
63
+ El nombre viene de 型紙, las plantillas de papel de la tintura tradicional japonesa. Los tipos se acumulan como capas de plantillas.
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
+ **Injection de dépendances avec sûreté des types pour TypeScript.**
6
+
7
+ Rendez les dépendances explicites et vérifiables, même quand des agents de programmation IA écrivent le code. Katagami accumule les types à chaque enregistrement, vérifie les jetons accessibles aux fabriques et suit les retours asynchrones. Sans décorateurs, reflect-metadata ni dépendances à l’exécution.
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
+ ## Démarrage rapide
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
+ ## Travailler avec des agents de programmation IA
29
+
30
+ 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.
31
+
32
+ Par exemple, accéder à un état Scoped depuis une fabrique Singleton produit une erreur de type.
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
+ Dans cet exemple, enregistrez handler avec registerScoped. @ts-expect-error sert à vérifier l’exemple incorrect en CI. Dans l’application, corrigez la durée de vie et lancez npx tsc --noEmit sans masquer l’erreur.
44
+
45
+ ## Types accumulés et garanties
46
+
47
+ createContainer() accumule les types des enregistrements. En conservant les clés littérales et les types unique symbol, les jetons absents de l’ensemble visible sont rejetés. Aucune table manuelle des types de services n’est nécessaire.
48
+
49
+ Les jetons de classe suivent le typage structurel : une autre classe compatible peut être acceptée. Une clé déclarée dans createContainer<Services>() peut aussi être visible dans les types sans enregistrement réel.
50
+
51
+ Prend en charge Singleton, Transient et Scoped, la composition avec use(), les fabriques asynchrones, la résolution optionnelle et multiple, la libération des ressources et la résolution différée. Pour peu de dépendances, des paramètres ordinaires peuvent suffire.
52
+
53
+ ## Guides et exemple exécutable
54
+
55
+ - [Guide pour agents IA (anglais)](./ai-coding-agents.md)
56
+ - [Garanties de types (anglais)](./type-safety.md)
57
+ - [Guide et API (anglais)](./guide.md)
58
+ - [Exemple de portée par requête (anglais)](../examples/request-scope/README.md)
59
+ - [Choisir une approche DI (anglais)](./choosing-di.md)
60
+
61
+ Les exemples de types et les tests d’exécution sont vérifiés en CI. Les gains de réussite des agents ou de consommation de tokens n’ont pas encore été mesurés.
62
+
63
+ Le nom vient de 型紙, les pochoirs de papier de la teinture traditionnelle japonaise. Les types s’accumulent comme des couches de pochoirs.
64
+
65
+ MIT