@frontmcp/di 0.0.1 → 0.7.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.
- package/decorators/async-with.decorator.d.ts +43 -0
- package/decorators/index.d.ts +4 -0
- package/esm/index.mjs +1173 -0
- package/esm/package.json +59 -0
- package/index.d.ts +18 -0
- package/index.js +1225 -0
- package/interfaces/base.interface.d.ts +119 -0
- package/interfaces/index.d.ts +6 -0
- package/interfaces/provider.interface.d.ts +57 -0
- package/interfaces/registry.interface.d.ts +66 -0
- package/metadata/index.d.ts +5 -0
- package/metadata/provider.metadata.d.ts +47 -0
- package/metadata/provider.schema.d.ts +32 -0
- package/package.json +1 -1
- package/records/index.d.ts +4 -0
- package/records/provider.record.d.ts +73 -0
- package/registry/container.d.ts +155 -0
- package/registry/index.d.ts +8 -0
- package/registry/indexed.registry.d.ts +140 -0
- package/registry/indexed.types.d.ts +87 -0
- package/registry/registry.base.d.ts +85 -0
- package/registry/simple.registry.d.ts +28 -0
- package/tokens/di.constants.d.ts +22 -0
- package/tokens/index.d.ts +9 -0
- package/tokens/token.factory.d.ts +55 -0
- package/utils/index.d.ts +6 -0
- package/utils/metadata.utils.d.ts +37 -0
- package/utils/provider.utils.d.ts +79 -0
- package/utils/token.utils.d.ts +74 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for registries with indexed lookups.
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - O(1) lookups by qualified ID, name, owner
|
|
6
|
+
* - Child registry adoption with live subscriptions
|
|
7
|
+
* - Lineage management for tracking ownership
|
|
8
|
+
* - Change event emission for subscribers
|
|
9
|
+
*
|
|
10
|
+
* Extended by ToolRegistry, ResourceRegistry, PromptRegistry, AgentRegistry.
|
|
11
|
+
*/
|
|
12
|
+
import type { Token } from '../interfaces/base.interface.js';
|
|
13
|
+
import { RegistryAbstract, type RegistryKind } from './registry.base.js';
|
|
14
|
+
import type { IndexedEntry, EntryLineage, EntryOwnerRef, ChangeEvent, ChangeKind, SubscribeOptions, RegistryEmitter } from './indexed.types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Abstract base class for registries with indexed lookups.
|
|
17
|
+
*
|
|
18
|
+
* @typeParam TInstance - Type of registry entry instances
|
|
19
|
+
* @typeParam TRecord - Type of registry records
|
|
20
|
+
* @typeParam TIndexed - Type of indexed entries (extends IndexedEntry)
|
|
21
|
+
* @typeParam TMetadata - Type of initialization metadata
|
|
22
|
+
* @typeParam TProviders - Type of parent provider registry
|
|
23
|
+
*/
|
|
24
|
+
export declare abstract class IndexedRegistry<TInstance, TRecord, TIndexed extends IndexedEntry<TInstance>, TMetadata, TProviders = unknown> extends RegistryAbstract<TInstance, TRecord, TMetadata, TProviders> {
|
|
25
|
+
/** Entries created by this registry */
|
|
26
|
+
protected localRows: TIndexed[];
|
|
27
|
+
/** Entries adopted from child registries */
|
|
28
|
+
protected adopted: Map<IndexedRegistry<TInstance, TRecord, TIndexed, any, any>, TIndexed[]>;
|
|
29
|
+
/** Set of child registries */
|
|
30
|
+
protected children: Set<IndexedRegistry<TInstance, TRecord, TIndexed, any, any>>;
|
|
31
|
+
/** Unsubscribe functions for child subscriptions */
|
|
32
|
+
protected childSubscriptions: Map<IndexedRegistry<TInstance, TRecord, TIndexed, any, any>, () => void>;
|
|
33
|
+
/** O(1) lookup by qualified ID */
|
|
34
|
+
protected byQualifiedId: Map<string, TIndexed>;
|
|
35
|
+
/** O(1) lookup by base name (array for conflicts) */
|
|
36
|
+
protected byName: Map<string, TIndexed[]>;
|
|
37
|
+
/** O(1) lookup by owner key */
|
|
38
|
+
protected byOwner: Map<string, TIndexed[]>;
|
|
39
|
+
/** O(1) lookup by owner:name composite */
|
|
40
|
+
protected byOwnerAndName: Map<string, TIndexed>;
|
|
41
|
+
/** Version counter for change tracking */
|
|
42
|
+
protected version: number;
|
|
43
|
+
/** Event emitter for change notifications */
|
|
44
|
+
protected emitter: RegistryEmitter<ChangeEvent<TIndexed>>;
|
|
45
|
+
/**
|
|
46
|
+
* Create an event emitter for this registry.
|
|
47
|
+
* Override to use custom emitter implementation.
|
|
48
|
+
*/
|
|
49
|
+
protected createEmitter(): RegistryEmitter<ChangeEvent<TIndexed>>;
|
|
50
|
+
protected constructor(name: RegistryKind, providers: TProviders, metadata: TMetadata, auto?: boolean);
|
|
51
|
+
/**
|
|
52
|
+
* Build additional indexes from rows.
|
|
53
|
+
* Called during reindex to populate custom indexes.
|
|
54
|
+
*
|
|
55
|
+
* @param rows - All indexed entries (local + adopted)
|
|
56
|
+
*/
|
|
57
|
+
protected abstract buildIndexes(rows: TIndexed[]): void;
|
|
58
|
+
/**
|
|
59
|
+
* Create an indexed entry from a record.
|
|
60
|
+
* Called during initialization to wrap records.
|
|
61
|
+
*
|
|
62
|
+
* @param token - Entry token
|
|
63
|
+
* @param record - Entry record
|
|
64
|
+
* @param instance - Instantiated entry
|
|
65
|
+
* @returns Indexed entry wrapper
|
|
66
|
+
*/
|
|
67
|
+
protected abstract makeRow(token: Token, record: TRecord, instance: TInstance): TIndexed;
|
|
68
|
+
/**
|
|
69
|
+
* Adopt entries from a child registry.
|
|
70
|
+
*
|
|
71
|
+
* @param child - Child registry to adopt from
|
|
72
|
+
* @param childOwner - Owner reference for lineage
|
|
73
|
+
*/
|
|
74
|
+
adoptFromChild(child: IndexedRegistry<TInstance, TRecord, TIndexed, any, any>, childOwner: EntryOwnerRef): void;
|
|
75
|
+
/**
|
|
76
|
+
* Remove a child registry.
|
|
77
|
+
*/
|
|
78
|
+
removeChild(child: IndexedRegistry<TInstance, TRecord, TIndexed, any, any>): void;
|
|
79
|
+
/**
|
|
80
|
+
* Relineage an entry with a new prefix.
|
|
81
|
+
* Creates a new indexed entry with updated lineage.
|
|
82
|
+
*/
|
|
83
|
+
protected relineage(row: TIndexed, prepend: EntryLineage): TIndexed;
|
|
84
|
+
/**
|
|
85
|
+
* Remove adjacent duplicate segments from lineage.
|
|
86
|
+
*/
|
|
87
|
+
protected dedupLineage(lineage: EntryLineage): EntryLineage;
|
|
88
|
+
/**
|
|
89
|
+
* Generate owner key from lineage.
|
|
90
|
+
*/
|
|
91
|
+
protected ownerKeyOf(lineage: EntryLineage): string;
|
|
92
|
+
/**
|
|
93
|
+
* Generate qualified name from base name and lineage.
|
|
94
|
+
*/
|
|
95
|
+
protected qualifiedNameOf(baseName: string, lineage: EntryLineage): string;
|
|
96
|
+
/**
|
|
97
|
+
* Rebuild all indexes from local and adopted entries.
|
|
98
|
+
*/
|
|
99
|
+
protected reindex(): void;
|
|
100
|
+
/**
|
|
101
|
+
* Subscribe to change events.
|
|
102
|
+
*/
|
|
103
|
+
subscribe(opts: SubscribeOptions<TInstance>, callback: (event: ChangeEvent<TIndexed>) => void): () => void;
|
|
104
|
+
/**
|
|
105
|
+
* Emit a change event.
|
|
106
|
+
*/
|
|
107
|
+
protected bump(kind: ChangeKind): void;
|
|
108
|
+
/**
|
|
109
|
+
* Find by base name (returns first match).
|
|
110
|
+
*/
|
|
111
|
+
findByName(name: string): TInstance | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Find all by base name.
|
|
114
|
+
*/
|
|
115
|
+
findAllByName(name: string): TInstance[];
|
|
116
|
+
/**
|
|
117
|
+
* Find by qualified ID.
|
|
118
|
+
*/
|
|
119
|
+
findByQualifiedId(qualifiedId: string): TInstance | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* List all indexed entries by owner.
|
|
122
|
+
*/
|
|
123
|
+
listByOwner(ownerKey: string): TIndexed[];
|
|
124
|
+
/**
|
|
125
|
+
* List all indexed entries.
|
|
126
|
+
*/
|
|
127
|
+
listAllIndexed(): TIndexed[];
|
|
128
|
+
/**
|
|
129
|
+
* List all instances.
|
|
130
|
+
*/
|
|
131
|
+
listAllInstances(): TInstance[];
|
|
132
|
+
/**
|
|
133
|
+
* Check if registry has any entries.
|
|
134
|
+
*/
|
|
135
|
+
hasAny(): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Dispose of this registry and clean up subscriptions.
|
|
138
|
+
*/
|
|
139
|
+
dispose(): void;
|
|
140
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for indexed registries with fast lookups.
|
|
3
|
+
*/
|
|
4
|
+
import type { Token } from '../interfaces/base.interface.js';
|
|
5
|
+
/**
|
|
6
|
+
* Entry lineage segment describing the owner path.
|
|
7
|
+
*/
|
|
8
|
+
export interface LineageSegment {
|
|
9
|
+
/** Type of owner (e.g., 'app', 'plugin', 'scope') */
|
|
10
|
+
type: string;
|
|
11
|
+
/** Identifier for this segment */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Optional name for display purposes */
|
|
14
|
+
name?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Complete lineage path from root to entry.
|
|
18
|
+
*/
|
|
19
|
+
export type EntryLineage = LineageSegment[];
|
|
20
|
+
/**
|
|
21
|
+
* Reference to an entry owner for adoption tracking.
|
|
22
|
+
*/
|
|
23
|
+
export interface EntryOwnerRef {
|
|
24
|
+
/** Lineage path to the owner */
|
|
25
|
+
lineage: EntryLineage;
|
|
26
|
+
/** String key representation of the owner */
|
|
27
|
+
ownerKey: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Base indexed entry interface.
|
|
31
|
+
* Extended by specific registries with additional fields.
|
|
32
|
+
*/
|
|
33
|
+
export interface IndexedEntry<T> {
|
|
34
|
+
/** Token for this entry */
|
|
35
|
+
token: Token;
|
|
36
|
+
/** Instantiated entry */
|
|
37
|
+
instance: T;
|
|
38
|
+
/** Base name without qualification */
|
|
39
|
+
baseName: string;
|
|
40
|
+
/** Full lineage path */
|
|
41
|
+
lineage: EntryLineage;
|
|
42
|
+
/** String key for owner lookup */
|
|
43
|
+
ownerKey: string;
|
|
44
|
+
/** Fully qualified name including owner path */
|
|
45
|
+
qualifiedName: string;
|
|
46
|
+
/** Fully qualified ID for unique lookup */
|
|
47
|
+
qualifiedId: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Change event kinds.
|
|
51
|
+
*/
|
|
52
|
+
export type ChangeKind = 'reset' | 'add' | 'remove' | 'update';
|
|
53
|
+
/**
|
|
54
|
+
* Change event scope.
|
|
55
|
+
*/
|
|
56
|
+
export type ChangeScope = 'local' | 'global';
|
|
57
|
+
/**
|
|
58
|
+
* Base change event for indexed registries.
|
|
59
|
+
*/
|
|
60
|
+
export interface ChangeEvent<TIndexed> {
|
|
61
|
+
/** Type of change */
|
|
62
|
+
kind: ChangeKind;
|
|
63
|
+
/** Scope of the change */
|
|
64
|
+
changeScope: ChangeScope;
|
|
65
|
+
/** Version counter after change */
|
|
66
|
+
version: number;
|
|
67
|
+
/** Current snapshot of all entries */
|
|
68
|
+
snapshot: TIndexed[];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Subscription options for change events.
|
|
72
|
+
*/
|
|
73
|
+
export interface SubscribeOptions<T> {
|
|
74
|
+
/** Emit immediately with current state */
|
|
75
|
+
immediate?: boolean;
|
|
76
|
+
/** Filter function for entries */
|
|
77
|
+
filter?: (instance: T) => boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Event emitter interface for change notifications.
|
|
81
|
+
*/
|
|
82
|
+
export interface RegistryEmitter<TEvent> {
|
|
83
|
+
/** Emit an event to all subscribers */
|
|
84
|
+
emit(event: TEvent): void;
|
|
85
|
+
/** Subscribe to events, returns unsubscribe function */
|
|
86
|
+
on(handler: (event: TEvent) => void): () => void;
|
|
87
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base abstract class for all registries.
|
|
3
|
+
*
|
|
4
|
+
* Provides the core structure for managing tokens, definitions, and
|
|
5
|
+
* dependency graphs. Subclasses implement specific initialization logic.
|
|
6
|
+
*/
|
|
7
|
+
import type { Token } from '../interfaces/base.interface.js';
|
|
8
|
+
/**
|
|
9
|
+
* Result of the buildMap phase containing registry structures.
|
|
10
|
+
*/
|
|
11
|
+
export type RegistryBuildMapResult<Record> = {
|
|
12
|
+
/** All tokens that are provided (graph nodes) */
|
|
13
|
+
tokens: Set<Token>;
|
|
14
|
+
/** Record definition by token */
|
|
15
|
+
defs: Map<Token, Record>;
|
|
16
|
+
/** Dependency graph by token */
|
|
17
|
+
graph: Map<Token, Set<Token>>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Registry kind identifier for categorizing registries.
|
|
21
|
+
*/
|
|
22
|
+
export type RegistryKind = string;
|
|
23
|
+
/**
|
|
24
|
+
* Abstract base class for registries.
|
|
25
|
+
*
|
|
26
|
+
* @typeParam Interface - The interface type for registry entries
|
|
27
|
+
* @typeParam Record - The record type stored in the registry
|
|
28
|
+
* @typeParam MetadataType - The metadata type for initialization
|
|
29
|
+
* @typeParam ProviderRegistryType - Optional parent provider registry type
|
|
30
|
+
*/
|
|
31
|
+
export declare abstract class RegistryAbstract<Interface, Record, MetadataType, ProviderRegistryType = unknown> {
|
|
32
|
+
/** Default timeout for async operations in milliseconds */
|
|
33
|
+
protected asyncTimeoutMs: number;
|
|
34
|
+
/** Promise that resolves when the registry is fully initialized */
|
|
35
|
+
ready: Promise<void>;
|
|
36
|
+
/** Reference to parent provider registry for dependency resolution */
|
|
37
|
+
protected providers: ProviderRegistryType;
|
|
38
|
+
/** Metadata used for initialization */
|
|
39
|
+
protected list: MetadataType;
|
|
40
|
+
/** All tokens that are provided (graph nodes) */
|
|
41
|
+
protected tokens: Set<Token>;
|
|
42
|
+
/** Record definition by token */
|
|
43
|
+
protected defs: Map<Token, Record>;
|
|
44
|
+
/** Dependency graph by token */
|
|
45
|
+
protected graph: Map<Token, Set<Token>>;
|
|
46
|
+
/** Instantiated entries by token */
|
|
47
|
+
protected readonly instances: Map<Token<Interface>, Interface>;
|
|
48
|
+
/**
|
|
49
|
+
* Create a new registry.
|
|
50
|
+
*
|
|
51
|
+
* @param name - Registry kind name for identification
|
|
52
|
+
* @param providers - Parent provider registry
|
|
53
|
+
* @param metadata - Initialization metadata
|
|
54
|
+
* @param auto - Whether to automatically build and initialize
|
|
55
|
+
*/
|
|
56
|
+
protected constructor(name: RegistryKind, providers: ProviderRegistryType, metadata: MetadataType, auto?: boolean);
|
|
57
|
+
/**
|
|
58
|
+
* Build the initial token/record/graph maps from metadata.
|
|
59
|
+
* Called during construction.
|
|
60
|
+
*
|
|
61
|
+
* @param list - Initialization metadata
|
|
62
|
+
* @returns Registry structures
|
|
63
|
+
*/
|
|
64
|
+
protected abstract buildMap(list: MetadataType): RegistryBuildMapResult<Record>;
|
|
65
|
+
/**
|
|
66
|
+
* Build the dependency graph.
|
|
67
|
+
* Called after buildMap to establish dependencies.
|
|
68
|
+
*/
|
|
69
|
+
protected abstract buildGraph(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Initialize the registry by instantiating entries.
|
|
72
|
+
* Called after buildGraph.
|
|
73
|
+
*
|
|
74
|
+
* @returns Promise that resolves when initialization is complete
|
|
75
|
+
*/
|
|
76
|
+
protected abstract initialize(): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Check if the registry has any entries.
|
|
79
|
+
*/
|
|
80
|
+
hasAny(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Get all instances as a readonly map.
|
|
83
|
+
*/
|
|
84
|
+
getAllInstances(): ReadonlyMap<Token<Interface>, Interface>;
|
|
85
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple registry base class without indexed lookups.
|
|
3
|
+
*
|
|
4
|
+
* Used for registries that don't need adoption or complex indexing:
|
|
5
|
+
* - AppRegistry
|
|
6
|
+
* - AuthRegistry
|
|
7
|
+
* - FlowRegistry
|
|
8
|
+
*/
|
|
9
|
+
import { RegistryAbstract, type RegistryKind } from './registry.base.js';
|
|
10
|
+
/**
|
|
11
|
+
* Simple registry without indexed lookups or adoption.
|
|
12
|
+
*
|
|
13
|
+
* @typeParam TInstance - Type of registry entry instances
|
|
14
|
+
* @typeParam TRecord - Type of registry records
|
|
15
|
+
* @typeParam TMetadata - Type of initialization metadata
|
|
16
|
+
* @typeParam TProviders - Type of parent provider registry
|
|
17
|
+
*/
|
|
18
|
+
export declare abstract class SimpleRegistry<TInstance, TRecord, TMetadata, TProviders = unknown> extends RegistryAbstract<TInstance, TRecord, TMetadata, TProviders> {
|
|
19
|
+
protected constructor(name: RegistryKind, providers: TProviders, metadata: TMetadata, auto?: boolean);
|
|
20
|
+
/**
|
|
21
|
+
* Get all entries as an array.
|
|
22
|
+
*/
|
|
23
|
+
getAll(): TInstance[];
|
|
24
|
+
/**
|
|
25
|
+
* Get entry count.
|
|
26
|
+
*/
|
|
27
|
+
count(): number;
|
|
28
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DI-related metadata keys and constants.
|
|
3
|
+
*
|
|
4
|
+
* These symbols are used with reflect-metadata for storing and retrieving
|
|
5
|
+
* dependency injection metadata on classes.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Metadata key for design:paramtypes (TypeScript's emitted constructor parameter types).
|
|
9
|
+
* Used by reflect-metadata to store constructor parameter type information.
|
|
10
|
+
*/
|
|
11
|
+
export declare const DESIGN_PARAMTYPES = "design:paramtypes";
|
|
12
|
+
/**
|
|
13
|
+
* Metadata key indicating a class uses async initialization via static `with()` method.
|
|
14
|
+
* When this metadata is present, the DI container will call the static `with()` method
|
|
15
|
+
* instead of the constructor for instantiation.
|
|
16
|
+
*/
|
|
17
|
+
export declare const META_ASYNC_WITH: unique symbol;
|
|
18
|
+
/**
|
|
19
|
+
* Metadata key for storing the token array used by @AsyncWith decorator.
|
|
20
|
+
* Contains a function that returns the dependency tokens for the static `with()` method.
|
|
21
|
+
*/
|
|
22
|
+
export declare const META_ASYNC_WITH_TOKENS: unique symbol;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token system for dependency injection.
|
|
3
|
+
*
|
|
4
|
+
* This module provides:
|
|
5
|
+
* - Token factory for creating type-safe DI tokens
|
|
6
|
+
* - DI-related metadata constants
|
|
7
|
+
*/
|
|
8
|
+
export { createTokenFactory, DiTokens, type TokenFactory, type TokenFactoryOptions } from './token.factory.js';
|
|
9
|
+
export { DESIGN_PARAMTYPES, META_ASYNC_WITH, META_ASYNC_WITH_TOKENS } from './di.constants.js';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token factory for creating type-safe DI tokens with configurable prefix.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* // Create a factory with custom prefix
|
|
7
|
+
* const tokens = createTokenFactory({ prefix: 'MyApp' });
|
|
8
|
+
*
|
|
9
|
+
* // Create typed tokens
|
|
10
|
+
* const serviceToken = tokens.type('UserService');
|
|
11
|
+
* // => Symbol('MyApp:type:UserService')
|
|
12
|
+
*
|
|
13
|
+
* const metaToken = tokens.meta('config');
|
|
14
|
+
* // => Symbol('MyApp:meta:config')
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export interface TokenFactoryOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Prefix for generated token symbols.
|
|
20
|
+
* @default 'DI'
|
|
21
|
+
*/
|
|
22
|
+
prefix?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface TokenFactory {
|
|
25
|
+
/**
|
|
26
|
+
* Create a type token for a service/provider.
|
|
27
|
+
* @param name - The name of the type
|
|
28
|
+
* @returns A unique symbol for the type
|
|
29
|
+
*/
|
|
30
|
+
type: (name: string) => symbol;
|
|
31
|
+
/**
|
|
32
|
+
* Create a metadata token for storing/retrieving metadata.
|
|
33
|
+
* @param name - The name of the metadata key
|
|
34
|
+
* @returns A unique symbol for the metadata key
|
|
35
|
+
*/
|
|
36
|
+
meta: (name: string) => symbol;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a token factory with the given options.
|
|
40
|
+
*
|
|
41
|
+
* @param options - Factory configuration
|
|
42
|
+
* @returns A token factory instance
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const tokens = createTokenFactory({ prefix: 'FrontMcp' });
|
|
47
|
+
* const userToken = tokens.type('UserService');
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function createTokenFactory(options?: TokenFactoryOptions): TokenFactory;
|
|
51
|
+
/**
|
|
52
|
+
* Default token factory instance with 'DI' prefix.
|
|
53
|
+
* Use this for standalone DI usage without custom branding.
|
|
54
|
+
*/
|
|
55
|
+
export declare const DiTokens: TokenFactory;
|
package/utils/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for dependency injection.
|
|
3
|
+
*/
|
|
4
|
+
export { getMetadata, setMetadata, hasAsyncWith } from './metadata.utils.js';
|
|
5
|
+
export { tokenName, isClass, isPromise, getAsyncWithTokens, readWithParamTypes, depsOfClass, depsOfFunc, } from './token.utils.js';
|
|
6
|
+
export { createProviderNormalizer, providerDiscoveryDeps, providerInvocationTokens, type ProviderTokens, type ProviderNormalizerOptions, } from './provider.utils.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata utilities for dependency injection.
|
|
3
|
+
*
|
|
4
|
+
* These utilities work with reflect-metadata to store and retrieve
|
|
5
|
+
* DI-related metadata on classes.
|
|
6
|
+
*/
|
|
7
|
+
import 'reflect-metadata';
|
|
8
|
+
import type { Type } from '../interfaces/base.interface.js';
|
|
9
|
+
/**
|
|
10
|
+
* Get metadata value from a target.
|
|
11
|
+
*
|
|
12
|
+
* @param key - The metadata key
|
|
13
|
+
* @param target - The target object or class
|
|
14
|
+
* @param propertyKey - Optional property key for method/property metadata
|
|
15
|
+
* @returns The metadata value or undefined
|
|
16
|
+
*/
|
|
17
|
+
export declare function getMetadata<T = any>(key: any, target: any, propertyKey?: string | symbol): T | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Set metadata value on a target.
|
|
20
|
+
*
|
|
21
|
+
* @param key - The metadata key
|
|
22
|
+
* @param value - The metadata value
|
|
23
|
+
* @param target - The target object or class
|
|
24
|
+
* @param propertyKey - Optional property key for method/property metadata
|
|
25
|
+
*/
|
|
26
|
+
export declare function setMetadata(key: any, value: any, target: any, propertyKey?: string | symbol): void;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a class uses async initialization via static `with()` method.
|
|
29
|
+
*
|
|
30
|
+
* Classes decorated with @AsyncWith will have this metadata set and
|
|
31
|
+
* should be instantiated using their static `with()` method instead
|
|
32
|
+
* of the constructor.
|
|
33
|
+
*
|
|
34
|
+
* @param klass - The class to check
|
|
35
|
+
* @returns True if the class uses async initialization
|
|
36
|
+
*/
|
|
37
|
+
export declare function hasAsyncWith(klass: Type<any>): boolean;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider normalization and dependency discovery utilities.
|
|
3
|
+
*
|
|
4
|
+
* These utilities convert user-facing provider definitions to internal
|
|
5
|
+
* ProviderRecord format and discover dependencies.
|
|
6
|
+
*/
|
|
7
|
+
import type { Token, Type } from '../interfaces/base.interface.js';
|
|
8
|
+
import type { ProviderType } from '../interfaces/provider.interface.js';
|
|
9
|
+
import { type ProviderRecord } from '../records/provider.record.js';
|
|
10
|
+
/**
|
|
11
|
+
* Token set for reading provider metadata from classes.
|
|
12
|
+
* Each key maps to a metadata symbol used with reflect-metadata.
|
|
13
|
+
*/
|
|
14
|
+
export interface ProviderTokens {
|
|
15
|
+
/** Token indicating this is a provider class */
|
|
16
|
+
type: symbol;
|
|
17
|
+
/** Token for provider name */
|
|
18
|
+
name: symbol;
|
|
19
|
+
/** Token for provider scope */
|
|
20
|
+
scope: symbol;
|
|
21
|
+
/** Token for provider description */
|
|
22
|
+
description?: symbol;
|
|
23
|
+
/** Token for provider id */
|
|
24
|
+
id?: symbol;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Options for creating a provider normalizer.
|
|
28
|
+
*/
|
|
29
|
+
export interface ProviderNormalizerOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Metadata tokens for reading provider information from decorated classes.
|
|
32
|
+
*/
|
|
33
|
+
tokens: ProviderTokens;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Create a provider normalizer function with the given metadata tokens.
|
|
37
|
+
*
|
|
38
|
+
* The normalizer converts user-facing provider definitions to internal
|
|
39
|
+
* ProviderRecord format. By injecting tokens, this works with any
|
|
40
|
+
* decorator system (FrontMCP, custom, etc.).
|
|
41
|
+
*
|
|
42
|
+
* @param options - Normalizer configuration with metadata tokens
|
|
43
|
+
* @returns A normalizer function
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import { createProviderNormalizer } from '@frontmcp/di';
|
|
48
|
+
*
|
|
49
|
+
* const normalizeProvider = createProviderNormalizer({
|
|
50
|
+
* tokens: {
|
|
51
|
+
* type: Symbol('provider:type'),
|
|
52
|
+
* name: Symbol('provider:name'),
|
|
53
|
+
* scope: Symbol('provider:scope'),
|
|
54
|
+
* }
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* const record = normalizeProvider(MyService);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function createProviderNormalizer(options: ProviderNormalizerOptions): (item: ProviderType) => ProviderRecord;
|
|
61
|
+
/**
|
|
62
|
+
* Discover dependencies for a provider record during the discovery phase.
|
|
63
|
+
*
|
|
64
|
+
* @param rec - The provider record
|
|
65
|
+
* @param localTokens - Set of locally registered tokens
|
|
66
|
+
* @param depsOfClassFn - Function to discover class dependencies
|
|
67
|
+
* @returns Array of dependency tokens
|
|
68
|
+
*/
|
|
69
|
+
export declare function providerDiscoveryDeps(rec: ProviderRecord, localTokens: Set<Token>, depsOfClassFn: (klass: Type, phase: 'discovery' | 'invocation') => Type[]): Token[];
|
|
70
|
+
/**
|
|
71
|
+
* Get invocation tokens for a provider record.
|
|
72
|
+
*
|
|
73
|
+
* These are the tokens that need to be resolved when instantiating the provider.
|
|
74
|
+
*
|
|
75
|
+
* @param rec - The provider record
|
|
76
|
+
* @param depsOfClassFn - Function to discover class dependencies
|
|
77
|
+
* @returns Array of dependency tokens
|
|
78
|
+
*/
|
|
79
|
+
export declare function providerInvocationTokens(rec: ProviderRecord, depsOfClassFn: (klass: Type, phase: 'discovery' | 'invocation') => Type[]): Token[];
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token utilities for dependency injection.
|
|
3
|
+
*
|
|
4
|
+
* These utilities help with token resolution, type checking, and
|
|
5
|
+
* dependency discovery from class metadata.
|
|
6
|
+
*/
|
|
7
|
+
import type { Token, Type } from '../interfaces/base.interface.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get a human-readable name for a token.
|
|
10
|
+
*
|
|
11
|
+
* @param t - The token to get the name for
|
|
12
|
+
* @returns A string representation of the token
|
|
13
|
+
*/
|
|
14
|
+
export declare const tokenName: (t: Token) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Check if a value is a class constructor.
|
|
17
|
+
*
|
|
18
|
+
* @param x - The value to check
|
|
19
|
+
* @returns True if x is a class constructor
|
|
20
|
+
*/
|
|
21
|
+
export declare const isClass: (x: any) => x is Type;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a value is a Promise.
|
|
24
|
+
*
|
|
25
|
+
* @param v - The value to check
|
|
26
|
+
* @returns True if v is a Promise
|
|
27
|
+
*/
|
|
28
|
+
export declare const isPromise: (v: any) => v is Promise<any>;
|
|
29
|
+
/**
|
|
30
|
+
* Get async-with dependency tokens from a class.
|
|
31
|
+
*
|
|
32
|
+
* If a class is decorated with @AsyncWith, this returns the token array
|
|
33
|
+
* that should be resolved and passed to the static `with()` method.
|
|
34
|
+
*
|
|
35
|
+
* @param klass - The class to get tokens from
|
|
36
|
+
* @returns Array of dependency tokens, or null if not decorated
|
|
37
|
+
*/
|
|
38
|
+
export declare function getAsyncWithTokens(klass: Type<any>): Type<any>[] | null;
|
|
39
|
+
/**
|
|
40
|
+
* Read parameter types for static with(...) method.
|
|
41
|
+
*
|
|
42
|
+
* This function is TDZ-friendly and will use the @AsyncWith token array
|
|
43
|
+
* if available, falling back to design:paramtypes metadata.
|
|
44
|
+
*
|
|
45
|
+
* @param klass - The class to read parameter types from
|
|
46
|
+
* @param forWhat - Whether this is for 'discovery' or 'invocation' phase
|
|
47
|
+
* @returns Array of dependency types
|
|
48
|
+
* @throws If parameter types cannot be determined
|
|
49
|
+
*/
|
|
50
|
+
export declare function readWithParamTypes(klass: Type, forWhat: 'discovery' | 'invocation'): Type[];
|
|
51
|
+
/**
|
|
52
|
+
* Discover dependencies for a CLASS token or concrete Type.
|
|
53
|
+
*
|
|
54
|
+
* For classes with @AsyncWith, reads from the static `with()` method.
|
|
55
|
+
* Otherwise, reads constructor parameter types.
|
|
56
|
+
*
|
|
57
|
+
* @param klass - The class to discover dependencies for
|
|
58
|
+
* @param phase - Whether this is 'discovery' or 'invocation' phase
|
|
59
|
+
* @returns Array of dependency types
|
|
60
|
+
* @throws If dependencies cannot be determined (TDZ issues, missing metadata)
|
|
61
|
+
*/
|
|
62
|
+
export declare function depsOfClass(klass: Type, phase: 'discovery' | 'invocation'): Type[];
|
|
63
|
+
/**
|
|
64
|
+
* Discover dependencies for a function token.
|
|
65
|
+
*
|
|
66
|
+
* Reads design:paramtypes metadata, skipping the first parameter
|
|
67
|
+
* (which is typically the input argument, not a dependency).
|
|
68
|
+
*
|
|
69
|
+
* @param fn - The function to discover dependencies for
|
|
70
|
+
* @param phase - Whether this is 'discovery' or 'invocation' phase
|
|
71
|
+
* @returns Array of dependency types
|
|
72
|
+
* @throws If dependencies cannot be determined
|
|
73
|
+
*/
|
|
74
|
+
export declare function depsOfFunc(fn: (...args: any[]) => any | Promise<any>, phase: 'discovery' | 'invocation'): Type[];
|