katagami 3.0.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -37
- package/dist/chunk-R66WOZUM.js +71 -0
- package/dist/container/index.d.cts +142 -35
- package/dist/container/index.d.ts +142 -35
- package/dist/container/policy.d.cts +36 -0
- package/dist/container/policy.d.ts +36 -0
- package/dist/disposable/index.cjs +27 -5
- package/dist/disposable/index.d.cts +17 -7
- package/dist/disposable/index.d.ts +17 -7
- package/dist/disposable/index.js +2 -41
- package/dist/entrypoint/index.d.cts +20 -0
- package/dist/entrypoint/index.d.ts +20 -0
- package/dist/index.cjs +551 -149
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +495 -150
- package/dist/internal.d.cts +65 -0
- package/dist/internal.d.ts +65 -0
- package/dist/metadata/index.d.cts +67 -0
- package/dist/metadata/index.d.ts +67 -0
- package/dist/resolver/index.d.cts +5 -0
- package/dist/resolver/index.d.ts +5 -0
- package/dist/scope/index.d.cts +49 -24
- package/dist/scope/index.d.ts +49 -24
- package/dist/scope/operations.d.cts +22 -0
- package/dist/scope/operations.d.ts +22 -0
- package/docs/README.de.md +3 -2
- package/docs/README.es.md +3 -2
- package/docs/README.fr.md +3 -2
- package/docs/README.ja.md +61 -27
- package/docs/README.ko.md +3 -2
- package/docs/README.zh-CN.md +3 -2
- package/docs/README.zh-TW.md +3 -2
- package/docs/ai-coding-agents.md +3 -3
- package/docs/articles/ai-coding-agents.md +1 -1
- package/docs/articles/request-scope.md +2 -1
- package/docs/choosing-di.md +36 -9
- package/docs/guide.md +35 -4
- package/docs/registration-policies.ja.md +261 -0
- package/docs/registration-policies.md +435 -0
- package/docs/type-safety.md +13 -4
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/dist/chunk-J2NYR3SH.js +0 -6
package/dist/internal.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { PolicyState } from './container/policy.cjs';
|
|
1
2
|
import type { Registration } from './resolver/index.cjs';
|
|
3
|
+
import type { BeforeResolve } from './scope/index.cjs';
|
|
2
4
|
/**
|
|
3
5
|
* Symbol used by extension modules (scope, disposable) to access container/scope internals.
|
|
4
6
|
*
|
|
@@ -7,6 +9,7 @@ import type { Registration } from './resolver/index.cjs';
|
|
|
7
9
|
export declare const INTERNALS: unique symbol;
|
|
8
10
|
/** Type-only registration state retained by disposable views. No runtime property is emitted. */
|
|
9
11
|
export declare const TYPE_STATE: unique symbol;
|
|
12
|
+
export declare const REGISTRATION_STATE: unique symbol;
|
|
10
13
|
/**
|
|
11
14
|
* Internal state exposed via the INTERNALS symbol.
|
|
12
15
|
*
|
|
@@ -16,6 +19,9 @@ export declare const TYPE_STATE: unique symbol;
|
|
|
16
19
|
* @internal
|
|
17
20
|
*/
|
|
18
21
|
export interface ContainerInternals {
|
|
22
|
+
readonly kind: 'container' | 'scope';
|
|
23
|
+
readonly policy: PolicyState | undefined;
|
|
24
|
+
readonly beforeResolve: readonly BeforeResolve[];
|
|
19
25
|
/** All registrations (singleton / transient / scoped). Each token maps to an array of registrations. */
|
|
20
26
|
readonly registrations: Map<unknown, Registration[]>;
|
|
21
27
|
/** Singleton cache keyed by Registration object (Container: singletons, Scope: shared with parent). */
|
|
@@ -27,3 +33,62 @@ export interface ContainerInternals {
|
|
|
27
33
|
/** Mark this container / scope as disposed. */
|
|
28
34
|
markDisposed(): void;
|
|
29
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Outcome of an asynchronous creation.
|
|
38
|
+
*
|
|
39
|
+
* Disposal needs the created value in order to close it, but must not listen to the promise the
|
|
40
|
+
* scope handed to the caller: that would take over a failure the caller was meant to see. The
|
|
41
|
+
* scope records the outcome on a chain of its own, which never rejects.
|
|
42
|
+
*
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export type Creation = {
|
|
46
|
+
readonly failed: false;
|
|
47
|
+
readonly value: unknown;
|
|
48
|
+
} | {
|
|
49
|
+
readonly failed: true;
|
|
50
|
+
readonly error: unknown;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Settlement records for cached asynchronous creations, keyed by the promise the scope caches.
|
|
54
|
+
*
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export declare const creations: WeakMap<Promise<unknown>, Promise<Creation>>;
|
|
58
|
+
/**
|
|
59
|
+
* Record how a creation settles, on a chain that never rejects.
|
|
60
|
+
*
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export declare function settle(creation: Promise<unknown>): Promise<Creation>;
|
|
64
|
+
/**
|
|
65
|
+
* A factory running synchronously right now.
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
export interface RunningFactory {
|
|
70
|
+
readonly scope: object;
|
|
71
|
+
readonly token: unknown;
|
|
72
|
+
readonly registration: Registration;
|
|
73
|
+
/** The singleton cache of the container the scope belongs to. */
|
|
74
|
+
readonly singletons: object;
|
|
75
|
+
readonly context: unknown;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Factories running synchronously right now, innermost last, across every scope and module copy.
|
|
79
|
+
*
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
export declare const constructing: RunningFactory[];
|
|
83
|
+
/**
|
|
84
|
+
* Internal state of a Scope.
|
|
85
|
+
*
|
|
86
|
+
* `resolveInternal` resolves without the policy return check: the value stays inside the
|
|
87
|
+
* face that asked for it. The operations face uses it to obtain the callable it never hands out.
|
|
88
|
+
*
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
export interface ScopeInternals extends ContainerInternals {
|
|
92
|
+
readonly kind: 'scope';
|
|
93
|
+
resolveInternal(token: unknown): unknown;
|
|
94
|
+
}
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { PolicyState } from './container/policy.js';
|
|
1
2
|
import type { Registration } from './resolver/index.js';
|
|
3
|
+
import type { BeforeResolve } from './scope/index.js';
|
|
2
4
|
/**
|
|
3
5
|
* Symbol used by extension modules (scope, disposable) to access container/scope internals.
|
|
4
6
|
*
|
|
@@ -7,6 +9,7 @@ import type { Registration } from './resolver/index.js';
|
|
|
7
9
|
export declare const INTERNALS: unique symbol;
|
|
8
10
|
/** Type-only registration state retained by disposable views. No runtime property is emitted. */
|
|
9
11
|
export declare const TYPE_STATE: unique symbol;
|
|
12
|
+
export declare const REGISTRATION_STATE: unique symbol;
|
|
10
13
|
/**
|
|
11
14
|
* Internal state exposed via the INTERNALS symbol.
|
|
12
15
|
*
|
|
@@ -16,6 +19,9 @@ export declare const TYPE_STATE: unique symbol;
|
|
|
16
19
|
* @internal
|
|
17
20
|
*/
|
|
18
21
|
export interface ContainerInternals {
|
|
22
|
+
readonly kind: 'container' | 'scope';
|
|
23
|
+
readonly policy: PolicyState | undefined;
|
|
24
|
+
readonly beforeResolve: readonly BeforeResolve[];
|
|
19
25
|
/** All registrations (singleton / transient / scoped). Each token maps to an array of registrations. */
|
|
20
26
|
readonly registrations: Map<unknown, Registration[]>;
|
|
21
27
|
/** Singleton cache keyed by Registration object (Container: singletons, Scope: shared with parent). */
|
|
@@ -27,3 +33,62 @@ export interface ContainerInternals {
|
|
|
27
33
|
/** Mark this container / scope as disposed. */
|
|
28
34
|
markDisposed(): void;
|
|
29
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Outcome of an asynchronous creation.
|
|
38
|
+
*
|
|
39
|
+
* Disposal needs the created value in order to close it, but must not listen to the promise the
|
|
40
|
+
* scope handed to the caller: that would take over a failure the caller was meant to see. The
|
|
41
|
+
* scope records the outcome on a chain of its own, which never rejects.
|
|
42
|
+
*
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export type Creation = {
|
|
46
|
+
readonly failed: false;
|
|
47
|
+
readonly value: unknown;
|
|
48
|
+
} | {
|
|
49
|
+
readonly failed: true;
|
|
50
|
+
readonly error: unknown;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Settlement records for cached asynchronous creations, keyed by the promise the scope caches.
|
|
54
|
+
*
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export declare const creations: WeakMap<Promise<unknown>, Promise<Creation>>;
|
|
58
|
+
/**
|
|
59
|
+
* Record how a creation settles, on a chain that never rejects.
|
|
60
|
+
*
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export declare function settle(creation: Promise<unknown>): Promise<Creation>;
|
|
64
|
+
/**
|
|
65
|
+
* A factory running synchronously right now.
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
export interface RunningFactory {
|
|
70
|
+
readonly scope: object;
|
|
71
|
+
readonly token: unknown;
|
|
72
|
+
readonly registration: Registration;
|
|
73
|
+
/** The singleton cache of the container the scope belongs to. */
|
|
74
|
+
readonly singletons: object;
|
|
75
|
+
readonly context: unknown;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Factories running synchronously right now, innermost last, across every scope and module copy.
|
|
79
|
+
*
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
export declare const constructing: RunningFactory[];
|
|
83
|
+
/**
|
|
84
|
+
* Internal state of a Scope.
|
|
85
|
+
*
|
|
86
|
+
* `resolveInternal` resolves without the policy return check: the value stays inside the
|
|
87
|
+
* face that asked for it. The operations face uses it to obtain the callable it never hands out.
|
|
88
|
+
*
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
export interface ScopeInternals extends ContainerInternals {
|
|
92
|
+
readonly kind: 'scope';
|
|
93
|
+
resolveInternal(token: unknown): unknown;
|
|
94
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
declare const KEY: unique symbol;
|
|
2
|
+
declare const ENTRY: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* A typed metadata key. Call it with a value to create a metadata entry for a registration.
|
|
5
|
+
*
|
|
6
|
+
* The name is used by type checking; runtime lookups use the key object's identity.
|
|
7
|
+
*/
|
|
8
|
+
export interface MetadataKey<T, Name extends PropertyKey = PropertyKey> {
|
|
9
|
+
(value: T): MetadataEntry<T, Name>;
|
|
10
|
+
readonly name: Name;
|
|
11
|
+
readonly [KEY]: true;
|
|
12
|
+
}
|
|
13
|
+
export interface MetadataEntry<T = unknown, Name extends PropertyKey = PropertyKey> {
|
|
14
|
+
readonly key: MetadataKey<T, Name>;
|
|
15
|
+
readonly value: T;
|
|
16
|
+
readonly [ENTRY]: true;
|
|
17
|
+
}
|
|
18
|
+
export interface AnyMetadataKey {
|
|
19
|
+
readonly name: PropertyKey;
|
|
20
|
+
readonly [KEY]: true;
|
|
21
|
+
}
|
|
22
|
+
export interface AnyMetadataEntry {
|
|
23
|
+
readonly key: AnyMetadataKey;
|
|
24
|
+
readonly value: unknown;
|
|
25
|
+
readonly [ENTRY]: true;
|
|
26
|
+
}
|
|
27
|
+
export type MetadataKeyOf<E> = E extends MetadataEntry<infer T, infer N> ? MetadataKey<T, N> : never;
|
|
28
|
+
/**
|
|
29
|
+
* Define a typed metadata key.
|
|
30
|
+
*
|
|
31
|
+
* The value type is given first and the name is inferred in a second call, so keys with different
|
|
32
|
+
* names are never confused.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const AREA = createMetadataKey<'internal' | 'public'>()('area');
|
|
37
|
+
* container.registerScoped('read', factory, { metadata: [AREA('public')] });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function createMetadataKey<T>(): <const Name extends PropertyKey>(name: Name) => MetadataKey<T, Name>;
|
|
41
|
+
export interface MetadataReader {
|
|
42
|
+
get<T>(key: MetadataKey<T>): T | undefined;
|
|
43
|
+
require<T>(key: MetadataKey<T>): T;
|
|
44
|
+
has(key: AnyMetadataKey): boolean;
|
|
45
|
+
}
|
|
46
|
+
/** Registration metadata as a key/value pair, so origins can be compared by content. */
|
|
47
|
+
export type MetadataPair = readonly [key: AnyMetadataKey, value: unknown];
|
|
48
|
+
/** A reader and the key/value pairs for the same registration metadata, built from one copy. */
|
|
49
|
+
export interface RegisteredMetadata {
|
|
50
|
+
readonly reader: MetadataReader;
|
|
51
|
+
readonly pairs: readonly MetadataPair[];
|
|
52
|
+
}
|
|
53
|
+
/** Copy the metadata at registration, so later changes to the array or entries do not affect checks. */
|
|
54
|
+
export declare function readMetadata(entries: readonly AnyMetadataEntry[], required: readonly AnyMetadataKey[]): RegisteredMetadata;
|
|
55
|
+
export declare function validateMetadataKeys(keys: readonly AnyMetadataKey[]): void;
|
|
56
|
+
export type RegistrationArguments<Required extends readonly AnyMetadataKey[], Entries extends readonly AnyMetadataEntry[]> = Required extends readonly [] ? [options?: {
|
|
57
|
+
readonly metadata?: Entries;
|
|
58
|
+
}] : [
|
|
59
|
+
options: {
|
|
60
|
+
readonly metadata: Entries;
|
|
61
|
+
} & ([Exclude<Required[number], MetadataKeyOf<Entries[number]>>] extends [
|
|
62
|
+
never
|
|
63
|
+
] ? unknown : {
|
|
64
|
+
readonly missingRequiredMetadata: never;
|
|
65
|
+
})
|
|
66
|
+
];
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
declare const KEY: unique symbol;
|
|
2
|
+
declare const ENTRY: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* A typed metadata key. Call it with a value to create a metadata entry for a registration.
|
|
5
|
+
*
|
|
6
|
+
* The name is used by type checking; runtime lookups use the key object's identity.
|
|
7
|
+
*/
|
|
8
|
+
export interface MetadataKey<T, Name extends PropertyKey = PropertyKey> {
|
|
9
|
+
(value: T): MetadataEntry<T, Name>;
|
|
10
|
+
readonly name: Name;
|
|
11
|
+
readonly [KEY]: true;
|
|
12
|
+
}
|
|
13
|
+
export interface MetadataEntry<T = unknown, Name extends PropertyKey = PropertyKey> {
|
|
14
|
+
readonly key: MetadataKey<T, Name>;
|
|
15
|
+
readonly value: T;
|
|
16
|
+
readonly [ENTRY]: true;
|
|
17
|
+
}
|
|
18
|
+
export interface AnyMetadataKey {
|
|
19
|
+
readonly name: PropertyKey;
|
|
20
|
+
readonly [KEY]: true;
|
|
21
|
+
}
|
|
22
|
+
export interface AnyMetadataEntry {
|
|
23
|
+
readonly key: AnyMetadataKey;
|
|
24
|
+
readonly value: unknown;
|
|
25
|
+
readonly [ENTRY]: true;
|
|
26
|
+
}
|
|
27
|
+
export type MetadataKeyOf<E> = E extends MetadataEntry<infer T, infer N> ? MetadataKey<T, N> : never;
|
|
28
|
+
/**
|
|
29
|
+
* Define a typed metadata key.
|
|
30
|
+
*
|
|
31
|
+
* The value type is given first and the name is inferred in a second call, so keys with different
|
|
32
|
+
* names are never confused.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const AREA = createMetadataKey<'internal' | 'public'>()('area');
|
|
37
|
+
* container.registerScoped('read', factory, { metadata: [AREA('public')] });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function createMetadataKey<T>(): <const Name extends PropertyKey>(name: Name) => MetadataKey<T, Name>;
|
|
41
|
+
export interface MetadataReader {
|
|
42
|
+
get<T>(key: MetadataKey<T>): T | undefined;
|
|
43
|
+
require<T>(key: MetadataKey<T>): T;
|
|
44
|
+
has(key: AnyMetadataKey): boolean;
|
|
45
|
+
}
|
|
46
|
+
/** Registration metadata as a key/value pair, so origins can be compared by content. */
|
|
47
|
+
export type MetadataPair = readonly [key: AnyMetadataKey, value: unknown];
|
|
48
|
+
/** A reader and the key/value pairs for the same registration metadata, built from one copy. */
|
|
49
|
+
export interface RegisteredMetadata {
|
|
50
|
+
readonly reader: MetadataReader;
|
|
51
|
+
readonly pairs: readonly MetadataPair[];
|
|
52
|
+
}
|
|
53
|
+
/** Copy the metadata at registration, so later changes to the array or entries do not affect checks. */
|
|
54
|
+
export declare function readMetadata(entries: readonly AnyMetadataEntry[], required: readonly AnyMetadataKey[]): RegisteredMetadata;
|
|
55
|
+
export declare function validateMetadataKeys(keys: readonly AnyMetadataKey[]): void;
|
|
56
|
+
export type RegistrationArguments<Required extends readonly AnyMetadataKey[], Entries extends readonly AnyMetadataEntry[]> = Required extends readonly [] ? [options?: {
|
|
57
|
+
readonly metadata?: Entries;
|
|
58
|
+
}] : [
|
|
59
|
+
options: {
|
|
60
|
+
readonly metadata: Entries;
|
|
61
|
+
} & ([Exclude<Required[number], MetadataKeyOf<Entries[number]>>] extends [
|
|
62
|
+
never
|
|
63
|
+
] ? unknown : {
|
|
64
|
+
readonly missingRequiredMetadata: never;
|
|
65
|
+
})
|
|
66
|
+
];
|
|
67
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MetadataPair, MetadataReader } from '../metadata/index.cjs';
|
|
1
2
|
export type AbstractConstructor<T = unknown> = abstract new (...args: never[]) => T;
|
|
2
3
|
/**
|
|
3
4
|
* Resolver passed to factory callbacks.
|
|
@@ -64,6 +65,10 @@ export type Lifetime = 'singleton' | 'transient' | 'scoped';
|
|
|
64
65
|
* Factory registration entry.
|
|
65
66
|
*/
|
|
66
67
|
export interface Registration {
|
|
68
|
+
readonly metadata: MetadataReader;
|
|
69
|
+
/** The same metadata as key/value pairs, so origins can be compared by content. */
|
|
70
|
+
readonly metadataPairs: readonly MetadataPair[];
|
|
71
|
+
readonly entrypoint: boolean;
|
|
67
72
|
/**
|
|
68
73
|
* Factory function.
|
|
69
74
|
*
|
package/dist/resolver/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MetadataPair, MetadataReader } from '../metadata/index.js';
|
|
1
2
|
export type AbstractConstructor<T = unknown> = abstract new (...args: never[]) => T;
|
|
2
3
|
/**
|
|
3
4
|
* Resolver passed to factory callbacks.
|
|
@@ -64,6 +65,10 @@ export type Lifetime = 'singleton' | 'transient' | 'scoped';
|
|
|
64
65
|
* Factory registration entry.
|
|
65
66
|
*/
|
|
66
67
|
export interface Registration {
|
|
68
|
+
readonly metadata: MetadataReader;
|
|
69
|
+
/** The same metadata as key/value pairs, so origins can be compared by content. */
|
|
70
|
+
readonly metadataPairs: readonly MetadataPair[];
|
|
71
|
+
readonly entrypoint: boolean;
|
|
67
72
|
/**
|
|
68
73
|
* Factory function.
|
|
69
74
|
*
|
package/dist/scope/index.d.cts
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import type { Container } from '../container/index.cjs';
|
|
2
|
+
import { type PolicyState } from '../container/policy.cjs';
|
|
2
3
|
import type { DisposableContainer, DisposableScope } from '../disposable/index.cjs';
|
|
3
|
-
import
|
|
4
|
-
import type
|
|
4
|
+
import type { REGISTRATION_STATE } from '../internal.cjs';
|
|
5
|
+
import { type ContainerInternals, INTERNALS, type ScopeInternals } from '../internal.cjs';
|
|
6
|
+
import type { AnyMetadataKey, MetadataReader } from '../metadata/index.cjs';
|
|
7
|
+
import type { AbstractConstructor, Lifetime, Registration } from '../resolver/index.cjs';
|
|
8
|
+
import { type OperationsScope, type OperationsScopeOptions } from './operations.cjs';
|
|
9
|
+
export interface RegistrationDescription {
|
|
10
|
+
readonly token: unknown;
|
|
11
|
+
readonly lifetime: Lifetime;
|
|
12
|
+
readonly metadata: MetadataReader;
|
|
13
|
+
readonly entrypoint: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ResolutionEvent extends RegistrationDescription {
|
|
16
|
+
readonly requester: RegistrationDescription | undefined;
|
|
17
|
+
readonly path: readonly unknown[];
|
|
18
|
+
}
|
|
19
|
+
export type BeforeResolve = (event: ResolutionEvent) => void;
|
|
20
|
+
export interface ScopeOptions {
|
|
21
|
+
readonly access?: never;
|
|
22
|
+
readonly beforeResolve?: BeforeResolve;
|
|
23
|
+
}
|
|
5
24
|
/**
|
|
6
25
|
* Create a new scope (child container) from a Container, Scope, or their disposable variants.
|
|
7
26
|
*
|
|
@@ -12,10 +31,14 @@ import type { AbstractConstructor, Registration } from '../resolver/index.cjs';
|
|
|
12
31
|
* @returns A new Scope instance
|
|
13
32
|
* @throws ContainerError if the source has been disposed
|
|
14
33
|
*/
|
|
15
|
-
export declare function createScope<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
export declare function createScope<C extends {
|
|
35
|
+
readonly [INTERNALS]: ContainerInternals;
|
|
36
|
+
readonly [REGISTRATION_STATE]: unknown;
|
|
37
|
+
}>(source: C, options: OperationsScopeOptions): OperationsScope<C[typeof REGISTRATION_STATE]>;
|
|
38
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Required extends readonly AnyMetadataKey[], Registrations>(source: Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Required, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
39
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Registrations>(source: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
40
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Required extends readonly AnyMetadataKey[], Registrations>(source: DisposableContainer<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Required, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
41
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Registrations>(source: DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
19
42
|
/**
|
|
20
43
|
* Scoped child container.
|
|
21
44
|
*
|
|
@@ -30,20 +53,21 @@ export declare function createScope<T, Sync extends AbstractConstructor, Async e
|
|
|
30
53
|
* @template ScopedSync Union of scoped sync class constructors
|
|
31
54
|
* @template ScopedAsync Union of scoped async class constructors
|
|
32
55
|
*/
|
|
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> {
|
|
56
|
+
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, Registrations = unknown> {
|
|
34
57
|
private readonly registrations;
|
|
35
58
|
private readonly singletonCache;
|
|
36
59
|
private readonly scopedCache;
|
|
37
|
-
private readonly
|
|
38
|
-
private
|
|
60
|
+
private readonly beforeResolve;
|
|
61
|
+
private readonly policy;
|
|
39
62
|
private disposed;
|
|
40
63
|
/**
|
|
41
64
|
* Internal state accessor for extension modules (scope, disposable).
|
|
42
65
|
*
|
|
43
66
|
* @internal
|
|
44
67
|
*/
|
|
45
|
-
readonly [
|
|
46
|
-
|
|
68
|
+
readonly [REGISTRATION_STATE]: Registrations;
|
|
69
|
+
readonly [INTERNALS]: ScopeInternals;
|
|
70
|
+
constructor(registrations: Map<unknown, Registration[]>, singletonCache: Map<Registration, unknown>, beforeResolve?: readonly BeforeResolve[], policy?: PolicyState);
|
|
47
71
|
/**
|
|
48
72
|
* Resolve an instance for the given token.
|
|
49
73
|
*
|
|
@@ -99,22 +123,23 @@ export declare class Scope<T = Record<never, never>, Sync extends AbstractConstr
|
|
|
99
123
|
tryResolveAll<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K][] | undefined;
|
|
100
124
|
tryResolveAll<V>(token: AbstractConstructor<V>): (V | Promise<V>)[] | undefined;
|
|
101
125
|
tryResolveAll(token: PropertyKey): unknown;
|
|
126
|
+
/** The context of a call through a public method: the running factory's, or the outside of this scope. */
|
|
127
|
+
private entry;
|
|
128
|
+
private describe;
|
|
129
|
+
private check;
|
|
130
|
+
private lookup;
|
|
131
|
+
/** Create a value that may leave this scope; a synchronous value passes the policy's return check here. */
|
|
132
|
+
private create;
|
|
102
133
|
/**
|
|
103
|
-
*
|
|
104
|
-
* Resolves the last registered factory for the token.
|
|
134
|
+
* Shape a created value for the caller.
|
|
105
135
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
136
|
+
* The return check runs on every resolution, so under a policy with a return check, an asynchronous
|
|
137
|
+
* creation leaving the scope is handed out as a per-call Promise that checks the resolved value. No
|
|
138
|
+
* listener is attached to a Promise already handed out. The per-call Promise is built only after every
|
|
139
|
+
* synchronous failure is ruled out, so no Promise is left without a receiver.
|
|
109
140
|
*/
|
|
141
|
+
private handOut;
|
|
110
142
|
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
143
|
private resolveAllTokens;
|
|
144
|
+
private instantiate;
|
|
120
145
|
}
|
package/dist/scope/index.d.ts
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import type { Container } from '../container/index.js';
|
|
2
|
+
import { type PolicyState } from '../container/policy.js';
|
|
2
3
|
import type { DisposableContainer, DisposableScope } from '../disposable/index.js';
|
|
3
|
-
import
|
|
4
|
-
import type
|
|
4
|
+
import type { REGISTRATION_STATE } from '../internal.js';
|
|
5
|
+
import { type ContainerInternals, INTERNALS, type ScopeInternals } from '../internal.js';
|
|
6
|
+
import type { AnyMetadataKey, MetadataReader } from '../metadata/index.js';
|
|
7
|
+
import type { AbstractConstructor, Lifetime, Registration } from '../resolver/index.js';
|
|
8
|
+
import { type OperationsScope, type OperationsScopeOptions } from './operations.js';
|
|
9
|
+
export interface RegistrationDescription {
|
|
10
|
+
readonly token: unknown;
|
|
11
|
+
readonly lifetime: Lifetime;
|
|
12
|
+
readonly metadata: MetadataReader;
|
|
13
|
+
readonly entrypoint: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ResolutionEvent extends RegistrationDescription {
|
|
16
|
+
readonly requester: RegistrationDescription | undefined;
|
|
17
|
+
readonly path: readonly unknown[];
|
|
18
|
+
}
|
|
19
|
+
export type BeforeResolve = (event: ResolutionEvent) => void;
|
|
20
|
+
export interface ScopeOptions {
|
|
21
|
+
readonly access?: never;
|
|
22
|
+
readonly beforeResolve?: BeforeResolve;
|
|
23
|
+
}
|
|
5
24
|
/**
|
|
6
25
|
* Create a new scope (child container) from a Container, Scope, or their disposable variants.
|
|
7
26
|
*
|
|
@@ -12,10 +31,14 @@ import type { AbstractConstructor, Registration } from '../resolver/index.js';
|
|
|
12
31
|
* @returns A new Scope instance
|
|
13
32
|
* @throws ContainerError if the source has been disposed
|
|
14
33
|
*/
|
|
15
|
-
export declare function createScope<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
export declare function createScope<C extends {
|
|
35
|
+
readonly [INTERNALS]: ContainerInternals;
|
|
36
|
+
readonly [REGISTRATION_STATE]: unknown;
|
|
37
|
+
}>(source: C, options: OperationsScopeOptions): OperationsScope<C[typeof REGISTRATION_STATE]>;
|
|
38
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Required extends readonly AnyMetadataKey[], Registrations>(source: Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Required, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
39
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Registrations>(source: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
40
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Required extends readonly AnyMetadataKey[], Registrations>(source: DisposableContainer<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Required, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
41
|
+
export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, Registrations>(source: DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>, options?: ScopeOptions): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync, Registrations>;
|
|
19
42
|
/**
|
|
20
43
|
* Scoped child container.
|
|
21
44
|
*
|
|
@@ -30,20 +53,21 @@ export declare function createScope<T, Sync extends AbstractConstructor, Async e
|
|
|
30
53
|
* @template ScopedSync Union of scoped sync class constructors
|
|
31
54
|
* @template ScopedAsync Union of scoped async class constructors
|
|
32
55
|
*/
|
|
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> {
|
|
56
|
+
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, Registrations = unknown> {
|
|
34
57
|
private readonly registrations;
|
|
35
58
|
private readonly singletonCache;
|
|
36
59
|
private readonly scopedCache;
|
|
37
|
-
private readonly
|
|
38
|
-
private
|
|
60
|
+
private readonly beforeResolve;
|
|
61
|
+
private readonly policy;
|
|
39
62
|
private disposed;
|
|
40
63
|
/**
|
|
41
64
|
* Internal state accessor for extension modules (scope, disposable).
|
|
42
65
|
*
|
|
43
66
|
* @internal
|
|
44
67
|
*/
|
|
45
|
-
readonly [
|
|
46
|
-
|
|
68
|
+
readonly [REGISTRATION_STATE]: Registrations;
|
|
69
|
+
readonly [INTERNALS]: ScopeInternals;
|
|
70
|
+
constructor(registrations: Map<unknown, Registration[]>, singletonCache: Map<Registration, unknown>, beforeResolve?: readonly BeforeResolve[], policy?: PolicyState);
|
|
47
71
|
/**
|
|
48
72
|
* Resolve an instance for the given token.
|
|
49
73
|
*
|
|
@@ -99,22 +123,23 @@ export declare class Scope<T = Record<never, never>, Sync extends AbstractConstr
|
|
|
99
123
|
tryResolveAll<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K][] | undefined;
|
|
100
124
|
tryResolveAll<V>(token: AbstractConstructor<V>): (V | Promise<V>)[] | undefined;
|
|
101
125
|
tryResolveAll(token: PropertyKey): unknown;
|
|
126
|
+
/** The context of a call through a public method: the running factory's, or the outside of this scope. */
|
|
127
|
+
private entry;
|
|
128
|
+
private describe;
|
|
129
|
+
private check;
|
|
130
|
+
private lookup;
|
|
131
|
+
/** Create a value that may leave this scope; a synchronous value passes the policy's return check here. */
|
|
132
|
+
private create;
|
|
102
133
|
/**
|
|
103
|
-
*
|
|
104
|
-
* Resolves the last registered factory for the token.
|
|
134
|
+
* Shape a created value for the caller.
|
|
105
135
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
136
|
+
* The return check runs on every resolution, so under a policy with a return check, an asynchronous
|
|
137
|
+
* creation leaving the scope is handed out as a per-call Promise that checks the resolved value. No
|
|
138
|
+
* listener is attached to a Promise already handed out. The per-call Promise is built only after every
|
|
139
|
+
* synchronous failure is ruled out, so no Promise is left without a receiver.
|
|
109
140
|
*/
|
|
141
|
+
private handOut;
|
|
110
142
|
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
143
|
private resolveAllTokens;
|
|
144
|
+
private instantiate;
|
|
120
145
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Callable } from '../entrypoint/index.cjs';
|
|
2
|
+
import type { Scope, ScopeOptions } from './index.cjs';
|
|
3
|
+
type PublicState<S> = S extends {
|
|
4
|
+
readonly callable: infer F;
|
|
5
|
+
} ? ([F] extends [never] ? never : S) : never;
|
|
6
|
+
type Token<S> = PublicState<S> extends infer P ? (P extends {
|
|
7
|
+
readonly token: infer K;
|
|
8
|
+
} ? K : never) : never;
|
|
9
|
+
type Operation<S, K> = Extract<PublicState<S>, {
|
|
10
|
+
readonly token: K;
|
|
11
|
+
}> extends {
|
|
12
|
+
readonly callable: infer F extends Callable;
|
|
13
|
+
} ? F : never;
|
|
14
|
+
export interface OperationsScopeOptions extends Omit<ScopeOptions, 'access'> {
|
|
15
|
+
readonly access: 'operations';
|
|
16
|
+
}
|
|
17
|
+
export interface OperationsScope<Registrations> extends AsyncDisposable {
|
|
18
|
+
get<K extends Token<Registrations>>(token: K): (...args: Parameters<Operation<Registrations, K>>) => Promise<Awaited<ReturnType<Operation<Registrations, K>>>>;
|
|
19
|
+
}
|
|
20
|
+
/** Build an operations scope: keep the resolver inside, and stop new calls and wait for running ones in one place. */
|
|
21
|
+
export declare function operations<Registrations>(source: Scope): OperationsScope<Registrations>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Callable } from '../entrypoint/index.js';
|
|
2
|
+
import type { Scope, ScopeOptions } from './index.js';
|
|
3
|
+
type PublicState<S> = S extends {
|
|
4
|
+
readonly callable: infer F;
|
|
5
|
+
} ? ([F] extends [never] ? never : S) : never;
|
|
6
|
+
type Token<S> = PublicState<S> extends infer P ? (P extends {
|
|
7
|
+
readonly token: infer K;
|
|
8
|
+
} ? K : never) : never;
|
|
9
|
+
type Operation<S, K> = Extract<PublicState<S>, {
|
|
10
|
+
readonly token: K;
|
|
11
|
+
}> extends {
|
|
12
|
+
readonly callable: infer F extends Callable;
|
|
13
|
+
} ? F : never;
|
|
14
|
+
export interface OperationsScopeOptions extends Omit<ScopeOptions, 'access'> {
|
|
15
|
+
readonly access: 'operations';
|
|
16
|
+
}
|
|
17
|
+
export interface OperationsScope<Registrations> extends AsyncDisposable {
|
|
18
|
+
get<K extends Token<Registrations>>(token: K): (...args: Parameters<Operation<Registrations, K>>) => Promise<Awaited<ReturnType<Operation<Registrations, K>>>>;
|
|
19
|
+
}
|
|
20
|
+
/** Build an operations scope: keep the resolver inside, and stop new calls and wait for running ones in one place. */
|
|
21
|
+
export declare function operations<Registrations>(source: Scope): OperationsScope<Registrations>;
|
|
22
|
+
export {};
|
package/docs/README.de.md
CHANGED
|
@@ -29,11 +29,11 @@ console.log(greeting);
|
|
|
29
29
|
|
|
30
30
|
Katagami verbindet **aus Registrierungen abgeleitete Typen, Scope-Prüfungen zur Compile-Zeit und keine Laufzeitabhängigkeiten** mit gewöhnlichen TypeScript-Factories. Decorators und Metadaten sind nicht nötig. Ressourcenfreigabe und Lazy Resolution haben eigene Einstiegspunkte.
|
|
31
31
|
|
|
32
|
-
**Geprüft am 2026-09-11**, anhand stabiler npm-Versionen und offizieller Quellen. Siehe [Versionen und Quellen](./choosing-di.md#comparison-sources) sowie den [vollständigen Vergleich mit Async-Verhalten und Ressourcenfreigabe](../README.md#library-comparison).
|
|
32
|
+
**Geprüft am 2026-09-11**, anhand stabiler npm-Versionen und offizieller Quellen. Die Katagami-Angaben beschreiben diese Version (4.0.0). Siehe [Versionen und Quellen](./choosing-di.md#comparison-sources) sowie den [vollständigen Vergleich mit Async-Verhalten und Ressourcenfreigabe](../README.md#library-comparison).
|
|
33
33
|
|
|
34
34
|
| Bibliothek / Version | Abhängigkeitstypen und Registrierungsprüfung | Scope-Verhalten |
|
|
35
35
|
| --- | --- | --- |
|
|
36
|
-
| **Katagami
|
|
36
|
+
| **Katagami 4.0.0** | **Sammelt Literal-/unique-symbol-Tokens; fehlende erforderliche Tokens sind Typfehler** | **Scoped-Tokens im Resolver von Singleton-/Transient-Factories ausgeschlossen** |
|
|
37
37
|
| InversifyJS 8.2.3 | Typisierte Bindings; Existenzprüfung zur Laufzeit | Konfigurierte Binding-Lebensdauer |
|
|
38
38
|
| tsyringe 4.10.0 | Klassen-/generische Typen; Registrierungsprüfung zur Laufzeit | Lebensdauer und Kindcontainer |
|
|
39
39
|
| TypeDI 0.10.0 | Klassen und `Token<T>`; Registrierungsprüfung zur Laufzeit | Geteilte/Transient-Services, benannte Container |
|
|
@@ -74,6 +74,7 @@ Unterstützt Singleton, Transient und Scoped, Modulkomposition mit use(), asynch
|
|
|
74
74
|
- [Anleitung für KI-Agenten (Englisch)](./ai-coding-agents.md)
|
|
75
75
|
- [Typgarantien (Englisch)](./type-safety.md)
|
|
76
76
|
- [API und Anwendung (Englisch)](./guide.md)
|
|
77
|
+
- [Registrierungsrichtlinien und Operationen (Englisch)](./registration-policies.md)
|
|
77
78
|
- [Starter für Anfrage-Scopes (Englisch)](../examples/request-scope/README.md)
|
|
78
79
|
- [DI auswählen (Englisch)](./choosing-di.md)
|
|
79
80
|
|