@stitchem/core 0.0.3

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 (68) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +815 -0
  4. package/dist/container/container.d.ts +79 -0
  5. package/dist/container/container.js +156 -0
  6. package/dist/container/module.map.d.ts +22 -0
  7. package/dist/container/module.map.js +40 -0
  8. package/dist/context/context.d.ts +181 -0
  9. package/dist/context/context.js +395 -0
  10. package/dist/context/scope.d.ts +30 -0
  11. package/dist/context/scope.js +42 -0
  12. package/dist/core/core.lifecycle.d.ts +41 -0
  13. package/dist/core/core.lifecycle.js +37 -0
  14. package/dist/core/core.lifetime.d.ts +21 -0
  15. package/dist/core/core.lifetime.js +22 -0
  16. package/dist/core/core.types.d.ts +2 -0
  17. package/dist/core/core.types.js +2 -0
  18. package/dist/core/core.utils.d.ts +8 -0
  19. package/dist/core/core.utils.js +13 -0
  20. package/dist/decorator/inject.decorator.d.ts +50 -0
  21. package/dist/decorator/inject.decorator.js +78 -0
  22. package/dist/decorator/injectable.decorator.d.ts +45 -0
  23. package/dist/decorator/injectable.decorator.js +46 -0
  24. package/dist/errors/core.error.d.ts +24 -0
  25. package/dist/errors/core.error.js +59 -0
  26. package/dist/errors/error.codes.d.ts +17 -0
  27. package/dist/errors/error.codes.js +21 -0
  28. package/dist/index.d.ts +25 -0
  29. package/dist/index.js +23 -0
  30. package/dist/injector/injector.d.ts +78 -0
  31. package/dist/injector/injector.js +295 -0
  32. package/dist/instance-wrapper/instance-wrapper.d.ts +61 -0
  33. package/dist/instance-wrapper/instance-wrapper.js +142 -0
  34. package/dist/instance-wrapper/instance-wrapper.types.d.ts +18 -0
  35. package/dist/instance-wrapper/instance-wrapper.types.js +2 -0
  36. package/dist/logger/console.logger.d.ts +52 -0
  37. package/dist/logger/console.logger.js +90 -0
  38. package/dist/logger/logger.token.d.ts +23 -0
  39. package/dist/logger/logger.token.js +23 -0
  40. package/dist/logger/logger.types.d.ts +38 -0
  41. package/dist/logger/logger.types.js +12 -0
  42. package/dist/module/module.d.ts +104 -0
  43. package/dist/module/module.decorator.d.ts +28 -0
  44. package/dist/module/module.decorator.js +42 -0
  45. package/dist/module/module.graph.d.ts +52 -0
  46. package/dist/module/module.graph.js +263 -0
  47. package/dist/module/module.js +181 -0
  48. package/dist/module/module.ref.d.ts +81 -0
  49. package/dist/module/module.ref.js +123 -0
  50. package/dist/module/module.types.d.ts +80 -0
  51. package/dist/module/module.types.js +10 -0
  52. package/dist/provider/provider.guards.d.ts +46 -0
  53. package/dist/provider/provider.guards.js +62 -0
  54. package/dist/provider/provider.interface.d.ts +39 -0
  55. package/dist/provider/provider.interface.js +2 -0
  56. package/dist/test/test.d.ts +22 -0
  57. package/dist/test/test.js +23 -0
  58. package/dist/test/test.module-builder.d.ts +136 -0
  59. package/dist/test/test.module-builder.js +377 -0
  60. package/dist/test/test.module.d.ts +71 -0
  61. package/dist/test/test.module.js +151 -0
  62. package/dist/token/lazy.token.d.ts +44 -0
  63. package/dist/token/lazy.token.js +42 -0
  64. package/dist/token/token.types.d.ts +8 -0
  65. package/dist/token/token.types.js +2 -0
  66. package/dist/token/token.utils.d.ts +9 -0
  67. package/dist/token/token.utils.js +19 -0
  68. package/package.json +62 -0
@@ -0,0 +1,181 @@
1
+ import { InstanceWrapper } from '../instance-wrapper/instance-wrapper.js';
2
+ import { hasOnDispose } from '../core/core.lifecycle.js';
3
+ import { isConstructorProvider, isClassProvider, getProviderToken, } from '../provider/provider.guards.js';
4
+ import { isInjectable } from '../decorator/injectable.decorator.js';
5
+ import { CoreError } from '../errors/core.error.js';
6
+ /**
7
+ * Represents a module instance with its own providers.
8
+ * Each module maintains its own provider registry and visibility rules.
9
+ */
10
+ export class Module {
11
+ /** Unique identifier for this module instance. */
12
+ id;
13
+ /** The module class. */
14
+ classRef;
15
+ /** Whether this is a global module. */
16
+ isGlobal;
17
+ /** Original metadata from @module decorator + dynamic config. */
18
+ metadata;
19
+ /** Provider storage (token -> InstanceWrapper). */
20
+ _providers = new Map();
21
+ /** Exported tokens. */
22
+ _exports = new Set();
23
+ /** Imported modules. */
24
+ _imports = new Set();
25
+ /** Registration order for disposal. */
26
+ _registrationOrder = [];
27
+ /** Component instances keyed by metadata key (e.g. 'routers'). */
28
+ _components = new Map();
29
+ /** Injectable instances (guards, filters, middleware, etc.) keyed by class ref. */
30
+ _injectables = new Map();
31
+ /** Insertion order for injectable disposal. */
32
+ _injectableOrder = [];
33
+ /** Module instance (the instantiated module class). */
34
+ _instance;
35
+ constructor(options) {
36
+ this.id = options.id;
37
+ this.classRef = options.classRef;
38
+ this.metadata = options.metadata;
39
+ this.isGlobal = options.isGlobal ?? false;
40
+ }
41
+ /** All providers in this module. */
42
+ get providers() {
43
+ return this._providers;
44
+ }
45
+ /** All exported tokens. */
46
+ get exports() {
47
+ return this._exports;
48
+ }
49
+ /** All imported modules. */
50
+ get imports() {
51
+ return this._imports;
52
+ }
53
+ /** The module class instance. */
54
+ get instance() {
55
+ return this._instance;
56
+ }
57
+ set instance(value) {
58
+ this._instance = value;
59
+ }
60
+ /**
61
+ * Adds a provider to this module.
62
+ * Validates that class-based providers have @injectable().
63
+ *
64
+ * @throws CoreError (NOT_INJECTABLE) if a class provider lacks @injectable()
65
+ */
66
+ addProvider(provider) {
67
+ this.validateProvider(provider);
68
+ const wrapper = InstanceWrapper.fromProvider(provider);
69
+ const token = getProviderToken(provider);
70
+ this._providers.set(token, wrapper);
71
+ this._registrationOrder.push(token);
72
+ return wrapper;
73
+ }
74
+ /** Gets a provider by token. */
75
+ getProvider(token) {
76
+ return this._providers.get(token);
77
+ }
78
+ /** Checks if a provider exists in this module. */
79
+ hasProvider(token) {
80
+ return this._providers.has(token);
81
+ }
82
+ /** Adds an export token. */
83
+ addExport(token) {
84
+ this._exports.add(token);
85
+ }
86
+ /** Adds an imported module. */
87
+ addImport(mod) {
88
+ this._imports.add(mod);
89
+ }
90
+ /** Registers a component instance under a metadata key. */
91
+ addComponent(key, instance, classRef) {
92
+ let entries = this._components.get(key);
93
+ if (!entries) {
94
+ entries = [];
95
+ this._components.set(key, entries);
96
+ }
97
+ entries.push({ instance, classRef });
98
+ }
99
+ /** Returns component instances for a metadata key. */
100
+ getComponents(key) {
101
+ return this._components.get(key) ?? [];
102
+ }
103
+ /** Returns a cached injectable instance, or undefined if not resolved yet. */
104
+ getInjectable(ctor) {
105
+ return this._injectables.get(ctor);
106
+ }
107
+ /** Caches an injectable instance and tracks insertion order. */
108
+ setInjectable(ctor, instance) {
109
+ if (!this._injectables.has(ctor)) {
110
+ this._injectableOrder.push(ctor);
111
+ }
112
+ this._injectables.set(ctor, instance);
113
+ }
114
+ /** All cached injectables as [classRef, instance] pairs. */
115
+ get injectables() {
116
+ return this._injectables;
117
+ }
118
+ /** Disposes all injectable instances in reverse insertion order. */
119
+ async disposeInjectables() {
120
+ for (const ctor of [...this._injectableOrder].reverse()) {
121
+ const instance = this._injectables.get(ctor);
122
+ if (hasOnDispose(instance))
123
+ await instance.onDispose();
124
+ }
125
+ this._injectables.clear();
126
+ this._injectableOrder.length = 0;
127
+ }
128
+ /** Disposes all component instances in reverse order. */
129
+ async disposeComponents() {
130
+ for (const [, entries] of this._components) {
131
+ for (const { instance } of [...entries].reverse()) {
132
+ if (hasOnDispose(instance))
133
+ await instance.onDispose();
134
+ }
135
+ }
136
+ this._components.clear();
137
+ }
138
+ /**
139
+ * Disposes provider instances in reverse registration order.
140
+ *
141
+ * - With scope: only dispose SCOPED instances for that scope
142
+ * - Without scope: dispose all SINGLETON instances (full shutdown)
143
+ */
144
+ async dispose(scope) {
145
+ const reversed = [...this._registrationOrder].reverse();
146
+ for (const token of reversed) {
147
+ const wrapper = this._providers.get(token);
148
+ if (!wrapper)
149
+ continue;
150
+ if (scope) {
151
+ if (wrapper.isScoped && wrapper.isResolved(scope)) {
152
+ const instance = wrapper.getInstance(scope);
153
+ if (hasOnDispose(instance))
154
+ await instance.onDispose();
155
+ wrapper.clear(scope);
156
+ }
157
+ }
158
+ else {
159
+ if (wrapper.isSingleton && wrapper.isResolved()) {
160
+ const instance = wrapper.getInstance();
161
+ if (hasOnDispose(instance))
162
+ await instance.onDispose();
163
+ wrapper.clear();
164
+ }
165
+ }
166
+ }
167
+ }
168
+ /**
169
+ * Validates a provider configuration.
170
+ * @throws CoreError (NOT_INJECTABLE) if a class provider lacks @injectable()
171
+ */
172
+ validateProvider(provider) {
173
+ if (isConstructorProvider(provider) && !isInjectable(provider)) {
174
+ throw CoreError.notInjectable(provider);
175
+ }
176
+ if (isClassProvider(provider) && !isInjectable(provider.useClass)) {
177
+ throw CoreError.notInjectable(provider.useClass);
178
+ }
179
+ }
180
+ }
181
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1,81 @@
1
+ import type { Token } from '../token/token.types.js';
2
+ import type { constructor } from '../core/core.types.js';
3
+ import type { ComponentRef } from '../context/context.js';
4
+ import type { Container } from '../container/container.js';
5
+ import type { Injector } from '../injector/injector.js';
6
+ import type { Module } from './module.js';
7
+ import { Scope } from '../context/scope.js';
8
+ /**
9
+ * Reference to a module, injectable into providers.
10
+ * Provides dynamic resolution, module navigation, and instance creation.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * @injectable()
15
+ * class DynamicService {
16
+ * static inject = [ModuleRef] as const;
17
+ * constructor(private moduleRef: ModuleRef) {}
18
+ *
19
+ * async getService<T>(token: Token<T>): Promise<T> {
20
+ * return this.moduleRef.resolve(token);
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+ export declare class ModuleRef {
26
+ private readonly container;
27
+ private readonly injector;
28
+ private readonly module;
29
+ constructor(container: Container, injector: Injector, module: Module);
30
+ /** The module class. */
31
+ get moduleClass(): constructor;
32
+ /** The module's unique identifier. */
33
+ get id(): string;
34
+ /** Whether this is a global module. */
35
+ get isGlobal(): boolean;
36
+ /** Gets the module instance. */
37
+ get<T = unknown>(): T;
38
+ /**
39
+ * Resolves a dependency from this module's context.
40
+ * Respects module visibility (can only resolve visible tokens).
41
+ */
42
+ resolve<T>(token: Token<T>, scope?: Scope): Promise<T>;
43
+ /** Synchronously resolves a dependency from this module's context. */
44
+ resolveSync<T>(token: Token<T>, scope?: Scope): T;
45
+ /**
46
+ * Creates a new instance of a registered provider, bypassing cache.
47
+ * The class must be registered as a provider in this module.
48
+ *
49
+ * @throws CoreError (PROVIDER_NOT_FOUND) if the class is not registered
50
+ */
51
+ create<T>(ctor: constructor<T>, scope?: Scope): Promise<T>;
52
+ /**
53
+ * Instantiates any class by resolving its dependencies.
54
+ * The class does not need to be registered as a provider.
55
+ */
56
+ constructClass<T>(ctor: constructor<T>, scope?: Scope): Promise<T>;
57
+ /**
58
+ * Resolves an injectable class instance with caching and lifecycle hooks.
59
+ *
60
+ * Injectables are auxiliary classes (guards, filters, middleware, etc.)
61
+ * that participate in DI but are not registered as providers. They are
62
+ * cached on the module and receive full lifecycle support.
63
+ *
64
+ * @param ctor - The injectable class to resolve.
65
+ * @param options - Resolution options.
66
+ * @param options.strict - When `true` (default), resolves dependencies from
67
+ * this module's visibility. When `false`, resolves globally.
68
+ * @returns The resolved instance (cached on subsequent calls).
69
+ */
70
+ resolveInjectable<T>(ctor: constructor<T>, options?: {
71
+ strict?: boolean;
72
+ }): Promise<T>;
73
+ /** Returns component instances for a given metadata key from this module. */
74
+ getComponents<T = unknown>(key: string): ComponentRef<T>[];
75
+ /**
76
+ * Navigates to a different module for resolution.
77
+ * Returns a new ModuleRef bound to the target module.
78
+ */
79
+ select<T extends constructor>(moduleClass: T): ModuleRef;
80
+ }
81
+ //# sourceMappingURL=module.ref.d.ts.map
@@ -0,0 +1,123 @@
1
+ import { Scope } from '../context/scope.js';
2
+ import { hasOnReady } from '../core/core.lifecycle.js';
3
+ import { CoreError } from '../errors/core.error.js';
4
+ /**
5
+ * Reference to a module, injectable into providers.
6
+ * Provides dynamic resolution, module navigation, and instance creation.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * @injectable()
11
+ * class DynamicService {
12
+ * static inject = [ModuleRef] as const;
13
+ * constructor(private moduleRef: ModuleRef) {}
14
+ *
15
+ * async getService<T>(token: Token<T>): Promise<T> {
16
+ * return this.moduleRef.resolve(token);
17
+ * }
18
+ * }
19
+ * ```
20
+ */
21
+ export class ModuleRef {
22
+ container;
23
+ injector;
24
+ module;
25
+ constructor(container, injector, module) {
26
+ this.container = container;
27
+ this.injector = injector;
28
+ this.module = module;
29
+ }
30
+ /** The module class. */
31
+ get moduleClass() {
32
+ return this.module.classRef;
33
+ }
34
+ /** The module's unique identifier. */
35
+ get id() {
36
+ return this.module.id;
37
+ }
38
+ /** Whether this is a global module. */
39
+ get isGlobal() {
40
+ return this.module.isGlobal;
41
+ }
42
+ /** Gets the module instance. */
43
+ get() {
44
+ return this.module.instance;
45
+ }
46
+ /**
47
+ * Resolves a dependency from this module's context.
48
+ * Respects module visibility (can only resolve visible tokens).
49
+ */
50
+ async resolve(token, scope = Scope.STATIC) {
51
+ const { wrapper, module } = this.container.getProviderByToken(token, this.module);
52
+ return this.injector.loadInstance(wrapper, module, scope);
53
+ }
54
+ /** Synchronously resolves a dependency from this module's context. */
55
+ resolveSync(token, scope = Scope.STATIC) {
56
+ const { wrapper, module } = this.container.getProviderByToken(token, this.module);
57
+ return this.injector.loadInstanceSync(wrapper, module, scope);
58
+ }
59
+ /**
60
+ * Creates a new instance of a registered provider, bypassing cache.
61
+ * The class must be registered as a provider in this module.
62
+ *
63
+ * @throws CoreError (PROVIDER_NOT_FOUND) if the class is not registered
64
+ */
65
+ async create(ctor, scope = Scope.STATIC) {
66
+ const wrapper = this.module.getProvider(ctor);
67
+ if (wrapper) {
68
+ return this.injector.createUncached(wrapper, this.module, scope);
69
+ }
70
+ throw CoreError.providerNotFound(ctor, this.module.id);
71
+ }
72
+ /**
73
+ * Instantiates any class by resolving its dependencies.
74
+ * The class does not need to be registered as a provider.
75
+ */
76
+ async constructClass(ctor, scope = Scope.STATIC) {
77
+ return this.injector.instantiateClass(ctor, this.module, scope);
78
+ }
79
+ /**
80
+ * Resolves an injectable class instance with caching and lifecycle hooks.
81
+ *
82
+ * Injectables are auxiliary classes (guards, filters, middleware, etc.)
83
+ * that participate in DI but are not registered as providers. They are
84
+ * cached on the module and receive full lifecycle support.
85
+ *
86
+ * @param ctor - The injectable class to resolve.
87
+ * @param options - Resolution options.
88
+ * @param options.strict - When `true` (default), resolves dependencies from
89
+ * this module's visibility. When `false`, resolves globally.
90
+ * @returns The resolved instance (cached on subsequent calls).
91
+ */
92
+ async resolveInjectable(ctor, options) {
93
+ const cached = this.module.getInjectable(ctor);
94
+ if (cached)
95
+ return cached;
96
+ const scope = Scope.current() ?? Scope.STATIC;
97
+ const instance = await (options?.strict === false
98
+ ? this.injector.instantiateClassGlobal(ctor, scope)
99
+ : this.injector.instantiateClass(ctor, this.module, scope));
100
+ if (hasOnReady(instance)) {
101
+ await instance.onReady();
102
+ }
103
+ this.module.setInjectable(ctor, instance);
104
+ return instance;
105
+ }
106
+ /** Returns component instances for a given metadata key from this module. */
107
+ getComponents(key) {
108
+ return this.module.getComponents(key).map((entry) => ({
109
+ instance: entry.instance,
110
+ classRef: entry.classRef,
111
+ moduleRef: this,
112
+ }));
113
+ }
114
+ /**
115
+ * Navigates to a different module for resolution.
116
+ * Returns a new ModuleRef bound to the target module.
117
+ */
118
+ select(moduleClass) {
119
+ const module = this.container.getModuleByClass(moduleClass);
120
+ return new ModuleRef(this.container, this.injector, module);
121
+ }
122
+ }
123
+ //# sourceMappingURL=module.ref.js.map
@@ -0,0 +1,80 @@
1
+ import type { constructor } from '../core/core.types.js';
2
+ import type { Token } from '../token/token.types.js';
3
+ import type { Provider } from '../provider/provider.interface.js';
4
+ /**
5
+ * Metadata for a module declaration.
6
+ *
7
+ * Plugins can extend this interface via TypeScript declaration merging:
8
+ * @example
9
+ * ```ts
10
+ * declare module '@stitchem/core' {
11
+ * interface ModuleMetadata {
12
+ * controllers?: constructor[];
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export interface ModuleMetadata {
18
+ /**
19
+ * Whether this module should be global.
20
+ * Global modules export their providers to all modules without explicit import.
21
+ */
22
+ global?: boolean;
23
+ /**
24
+ * Modules to import. Importing a module gives access to its exports.
25
+ * Can be module classes or DynamicModule objects from forRoot/forFeature.
26
+ */
27
+ imports?: ModuleImport[];
28
+ /**
29
+ * Providers registered in this module.
30
+ * Private by default — only accessible within this module.
31
+ */
32
+ providers?: Provider[];
33
+ /**
34
+ * Tokens or modules to export from this module.
35
+ * Exported providers become accessible to importing modules.
36
+ * Exporting a module class re-exports all of that module's exports.
37
+ */
38
+ exports?: (Token | constructor)[];
39
+ }
40
+ /**
41
+ * A dynamic module configuration returned by forRoot/forFeature static methods.
42
+ * Allows modules to be configured dynamically with additional providers.
43
+ *
44
+ * Extends ModuleMetadata so that augmented keys (e.g. `routers`) are
45
+ * automatically available on DynamicModule as well.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * class ConfigModule {
50
+ * static forRoot(options: ConfigModuleOptions): DynamicModule {
51
+ * return {
52
+ * module: ConfigModule,
53
+ * providers: [
54
+ * { provide: CONFIG_OPTIONS, useValue: options },
55
+ * ConfigService,
56
+ * ],
57
+ * exports: [ConfigService],
58
+ * global: options.isGlobal,
59
+ * };
60
+ * }
61
+ * }
62
+ * ```
63
+ */
64
+ export interface DynamicModule extends ModuleMetadata {
65
+ /** The module class. */
66
+ module: constructor;
67
+ }
68
+ /**
69
+ * A module import: either a class or a DynamicModule configuration.
70
+ */
71
+ export type ModuleImport = constructor | DynamicModule;
72
+ /**
73
+ * A module class decorated with @module().
74
+ */
75
+ export type ModuleClass = constructor;
76
+ /**
77
+ * Checks if a value is a DynamicModule.
78
+ */
79
+ export declare function isDynamicModule(value: ModuleImport): value is DynamicModule;
80
+ //# sourceMappingURL=module.types.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checks if a value is a DynamicModule.
3
+ */
4
+ export function isDynamicModule(value) {
5
+ return (typeof value === 'object' &&
6
+ value !== null &&
7
+ 'module' in value &&
8
+ typeof value.module === 'function');
9
+ }
10
+ //# sourceMappingURL=module.types.js.map
@@ -0,0 +1,46 @@
1
+ import type { constructor } from '../core/core.types.js';
2
+ import type { Token } from '../token/token.types.js';
3
+ import type { ClassProvider, ExistingProvider, FactoryProvider, Provider, ValueProvider } from './provider.interface.js';
4
+ /**
5
+ * Type guard for ClassProvider.
6
+ *
7
+ * @param provider - The provider to check
8
+ * @returns True if the provider is a ClassProvider
9
+ */
10
+ export declare function isClassProvider<T>(provider: Provider<T>): provider is ClassProvider<T>;
11
+ /**
12
+ * Type guard for ValueProvider.
13
+ *
14
+ * @param provider - The provider to check
15
+ * @returns True if the provider is a ValueProvider
16
+ */
17
+ export declare function isValueProvider<T>(provider: Provider<T>): provider is ValueProvider<T>;
18
+ /**
19
+ * Type guard for FactoryProvider.
20
+ *
21
+ * @param provider - The provider to check
22
+ * @returns True if the provider is a FactoryProvider
23
+ */
24
+ export declare function isFactoryProvider<T>(provider: Provider<T>): provider is FactoryProvider<T>;
25
+ /**
26
+ * Type guard for ExistingProvider.
27
+ *
28
+ * @param provider - The provider to check
29
+ * @returns True if the provider is an ExistingProvider
30
+ */
31
+ export declare function isExistingProvider<T>(provider: Provider<T>): provider is ExistingProvider<T>;
32
+ /**
33
+ * Type guard to check if a provider is a class constructor (shorthand form).
34
+ *
35
+ * @param provider - The provider to check
36
+ * @returns True if the provider is a class constructor
37
+ */
38
+ export declare function isConstructorProvider<T>(provider: Provider<T>): provider is constructor<T>;
39
+ /**
40
+ * Extracts the token from a provider.
41
+ *
42
+ * @param provider - The provider to extract the token from
43
+ * @returns The injection token for the provider
44
+ */
45
+ export declare function getProviderToken<T>(provider: Provider<T>): Token<T>;
46
+ //# sourceMappingURL=provider.guards.d.ts.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Type guard for ClassProvider.
3
+ *
4
+ * @param provider - The provider to check
5
+ * @returns True if the provider is a ClassProvider
6
+ */
7
+ export function isClassProvider(provider) {
8
+ return (typeof provider === 'object' && provider !== null && 'useClass' in provider);
9
+ }
10
+ /**
11
+ * Type guard for ValueProvider.
12
+ *
13
+ * @param provider - The provider to check
14
+ * @returns True if the provider is a ValueProvider
15
+ */
16
+ export function isValueProvider(provider) {
17
+ return (typeof provider === 'object' && provider !== null && 'useValue' in provider);
18
+ }
19
+ /**
20
+ * Type guard for FactoryProvider.
21
+ *
22
+ * @param provider - The provider to check
23
+ * @returns True if the provider is a FactoryProvider
24
+ */
25
+ export function isFactoryProvider(provider) {
26
+ return (typeof provider === 'object' &&
27
+ provider !== null &&
28
+ 'useFactory' in provider);
29
+ }
30
+ /**
31
+ * Type guard for ExistingProvider.
32
+ *
33
+ * @param provider - The provider to check
34
+ * @returns True if the provider is an ExistingProvider
35
+ */
36
+ export function isExistingProvider(provider) {
37
+ return (typeof provider === 'object' &&
38
+ provider !== null &&
39
+ 'useExisting' in provider);
40
+ }
41
+ /**
42
+ * Type guard to check if a provider is a class constructor (shorthand form).
43
+ *
44
+ * @param provider - The provider to check
45
+ * @returns True if the provider is a class constructor
46
+ */
47
+ export function isConstructorProvider(provider) {
48
+ return typeof provider === 'function';
49
+ }
50
+ /**
51
+ * Extracts the token from a provider.
52
+ *
53
+ * @param provider - The provider to extract the token from
54
+ * @returns The injection token for the provider
55
+ */
56
+ export function getProviderToken(provider) {
57
+ if (isConstructorProvider(provider)) {
58
+ return provider;
59
+ }
60
+ return provider.provide;
61
+ }
62
+ //# sourceMappingURL=provider.guards.js.map
@@ -0,0 +1,39 @@
1
+ import type { constructor } from '../core/core.types.js';
2
+ import type { Lifetime } from '../core/core.lifetime.js';
3
+ import type { Token } from '../token/token.types.js';
4
+ /**
5
+ * Provider that uses a class constructor.
6
+ */
7
+ export interface ClassProvider<T = unknown> {
8
+ provide: Token<T>;
9
+ useClass: constructor<T>;
10
+ lifetime?: Lifetime;
11
+ }
12
+ /**
13
+ * Provider that uses a static value.
14
+ */
15
+ export interface ValueProvider<T = unknown> {
16
+ provide: Token<T>;
17
+ useValue: T;
18
+ }
19
+ /**
20
+ * Provider that uses a factory function.
21
+ */
22
+ export interface FactoryProvider<T = unknown> {
23
+ provide: Token<T>;
24
+ useFactory: (...args: any[]) => T | Promise<T>;
25
+ inject?: Token[];
26
+ lifetime?: Lifetime;
27
+ }
28
+ /**
29
+ * Provider that aliases another token.
30
+ */
31
+ export interface ExistingProvider<T = unknown> {
32
+ provide: Token<T>;
33
+ useExisting: Token<T>;
34
+ }
35
+ /**
36
+ * Union of all provider types.
37
+ */
38
+ export type Provider<T = unknown> = constructor<T> | ClassProvider<T> | ValueProvider<T> | FactoryProvider<T> | ExistingProvider<T>;
39
+ //# sourceMappingURL=provider.interface.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=provider.interface.js.map
@@ -0,0 +1,22 @@
1
+ import type { ModuleMetadata } from '../module/module.types.js';
2
+ import { TestModuleBuilder } from './test.module-builder.js';
3
+ /**
4
+ * Entry point for the testing API.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const module = await Test.createModule({
9
+ * imports: [UserModule],
10
+ * providers: [UserService],
11
+ * })
12
+ * .overrideProvider(DbService).useValue({ query: vi.fn() })
13
+ * .compile();
14
+ *
15
+ * const userService = await module.resolve(UserService);
16
+ * await module.close();
17
+ * ```
18
+ */
19
+ export declare class Test {
20
+ static createModule(metadata: ModuleMetadata): TestModuleBuilder;
21
+ }
22
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1,23 @@
1
+ import { TestModuleBuilder } from './test.module-builder.js';
2
+ /**
3
+ * Entry point for the testing API.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * const module = await Test.createModule({
8
+ * imports: [UserModule],
9
+ * providers: [UserService],
10
+ * })
11
+ * .overrideProvider(DbService).useValue({ query: vi.fn() })
12
+ * .compile();
13
+ *
14
+ * const userService = await module.resolve(UserService);
15
+ * await module.close();
16
+ * ```
17
+ */
18
+ export class Test {
19
+ static createModule(metadata) {
20
+ return new TestModuleBuilder(metadata);
21
+ }
22
+ }
23
+ //# sourceMappingURL=test.js.map