katagami 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +140 -584
  2. package/dist/chunk-J2NYR3SH.js +6 -0
  3. package/dist/container/index.d.cts +108 -0
  4. package/dist/container/index.d.ts +2 -2
  5. package/dist/disposable/index.cjs +16 -25
  6. package/dist/disposable/index.d.cts +69 -0
  7. package/dist/disposable/index.d.ts +13 -5
  8. package/dist/disposable/index.js +1 -1
  9. package/dist/error/index.d.cts +11 -0
  10. package/dist/index.cjs +91 -55
  11. package/dist/index.d.cts +6 -0
  12. package/dist/index.d.ts +6 -6
  13. package/dist/index.js +76 -31
  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 +3 -3
  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 +84 -0
  24. package/docs/README.es.md +84 -0
  25. package/docs/README.fr.md +84 -0
  26. package/docs/README.ja.md +105 -0
  27. package/docs/README.ko.md +84 -0
  28. package/docs/README.zh-CN.md +84 -0
  29. package/docs/README.zh-TW.md +84 -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 +143 -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 -23
  47. package/dist/index-jx8b52m0.js +0 -4
@@ -0,0 +1,6 @@
1
+ // src/internal.ts
2
+ var INTERNALS = /* @__PURE__ */ Symbol.for("katagami.internals.v3");
3
+
4
+ export {
5
+ INTERNALS
6
+ };
@@ -0,0 +1,108 @@
1
+ import { type ContainerInternals, INTERNALS } from '../internal.cjs';
2
+ import type { AbstractConstructor, Resolver } from '../resolver/index.cjs';
3
+ /**
4
+ * Create a new DI container.
5
+ *
6
+ * Pass an interface as generic T to fix the PropertyKey token type map upfront (order-independent).
7
+ * Class tokens are accumulated via registerSingleton/registerTransient method chaining (order-dependent).
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * interface Services { SampleController: string }
12
+ * const c = createContainer<Services>()
13
+ * .registerSingleton(TextGenerationService, () => new MastraTextGenerationService())
14
+ * .registerTransient(GenerateTextUseCase, r => new GenerateTextUseCase(r.resolve(TextGenerationService)));
15
+ * ```
16
+ */
17
+ export declare function createContainer<T = Record<never, never>, ScopedT = Record<never, never>>(): Container<T, never, never, ScopedT>;
18
+ /**
19
+ * Lightweight DI container — registration only.
20
+ *
21
+ * Provides type inference through method chaining with registerSingleton/registerTransient/registerScoped.
22
+ * Resolution is performed through a Scope created via `createScope(container)`.
23
+ *
24
+ * Registering the same token multiple times accumulates all factories.
25
+ *
26
+ * @template T PropertyKey-based token type map (defined via interface, order-independent)
27
+ * @template Sync Union of registered sync class constructors (accumulated via chaining, order-dependent)
28
+ * @template Async Union of registered async class constructors (accumulated via chaining, order-dependent)
29
+ * @template ScopedT PropertyKey-based token type map for scoped registrations
30
+ * @template ScopedSync Union of scoped sync class constructors (accumulated via chaining, order-dependent)
31
+ * @template ScopedAsync Union of scoped async class constructors (accumulated via chaining, order-dependent)
32
+ */
33
+ export declare class Container<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 disposed;
37
+ /**
38
+ * Internal state accessor for extension modules (scope, disposable).
39
+ *
40
+ * @internal
41
+ */
42
+ readonly [INTERNALS]: ContainerInternals;
43
+ constructor();
44
+ /**
45
+ * Register a factory function as a singleton for the given token.
46
+ *
47
+ * Creates the instance on the first resolve and returns the cached value thereafter.
48
+ * If the same token is registered multiple times, all factories are accumulated.
49
+ * `resolve()` returns the last registered instance; `resolveAll()` returns all.
50
+ *
51
+ * @param token Any value to use as a token
52
+ * @param factory Factory function that receives a resolver and returns an instance
53
+ * @returns The container for method chaining
54
+ */
55
+ registerSingleton<V>(token: AbstractConstructor<V>, factory: (resolver: Resolver<T, Sync, Async>) => Promise<V>): Container<T, Sync, Async | AbstractConstructor<V>, ScopedT, ScopedSync, ScopedAsync>;
56
+ registerSingleton<V>(token: AbstractConstructor<V>, factory: (resolver: Resolver<T, Sync, Async>) => V): Container<T, Sync | AbstractConstructor<V>, Async, ScopedT, ScopedSync, ScopedAsync>;
57
+ registerSingleton<K extends PropertyKey, V>(token: K, factory: (resolver: Resolver<T, Sync, Async>) => V): Container<Record<K, V> & T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
58
+ registerSingleton<V>(token: unknown, factory: (resolver: Resolver<T, Sync, Async>) => V): Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
59
+ /**
60
+ * Register a factory function as transient for the given token.
61
+ *
62
+ * Creates a new instance via the factory function on every resolve.
63
+ * If the same token is registered multiple times, all factories are accumulated.
64
+ * `resolve()` returns the last registered instance; `resolveAll()` returns all.
65
+ *
66
+ * @param token Any value to use as a token
67
+ * @param factory Factory function that receives a resolver and returns an instance
68
+ * @returns The container for method chaining
69
+ */
70
+ registerTransient<V>(token: AbstractConstructor<V>, factory: (resolver: Resolver<T, Sync, Async>) => Promise<V>): Container<T, Sync, Async | AbstractConstructor<V>, ScopedT, ScopedSync, ScopedAsync>;
71
+ registerTransient<V>(token: AbstractConstructor<V>, factory: (resolver: Resolver<T, Sync, Async>) => V): Container<T, Sync | AbstractConstructor<V>, Async, ScopedT, ScopedSync, ScopedAsync>;
72
+ registerTransient<K extends PropertyKey, V>(token: K, factory: (resolver: Resolver<T, Sync, Async>) => V): Container<Record<K, V> & T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
73
+ registerTransient<V>(token: unknown, factory: (resolver: Resolver<T, Sync, Async>) => V): Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
74
+ /**
75
+ * Register a factory function as scoped for the given token.
76
+ *
77
+ * Within a scope, creates the instance on the first resolve and returns the cached value thereafter.
78
+ * Each scope maintains its own cache, so different scopes produce different instances.
79
+ * Scoped tokens cannot be resolved from the root container — use createScope() first.
80
+ *
81
+ * @param token Any value to use as a token
82
+ * @param factory Factory function that receives a resolver and returns an instance
83
+ * @returns The container for method chaining
84
+ */
85
+ registerScoped<V>(token: AbstractConstructor<V>, factory: (resolver: Resolver<T & ScopedT, Sync | ScopedSync, Async | ScopedAsync>) => Promise<V>): Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync | AbstractConstructor<V>>;
86
+ registerScoped<V>(token: AbstractConstructor<V>, factory: (resolver: Resolver<T & ScopedT, Sync | ScopedSync, Async | ScopedAsync>) => V): Container<T, Sync, Async, ScopedT, ScopedSync | AbstractConstructor<V>, ScopedAsync>;
87
+ registerScoped<K extends PropertyKey, V>(token: K, factory: (resolver: Resolver<T & ScopedT, Sync | ScopedSync, Async | ScopedAsync>) => V): Container<T, Sync, Async, Record<K, V> & ScopedT, ScopedSync, ScopedAsync>;
88
+ registerScoped<V>(token: unknown, factory: (resolver: Resolver<T & ScopedT, Sync | ScopedSync, Async | ScopedAsync>) => V): Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
89
+ /**
90
+ * Apply all registrations from another container (module) to this container.
91
+ *
92
+ * Copies registration entries (factory + lifetime) by replacing existing entries for each token.
93
+ * Singleton instance caches are not shared — each container manages its own.
94
+ *
95
+ * @param source A container whose registrations will be copied into this container
96
+ * @returns The container for method chaining
97
+ */
98
+ use<MT, MSync extends AbstractConstructor, MAsync extends AbstractConstructor, MScopedT, MScopedSync extends AbstractConstructor, MScopedAsync extends AbstractConstructor>(source: Container<MT, MSync, MAsync, MScopedT, MScopedSync, MScopedAsync>): Container<T & MT, Sync | MSync, Async | MAsync, ScopedT & MScopedT, ScopedSync | MScopedSync, ScopedAsync | MScopedAsync>;
99
+ /**
100
+ * Add a registration entry. Accumulates registrations for the same token.
101
+ *
102
+ * @param token Token
103
+ * @param factory Factory function
104
+ * @param lifetime Lifetime of the registration
105
+ * @returns The container for method chaining
106
+ */
107
+ private addRegistration;
108
+ }
@@ -1,5 +1,5 @@
1
- import { type ContainerInternals, INTERNALS } from '../internal';
2
- import type { AbstractConstructor, Resolver } from '../resolver';
1
+ import { type ContainerInternals, INTERNALS } from '../internal.js';
2
+ import type { AbstractConstructor, Resolver } from '../resolver/index.js';
3
3
  /**
4
4
  * Create a new DI container.
5
5
  *
@@ -1,40 +1,31 @@
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/disposable/index.ts
30
- var exports_disposable = {};
31
- __export(exports_disposable, {
21
+ var disposable_exports = {};
22
+ __export(disposable_exports, {
32
23
  disposable: () => disposable
33
24
  });
34
- module.exports = __toCommonJS(exports_disposable);
25
+ module.exports = __toCommonJS(disposable_exports);
35
26
 
36
27
  // src/internal.ts
37
- var INTERNALS = Symbol("katagami.internals");
28
+ var INTERNALS = /* @__PURE__ */ Symbol.for("katagami.internals.v3");
38
29
 
39
30
  // src/disposable/index.ts
40
31
  function disposable(container) {
@@ -0,0 +1,69 @@
1
+ import type { Container } from '../container/index.cjs';
2
+ import { type ContainerInternals, INTERNALS, type TYPE_STATE } from '../internal.cjs';
3
+ import type { AbstractConstructor, Resolver } from '../resolver/index.cjs';
4
+ import type { Scope } from '../scope/index.cjs';
5
+ /**
6
+ * A container wrapped with `disposable()`.
7
+ *
8
+ * Registration methods (`registerSingleton`, `registerTransient`, `registerScoped`, `use`)
9
+ * are excluded, preventing accidental registration on a potentially-disposed container.
10
+ * Use `createScope()` to create a scope for resolution.
11
+ *
12
+ * @template T PropertyKey-based token type map
13
+ * @template Sync Union of registered sync class constructors
14
+ * @template Async Union of registered async class constructors
15
+ * @template ScopedT PropertyKey-based token type map for scoped registrations
16
+ * @template ScopedSync Union of scoped sync class constructors
17
+ * @template ScopedAsync Union of scoped async class constructors
18
+ */
19
+ export interface DisposableContainer<T = Record<never, never>, Sync extends AbstractConstructor = never, Async extends AbstractConstructor = never, ScopedT = Record<never, never>, ScopedSync extends AbstractConstructor = never, ScopedAsync extends AbstractConstructor = never> extends AsyncDisposable {
20
+ readonly [INTERNALS]: ContainerInternals;
21
+ readonly [TYPE_STATE]?: {
22
+ readonly kind: 'container';
23
+ readonly registrations: readonly [T, Sync, Async, ScopedT, ScopedSync, ScopedAsync];
24
+ };
25
+ }
26
+ /**
27
+ * A scope wrapped with `disposable()`.
28
+ *
29
+ * Only `resolve`, `tryResolve`, `resolveAll`, and `tryResolveAll` are available at the type level.
30
+ *
31
+ * @template T PropertyKey-based token type map
32
+ * @template Sync Union of registered sync class constructors
33
+ * @template Async Union of registered async class constructors
34
+ * @template ScopedT PropertyKey-based token type map for scoped registrations
35
+ * @template ScopedSync Union of scoped sync class constructors
36
+ * @template ScopedAsync Union of scoped async class constructors
37
+ */
38
+ export interface DisposableScope<T = Record<never, never>, Sync extends AbstractConstructor = never, Async extends AbstractConstructor = never, ScopedT = Record<never, never>, ScopedSync extends AbstractConstructor = never, ScopedAsync extends AbstractConstructor = never> extends Resolver<T & ScopedT, Sync | ScopedSync, Async | ScopedAsync>, AsyncDisposable {
39
+ readonly [INTERNALS]: ContainerInternals;
40
+ readonly [TYPE_STATE]?: {
41
+ readonly kind: 'scope';
42
+ readonly registrations: readonly [T, Sync, Async, ScopedT, ScopedSync, ScopedAsync];
43
+ };
44
+ }
45
+ /**
46
+ * Add async disposal capability to a container or scope.
47
+ *
48
+ * Enables `await using` syntax by attaching `[Symbol.asyncDispose]` to the target.
49
+ * Disposes owned instances in reverse creation order (LIFO), calling
50
+ * `[Symbol.asyncDispose]()` or `[Symbol.dispose]()` on each instance that implements them.
51
+ *
52
+ * The returned type prevents registration methods from being called on a potentially-disposed container.
53
+ * For scopes, `resolve`, `tryResolve`, `resolveAll`, and `tryResolveAll` remain available.
54
+ *
55
+ * @param container A Container or Scope to make disposable
56
+ * @returns The same object with `AsyncDisposable` capability added and registration methods removed from the type
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * import { createContainer } from 'katagami';
61
+ * import { disposable } from 'katagami/disposable';
62
+ *
63
+ * await using container = disposable(
64
+ * createContainer().registerSingleton(DB, () => new Database())
65
+ * );
66
+ * ```
67
+ */
68
+ export declare function disposable<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(container: Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): DisposableContainer<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
69
+ export declare function disposable<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(scope: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
@@ -1,7 +1,7 @@
1
- import type { Container } from '../container';
2
- import { type ContainerInternals, INTERNALS } from '../internal';
3
- import type { AbstractConstructor, Resolver } from '../resolver';
4
- import type { Scope } from '../scope';
1
+ import type { Container } from '../container/index.js';
2
+ import { type ContainerInternals, INTERNALS, type TYPE_STATE } from '../internal.js';
3
+ import type { AbstractConstructor, Resolver } from '../resolver/index.js';
4
+ import type { Scope } from '../scope/index.js';
5
5
  /**
6
6
  * A container wrapped with `disposable()`.
7
7
  *
@@ -16,8 +16,12 @@ import type { Scope } from '../scope';
16
16
  * @template ScopedSync Union of scoped sync class constructors
17
17
  * @template ScopedAsync Union of scoped async class constructors
18
18
  */
19
- export interface DisposableContainer<_T = Record<never, never>, _Sync extends AbstractConstructor = never, _Async extends AbstractConstructor = never, _ScopedT = Record<never, never>, _ScopedSync extends AbstractConstructor = never, _ScopedAsync extends AbstractConstructor = never> extends AsyncDisposable {
19
+ export interface DisposableContainer<T = Record<never, never>, Sync extends AbstractConstructor = never, Async extends AbstractConstructor = never, ScopedT = Record<never, never>, ScopedSync extends AbstractConstructor = never, ScopedAsync extends AbstractConstructor = never> extends AsyncDisposable {
20
20
  readonly [INTERNALS]: ContainerInternals;
21
+ readonly [TYPE_STATE]?: {
22
+ readonly kind: 'container';
23
+ readonly registrations: readonly [T, Sync, Async, ScopedT, ScopedSync, ScopedAsync];
24
+ };
21
25
  }
22
26
  /**
23
27
  * A scope wrapped with `disposable()`.
@@ -33,6 +37,10 @@ export interface DisposableContainer<_T = Record<never, never>, _Sync extends Ab
33
37
  */
34
38
  export interface DisposableScope<T = Record<never, never>, Sync extends AbstractConstructor = never, Async extends AbstractConstructor = never, ScopedT = Record<never, never>, ScopedSync extends AbstractConstructor = never, ScopedAsync extends AbstractConstructor = never> extends Resolver<T & ScopedT, Sync | ScopedSync, Async | ScopedAsync>, AsyncDisposable {
35
39
  readonly [INTERNALS]: ContainerInternals;
40
+ readonly [TYPE_STATE]?: {
41
+ readonly kind: 'scope';
42
+ readonly registrations: readonly [T, Sync, Async, ScopedT, ScopedSync, ScopedAsync];
43
+ };
36
44
  }
37
45
  /**
38
46
  * Add async disposal capability to a container or scope.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  INTERNALS
3
- } from "../index-jx8b52m0.js";
3
+ } from "../chunk-J2NYR3SH.js";
4
4
 
5
5
  // src/disposable/index.ts
6
6
  function disposable(container) {
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Error thrown by the DI container.
3
+ *
4
+ * Represents failures in container operations such as resolving an unregistered token.
5
+ */
6
+ export declare class ContainerError extends Error {
7
+ /**
8
+ * @param message Error message
9
+ */
10
+ constructor(message: string);
11
+ }
package/dist/index.cjs CHANGED
@@ -1,58 +1,53 @@
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/index.ts
30
- var exports_src = {};
31
- __export(exports_src, {
32
- createScope: () => createScope,
33
- createContainer: () => createContainer,
34
- Scope: () => Scope,
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Container: () => Container,
35
24
  ContainerError: () => ContainerError,
36
- Container: () => Container
25
+ Scope: () => Scope,
26
+ createContainer: () => createContainer,
27
+ createScope: () => createScope
37
28
  });
38
- module.exports = __toCommonJS(exports_src);
29
+ module.exports = __toCommonJS(index_exports);
39
30
 
40
31
  // src/internal.ts
41
- var INTERNALS = Symbol("katagami.internals");
32
+ var INTERNALS = /* @__PURE__ */ Symbol.for("katagami.internals.v3");
42
33
 
43
34
  // src/container/index.ts
44
35
  function createContainer() {
45
- return new Container;
36
+ return new Container();
46
37
  }
47
-
48
- class Container {
38
+ var Container = class {
49
39
  registrations;
50
40
  singletonCache;
51
41
  disposed = false;
42
+ /**
43
+ * Internal state accessor for extension modules (scope, disposable).
44
+ *
45
+ * @internal
46
+ */
52
47
  [INTERNALS];
53
48
  constructor() {
54
- this.registrations = new Map;
55
- this.singletonCache = new Map;
49
+ this.registrations = /* @__PURE__ */ new Map();
50
+ this.singletonCache = /* @__PURE__ */ new Map();
56
51
  this[INTERNALS] = {
57
52
  isDisposed: () => this.disposed,
58
53
  markDisposed: () => {
@@ -78,23 +73,36 @@ class Container {
78
73
  }
79
74
  return this;
80
75
  }
76
+ /**
77
+ * Add a registration entry. Accumulates registrations for the same token.
78
+ *
79
+ * @param token Token
80
+ * @param factory Factory function
81
+ * @param lifetime Lifetime of the registration
82
+ * @returns The container for method chaining
83
+ */
81
84
  addRegistration(token, factory, lifetime) {
82
85
  const existing = this.registrations.get(token);
83
- if (existing !== undefined) {
86
+ if (existing !== void 0) {
84
87
  existing.push({ factory, lifetime });
85
88
  } else {
86
89
  this.registrations.set(token, [{ factory, lifetime }]);
87
90
  }
88
91
  return this;
89
92
  }
90
- }
93
+ };
94
+
91
95
  // src/error/index.ts
92
- class ContainerError extends Error {
96
+ var ContainerError = class extends Error {
97
+ /**
98
+ * @param message Error message
99
+ */
93
100
  constructor(message) {
94
101
  super(message);
95
102
  this.name = "ContainerError";
96
103
  }
97
- }
104
+ };
105
+
98
106
  // src/resolver/index.ts
99
107
  function tokenToString(token) {
100
108
  if (typeof token === "function") {
@@ -128,20 +136,24 @@ function createScope(source) {
128
136
  }
129
137
  return new Scope(internals.registrations, internals.singletonCache);
130
138
  }
131
-
132
- class Scope {
139
+ var Scope = class {
133
140
  registrations;
134
141
  singletonCache;
135
142
  scopedCache;
136
143
  resolvingTokens;
137
144
  singletonDepth = 0;
138
145
  disposed = false;
146
+ /**
147
+ * Internal state accessor for extension modules (scope, disposable).
148
+ *
149
+ * @internal
150
+ */
139
151
  [INTERNALS];
140
152
  constructor(registrations, singletonCache) {
141
153
  this.registrations = registrations;
142
154
  this.singletonCache = singletonCache;
143
- this.scopedCache = new Map;
144
- this.resolvingTokens = new Set;
155
+ this.scopedCache = /* @__PURE__ */ new Map();
156
+ this.resolvingTokens = /* @__PURE__ */ new Set();
145
157
  this[INTERNALS] = {
146
158
  isDisposed: () => this.disposed,
147
159
  markDisposed: () => {
@@ -164,27 +176,37 @@ class Scope {
164
176
  tryResolveAll(token) {
165
177
  return this.resolveAllTokens(token, false);
166
178
  }
179
+ /**
180
+ * Internal resolution logic shared by resolve and tryResolve.
181
+ * Resolves the last registered factory for the token.
182
+ *
183
+ * @param token Token to resolve
184
+ * @param required If true, throws when the token is not registered. If false, returns undefined.
185
+ * @returns The resolved instance, or undefined if not registered and required is false
186
+ */
167
187
  resolveToken(token, required) {
168
188
  if (this.disposed) {
169
189
  throw new ContainerError("Cannot resolve from a disposed scope.");
170
190
  }
171
191
  const registrations = this.registrations.get(token);
172
- if (registrations === undefined || registrations.length === 0) {
192
+ if (registrations === void 0 || registrations.length === 0) {
173
193
  if (required) {
174
194
  throw new ContainerError(`Token "${tokenToString(token)}" is not registered.`);
175
195
  }
176
- return;
196
+ return void 0;
177
197
  }
178
198
  const registration = registrations[registrations.length - 1];
179
199
  const singletonCached = this.singletonCache.get(registration);
180
- if (singletonCached !== undefined) {
200
+ if (singletonCached !== void 0) {
181
201
  return singletonCached;
182
202
  }
183
203
  if (registration.lifetime === "scoped" && this.singletonDepth > 0) {
184
- throw new ContainerError(`Captive dependency detected: scoped token "${tokenToString(token)}" cannot be resolved inside a singleton factory. Scoped instances must not be captured by singletons.`);
204
+ throw new ContainerError(
205
+ `Captive dependency detected: scoped token "${tokenToString(token)}" cannot be resolved inside a singleton factory. Scoped instances must not be captured by singletons.`
206
+ );
185
207
  }
186
208
  const scopedCached = this.scopedCache.get(registration);
187
- if (scopedCached !== undefined) {
209
+ if (scopedCached !== void 0) {
188
210
  return scopedCached;
189
211
  }
190
212
  if (this.resolvingTokens.has(token)) {
@@ -195,7 +217,9 @@ class Scope {
195
217
  this.singletonDepth++;
196
218
  }
197
219
  try {
198
- const instance = registration.factory(this);
220
+ const instance = registration.factory(
221
+ this
222
+ );
199
223
  if (registration.lifetime === "singleton") {
200
224
  this.singletonCache.set(registration, instance);
201
225
  } else if (registration.lifetime === "scoped") {
@@ -209,16 +233,24 @@ class Scope {
209
233
  this.resolvingTokens.delete(token);
210
234
  }
211
235
  }
236
+ /**
237
+ * Internal resolution logic shared by resolveAll and tryResolveAll.
238
+ * Resolves all registered factories for the token.
239
+ *
240
+ * @param token Token to resolve
241
+ * @param required If true, throws when the token is not registered. If false, returns undefined.
242
+ * @returns An array of resolved instances, or undefined if not registered and required is false
243
+ */
212
244
  resolveAllTokens(token, required) {
213
245
  if (this.disposed) {
214
246
  throw new ContainerError("Cannot resolve from a disposed scope.");
215
247
  }
216
248
  const registrations = this.registrations.get(token);
217
- if (registrations === undefined || registrations.length === 0) {
249
+ if (registrations === void 0 || registrations.length === 0) {
218
250
  if (required) {
219
251
  throw new ContainerError(`Token "${tokenToString(token)}" is not registered.`);
220
252
  }
221
- return;
253
+ return void 0;
222
254
  }
223
255
  if (this.resolvingTokens.has(token)) {
224
256
  throw new ContainerError(`Circular dependency detected: ${buildCircularPath(this.resolvingTokens, token)}`);
@@ -228,21 +260,25 @@ class Scope {
228
260
  return registrations.map((registration) => {
229
261
  const reg = registration;
230
262
  const singletonCached = this.singletonCache.get(registration);
231
- if (singletonCached !== undefined) {
263
+ if (singletonCached !== void 0) {
232
264
  return singletonCached;
233
265
  }
234
266
  if (reg.lifetime === "scoped" && this.singletonDepth > 0) {
235
- throw new ContainerError(`Captive dependency detected: scoped token "${tokenToString(token)}" cannot be resolved inside a singleton factory. Scoped instances must not be captured by singletons.`);
267
+ throw new ContainerError(
268
+ `Captive dependency detected: scoped token "${tokenToString(token)}" cannot be resolved inside a singleton factory. Scoped instances must not be captured by singletons.`
269
+ );
236
270
  }
237
271
  const scopedCached = this.scopedCache.get(registration);
238
- if (scopedCached !== undefined) {
272
+ if (scopedCached !== void 0) {
239
273
  return scopedCached;
240
274
  }
241
275
  if (reg.lifetime === "singleton") {
242
276
  this.singletonDepth++;
243
277
  }
244
278
  try {
245
- const instance = reg.factory(this);
279
+ const instance = reg.factory(
280
+ this
281
+ );
246
282
  if (reg.lifetime === "singleton") {
247
283
  this.singletonCache.set(registration, instance);
248
284
  } else if (reg.lifetime === "scoped") {
@@ -259,4 +295,4 @@ class Scope {
259
295
  this.resolvingTokens.delete(token);
260
296
  }
261
297
  }
262
- }
298
+ };
@@ -0,0 +1,6 @@
1
+ export { Container, createContainer } from './container/index.cjs';
2
+ export type { DisposableContainer, DisposableScope, disposable } from './disposable/index.cjs';
3
+ export { ContainerError } from './error/index.cjs';
4
+ export type { lazy } from './lazy/index.cjs';
5
+ export type { Resolver } from './resolver/index.cjs';
6
+ export { createScope, Scope } from './scope/index.cjs';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { Container, createContainer } from './container';
2
- export type { DisposableContainer, DisposableScope, disposable } from './disposable';
3
- export { ContainerError } from './error';
4
- export type { lazy } from './lazy';
5
- export type { Resolver } from './resolver';
6
- export { createScope, Scope } from './scope';
1
+ export { Container, createContainer } from './container/index.js';
2
+ export type { DisposableContainer, DisposableScope, disposable } from './disposable/index.js';
3
+ export { ContainerError } from './error/index.js';
4
+ export type { lazy } from './lazy/index.js';
5
+ export type { Resolver } from './resolver/index.js';
6
+ export { createScope, Scope } from './scope/index.js';