@tsed/di 8.18.1 → 8.19.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/lib/esm/common/decorators/autoInjectable.js +28 -9
- package/lib/esm/common/decorators/constant.js +26 -22
- package/lib/esm/common/decorators/controller.js +40 -20
- package/lib/esm/common/decorators/injectable.js +30 -10
- package/lib/esm/common/decorators/intercept.js +41 -3
- package/lib/esm/common/decorators/interceptor.js +31 -4
- package/lib/esm/common/decorators/module.js +36 -5
- package/lib/esm/common/decorators/opts.js +20 -12
- package/lib/esm/common/decorators/overrideProvider.js +38 -4
- package/lib/esm/common/decorators/scope.js +32 -3
- package/lib/esm/common/decorators/service.js +24 -4
- package/lib/esm/common/decorators/useOpts.js +21 -13
- package/lib/esm/common/decorators/value.js +28 -22
- package/lib/esm/common/domain/Container.js +20 -0
- package/lib/esm/common/domain/ContextLogger.js +21 -0
- package/lib/esm/common/domain/ControllerProvider.js +22 -0
- package/lib/esm/common/domain/DIContext.js +22 -0
- package/lib/esm/common/domain/InjectablePropertyType.js +16 -0
- package/lib/esm/common/domain/LocalsContainer.js +21 -0
- package/lib/esm/common/domain/Provider.js +19 -0
- package/lib/esm/common/domain/ProviderScope.js +25 -0
- package/lib/esm/common/domain/ProviderType.js +25 -0
- package/lib/esm/common/errors/InjectionError.js +24 -0
- package/lib/esm/common/errors/InvalidPropertyTokenError.js +15 -0
- package/lib/esm/common/fn/inject.js +19 -6
- package/lib/esm/common/fn/injectMany.js +24 -6
- package/lib/esm/common/fn/injectable.js +57 -0
- package/lib/esm/common/fn/injector.js +21 -2
- package/lib/esm/common/fn/lazyInject.js +48 -1
- package/lib/esm/common/fn/localsContainer.js +31 -2
- package/lib/esm/common/fn/logger.js +15 -1
- package/lib/esm/common/services/DIConfiguration.js +24 -0
- package/lib/esm/common/services/DILogger.js +23 -0
- package/lib/esm/common/services/InjectorService.js +89 -43
- package/lib/types/common/decorators/autoInjectable.d.ts +31 -10
- package/lib/types/common/decorators/configuration.d.ts +32 -2
- package/lib/types/common/decorators/constant.d.ts +26 -22
- package/lib/types/common/decorators/controller.d.ts +40 -20
- package/lib/types/common/decorators/inject.d.ts +29 -7
- package/lib/types/common/decorators/injectable.d.ts +30 -10
- package/lib/types/common/decorators/intercept.d.ts +41 -3
- package/lib/types/common/decorators/interceptor.d.ts +31 -4
- package/lib/types/common/decorators/lazyInject.d.ts +43 -9
- package/lib/types/common/decorators/module.d.ts +36 -5
- package/lib/types/common/decorators/opts.d.ts +20 -12
- package/lib/types/common/decorators/overrideProvider.d.ts +38 -4
- package/lib/types/common/decorators/scope.d.ts +32 -3
- package/lib/types/common/decorators/service.d.ts +24 -4
- package/lib/types/common/decorators/useOpts.d.ts +21 -13
- package/lib/types/common/decorators/value.d.ts +28 -22
- package/lib/types/common/domain/Container.d.ts +20 -0
- package/lib/types/common/domain/ContextLogger.d.ts +26 -0
- package/lib/types/common/domain/ControllerProvider.d.ts +29 -0
- package/lib/types/common/domain/DIContext.d.ts +27 -0
- package/lib/types/common/domain/InjectablePropertyType.d.ts +16 -0
- package/lib/types/common/domain/LocalsContainer.d.ts +21 -0
- package/lib/types/common/domain/Provider.d.ts +25 -0
- package/lib/types/common/domain/ProviderScope.d.ts +25 -0
- package/lib/types/common/domain/ProviderType.d.ts +25 -0
- package/lib/types/common/errors/InjectionError.d.ts +24 -0
- package/lib/types/common/errors/InvalidPropertyTokenError.d.ts +15 -0
- package/lib/types/common/fn/configuration.d.ts +31 -0
- package/lib/types/common/fn/constant.d.ts +22 -0
- package/lib/types/common/fn/inject.d.ts +19 -6
- package/lib/types/common/fn/injectMany.d.ts +24 -6
- package/lib/types/common/fn/injectable.d.ts +57 -0
- package/lib/types/common/fn/injector.d.ts +21 -2
- package/lib/types/common/fn/lazyInject.d.ts +48 -1
- package/lib/types/common/fn/localsContainer.d.ts +31 -2
- package/lib/types/common/fn/logger.d.ts +15 -1
- package/lib/types/common/fn/refValue.d.ts +15 -6
- package/lib/types/common/interfaces/AlterRunInContext.d.ts +26 -0
- package/lib/types/common/interfaces/DILogger.d.ts +36 -0
- package/lib/types/common/interfaces/DILoggerOptions.d.ts +23 -0
- package/lib/types/common/interfaces/ImportTokenProviderOpts.d.ts +43 -0
- package/lib/types/common/interfaces/InterceptorContext.d.ts +35 -0
- package/lib/types/common/interfaces/InterceptorMethods.d.ts +27 -0
- package/lib/types/common/interfaces/InvokeOptions.d.ts +8 -0
- package/lib/types/common/interfaces/OnDestroy.d.ts +22 -0
- package/lib/types/common/interfaces/OnInit.d.ts +22 -0
- package/lib/types/common/interfaces/ProviderOpts.d.ts +31 -0
- package/lib/types/common/interfaces/ResolvedInvokeOptions.d.ts +9 -0
- package/lib/types/common/interfaces/TokenProvider.d.ts +32 -2
- package/lib/types/common/interfaces/TokenRoute.d.ts +16 -0
- package/lib/types/common/services/DIConfiguration.d.ts +24 -0
- package/lib/types/common/services/DILogger.d.ts +28 -0
- package/lib/types/common/services/InjectorService.d.ts +89 -43
- package/lib/types/node/utils/asyncHookContext.d.ts +0 -1
- package/package.json +6 -6
|
@@ -15,38 +15,44 @@ export function bindValue(target, propertyKey, expression, defaultValue) {
|
|
|
15
15
|
catchError(() => Reflect.defineProperty(target, propertyKey, descriptor));
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Inject a reactive configuration value into a property.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* Creates a getter/setter that always reflects the current configuration value.
|
|
21
|
+
* Unlike `@Constant()`, the value is not frozen and can change at runtime.
|
|
21
22
|
*
|
|
22
|
-
*
|
|
23
|
-
* import {Env} from "@tsed/core/domain/Env.js";
|
|
24
|
-
* import {Constant, Value} from "@tsed/di";
|
|
25
|
-
*
|
|
26
|
-
* export class MyClass {
|
|
23
|
+
* ### Usage
|
|
27
24
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import {Injectable, Value} from "@tsed/di";
|
|
30
27
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
28
|
+
* @Injectable()
|
|
29
|
+
* export class MyService {
|
|
30
|
+
* @Value("swagger.path")
|
|
31
|
+
* swaggerPath: string;
|
|
33
32
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* @Value("api.port", 3000)
|
|
34
|
+
* port: number;
|
|
36
35
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
36
|
+
* constructor() {
|
|
37
|
+
* // Not available yet - undefined
|
|
38
|
+
* }
|
|
40
39
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
40
|
+
* $onInit() {
|
|
41
|
+
* console.log(this.swaggerPath); // Current value
|
|
42
|
+
* this.swaggerPath = "/new-path"; // Can be modified
|
|
43
|
+
* }
|
|
44
44
|
* }
|
|
45
45
|
* ```
|
|
46
46
|
*
|
|
47
|
-
* @
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* ### Difference from @Constant
|
|
48
|
+
*
|
|
49
|
+
* - `@Constant`: Frozen immutable value (deep clone)
|
|
50
|
+
* - `@Value`: Reactive value (always reads current config)
|
|
51
|
+
*
|
|
52
|
+
* @param expression Dot-notation path to the configuration value
|
|
53
|
+
* @param defaultValue Optional default value if not found
|
|
54
|
+
* @returns Property decorator function
|
|
55
|
+
* @public
|
|
50
56
|
* @decorator
|
|
51
57
|
*/
|
|
52
58
|
export function Value(expression, defaultValue) {
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { GlobalProviders } from "../registries/GlobalProviders.js";
|
|
2
2
|
import { Provider } from "./Provider.js";
|
|
3
|
+
/**
|
|
4
|
+
* Provider container managing registered providers and their metadata.
|
|
5
|
+
*
|
|
6
|
+
* Extends `Map` to provide specialized methods for adding, retrieving, and managing providers
|
|
7
|
+
* within the dependency injection system. Acts as a registry for all injectable classes and values.
|
|
8
|
+
*
|
|
9
|
+
* ### Usage
|
|
10
|
+
*
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import {Container} from "@tsed/di";
|
|
13
|
+
*
|
|
14
|
+
* const container = new Container();
|
|
15
|
+
* container.add(MyService, {scope: ProviderScope.SINGLETON});
|
|
16
|
+
*
|
|
17
|
+
* const provider = container.getProvider(MyService);
|
|
18
|
+
* const controllers = container.getProviders(ProviderType.CONTROLLER);
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
3
23
|
export class Container extends Map {
|
|
4
24
|
/**
|
|
5
25
|
*
|
|
@@ -2,6 +2,27 @@ import { Hooks } from "@tsed/hooks";
|
|
|
2
2
|
import { levels } from "@tsed/logger";
|
|
3
3
|
import { logger as injectLogger } from "../../common/index.js";
|
|
4
4
|
const LEVELS = levels();
|
|
5
|
+
/**
|
|
6
|
+
* Context-aware logger for scoped logging within a request or execution context.
|
|
7
|
+
*
|
|
8
|
+
* Buffers log messages and associates them with a specific context (like an HTTP request).
|
|
9
|
+
* Supports log level filtering, buffering, and automatic flushing when the context ends.
|
|
10
|
+
*
|
|
11
|
+
* ### Usage
|
|
12
|
+
*
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import {ContextLogger} from "@tsed/di";
|
|
15
|
+
*
|
|
16
|
+
* const logger = new ContextLogger({id: "req-123"});
|
|
17
|
+
*
|
|
18
|
+
* logger.info("Processing request");
|
|
19
|
+
* logger.debug("Debug info");
|
|
20
|
+
*
|
|
21
|
+
* await logger.flush(); // Write buffered logs
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
5
26
|
export class ContextLogger {
|
|
6
27
|
#additionalProps;
|
|
7
28
|
#level;
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import { Provider } from "./Provider.js";
|
|
2
2
|
import { ProviderType } from "./ProviderType.js";
|
|
3
|
+
/**
|
|
4
|
+
* Specialized provider for HTTP controllers.
|
|
5
|
+
*
|
|
6
|
+
* Extends the base `Provider` class with controller-specific metadata like middleware configuration
|
|
7
|
+
* and routing information. Used internally to manage HTTP route controllers in the DI system.
|
|
8
|
+
*
|
|
9
|
+
* ### Usage
|
|
10
|
+
*
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import {ControllerProvider} from "@tsed/di";
|
|
13
|
+
*
|
|
14
|
+
* const provider = new ControllerProvider(MyController);
|
|
15
|
+
* provider.middlewares = {
|
|
16
|
+
* useBefore: [AuthMiddleware],
|
|
17
|
+
* use: [ValidationMiddleware],
|
|
18
|
+
* useAfter: [LoggingMiddleware]
|
|
19
|
+
* };
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @typeParam T - The type of controller class
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
3
25
|
export class ControllerProvider extends Provider {
|
|
4
26
|
constructor(token, options = {}) {
|
|
5
27
|
super(token, options);
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import { injector, LocalsContainer } from "../index.js";
|
|
2
2
|
import { ContextLogger } from "./ContextLogger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Execution context for dependency injection operations.
|
|
5
|
+
*
|
|
6
|
+
* Represents a single execution scope (typically an HTTP request) with its own
|
|
7
|
+
* scoped provider instances, logger, and lifecycle management. Provides access to
|
|
8
|
+
* request-scoped services and context-specific data.
|
|
9
|
+
*
|
|
10
|
+
* ### Usage
|
|
11
|
+
*
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import {DIContext} from "@tsed/di";
|
|
14
|
+
*
|
|
15
|
+
* const context = new DIContext({id: "req-123"});
|
|
16
|
+
*
|
|
17
|
+
* context.logger.info("Processing request");
|
|
18
|
+
* const service = await context.injector.invoke(MyService, context.container);
|
|
19
|
+
*
|
|
20
|
+
* await context.destroy(); // Cleanup when done
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
3
25
|
export class DIContext {
|
|
4
26
|
#container;
|
|
5
27
|
#cache;
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration defining types of injectable properties and decorators.
|
|
3
|
+
*
|
|
4
|
+
* Used internally to track and classify different kinds of injected dependencies
|
|
5
|
+
* and decorated members within a class.
|
|
6
|
+
*
|
|
7
|
+
* ### Types
|
|
8
|
+
*
|
|
9
|
+
* - `METHOD`: Injectable method parameter
|
|
10
|
+
* - `PROPERTY`: Injectable class property
|
|
11
|
+
* - `CONSTANT`: Injected constant value
|
|
12
|
+
* - `VALUE`: Injected configured value
|
|
13
|
+
* - `INTERCEPTOR`: Interceptor applied to a method
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
1
17
|
export var InjectablePropertyType;
|
|
2
18
|
(function (InjectablePropertyType) {
|
|
3
19
|
InjectablePropertyType["METHOD"] = "method";
|
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
import { Hooks } from "@tsed/hooks";
|
|
2
|
+
/**
|
|
3
|
+
* Container for request-scoped and instance-scoped provider instances.
|
|
4
|
+
*
|
|
5
|
+
* Stores instances created within a specific execution context (like an HTTP request).
|
|
6
|
+
* Manages lifecycle hooks and destruction of scoped instances when the context ends.
|
|
7
|
+
*
|
|
8
|
+
* ### Usage
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import {LocalsContainer} from "@tsed/di";
|
|
12
|
+
*
|
|
13
|
+
* const locals = new LocalsContainer();
|
|
14
|
+
* locals.set(MyService, serviceInstance);
|
|
15
|
+
*
|
|
16
|
+
* const instance = locals.get(MyService);
|
|
17
|
+
*
|
|
18
|
+
* await locals.destroy(); // Cleanup when context ends
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
2
23
|
export class LocalsContainer extends Map {
|
|
3
24
|
constructor() {
|
|
4
25
|
super(...arguments);
|
|
@@ -7,6 +7,25 @@ import { DI_USE_PARAM_OPTIONS } from "../constants/constants.js";
|
|
|
7
7
|
import { discoverHooks } from "../utils/discoverHooks.js";
|
|
8
8
|
import { ProviderScope } from "./ProviderScope.js";
|
|
9
9
|
import { ProviderType } from "./ProviderType.js";
|
|
10
|
+
/**
|
|
11
|
+
* Provider metadata class managing dependency injection configuration.
|
|
12
|
+
*
|
|
13
|
+
* Encapsulates all information needed to create, configure, and manage a provider instance
|
|
14
|
+
* within the DI container. Tracks dependencies, lifecycle hooks, creation strategies, and metadata.
|
|
15
|
+
*
|
|
16
|
+
* ### Usage
|
|
17
|
+
*
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import {Provider, ProviderType} from "@tsed/di";
|
|
20
|
+
*
|
|
21
|
+
* const provider = new Provider(MyService);
|
|
22
|
+
* provider.type = ProviderType.PROVIDER;
|
|
23
|
+
* provider.deps = [DatabaseService, LoggerService];
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @typeParam T - The type of instance this provider creates
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
10
29
|
export class Provider {
|
|
11
30
|
#useClass;
|
|
12
31
|
#token;
|
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration defining the lifecycle scopes for provider instances.
|
|
3
|
+
*
|
|
4
|
+
* Determines when and how provider instances are created and shared across the application.
|
|
5
|
+
*
|
|
6
|
+
* ### Scopes
|
|
7
|
+
*
|
|
8
|
+
* - `SINGLETON`: One instance shared across the entire application (default)
|
|
9
|
+
* - `REQUEST`: New instance created for each request/context
|
|
10
|
+
* - `INSTANCE`: New instance created on every injection
|
|
11
|
+
*
|
|
12
|
+
* ### Usage
|
|
13
|
+
*
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import {Injectable, Scope, ProviderScope} from "@tsed/di";
|
|
16
|
+
*
|
|
17
|
+
* @Injectable()
|
|
18
|
+
* @Scope(ProviderScope.REQUEST)
|
|
19
|
+
* class RequestScopedService {
|
|
20
|
+
* // New instance per request
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
1
26
|
export var ProviderScope;
|
|
2
27
|
(function (ProviderScope) {
|
|
3
28
|
ProviderScope["SINGLETON"] = "singleton";
|
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration categorizing different types of providers in the DI system.
|
|
3
|
+
*
|
|
4
|
+
* Used to classify and filter providers based on their role in the application architecture.
|
|
5
|
+
* Each type represents a distinct pattern or responsibility within the framework.
|
|
6
|
+
*
|
|
7
|
+
* ### Types
|
|
8
|
+
*
|
|
9
|
+
* - `VALUE`: Simple value providers (constants, configuration)
|
|
10
|
+
* - `PROVIDER`: Standard service providers
|
|
11
|
+
* - `MODULE`: Module providers organizing related functionality
|
|
12
|
+
* - `CONTROLLER`: HTTP route controllers
|
|
13
|
+
* - `INTERCEPTOR`: Method interceptors for cross-cutting concerns
|
|
14
|
+
* - `MIDDLEWARE`: Request/response middleware
|
|
15
|
+
*
|
|
16
|
+
* ### Usage
|
|
17
|
+
*
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import {ProviderType} from "@tsed/di";
|
|
20
|
+
*
|
|
21
|
+
* const providers = container.getProviders(ProviderType.CONTROLLER);
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
1
26
|
export var ProviderType;
|
|
2
27
|
(function (ProviderType) {
|
|
3
28
|
ProviderType["VALUE"] = "value";
|
|
@@ -3,6 +3,30 @@ import { isClass } from "@tsed/core/utils/isClass.js";
|
|
|
3
3
|
import { isString } from "@tsed/core/utils/isString.js";
|
|
4
4
|
import { nameOf } from "@tsed/core/utils/nameOf.js";
|
|
5
5
|
import { colors } from "../utils/colors.js";
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when dependency injection fails.
|
|
8
|
+
*
|
|
9
|
+
* Provides detailed information about the failed injection including the dependency chain
|
|
10
|
+
* and the original error. Helps diagnose circular dependencies, missing providers, and
|
|
11
|
+
* configuration issues in the DI system.
|
|
12
|
+
*
|
|
13
|
+
* ### Usage
|
|
14
|
+
*
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import {InjectionError} from "@tsed/di";
|
|
17
|
+
*
|
|
18
|
+
* try {
|
|
19
|
+
* injector.invoke(MyService);
|
|
20
|
+
* } catch (error) {
|
|
21
|
+
* if (error instanceof InjectionError) {
|
|
22
|
+
* console.log("Dependency chain:", error.tokens);
|
|
23
|
+
* console.log("Original error:", error.origin);
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
6
30
|
export class InjectionError extends Error {
|
|
7
31
|
constructor(token, origin) {
|
|
8
32
|
super(isString(origin) ? origin : "");
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { classOf } from "@tsed/core/utils/classOf.js";
|
|
2
2
|
import { nameOf } from "@tsed/core/utils/nameOf.js";
|
|
3
|
+
/**
|
|
4
|
+
* Error thrown when an invalid token is used for property injection.
|
|
5
|
+
*
|
|
6
|
+
* Typically indicates a circular reference, missing import, or undefined token
|
|
7
|
+
* in property decorators like `@Inject()` or `@Constant()`.
|
|
8
|
+
*
|
|
9
|
+
* ### Common causes
|
|
10
|
+
*
|
|
11
|
+
* - Circular dependency between classes
|
|
12
|
+
* - Missing or incorrect import statement
|
|
13
|
+
* - Using `undefined` as a token
|
|
14
|
+
* - Forward reference not properly handled
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
3
18
|
export class InvalidPropertyTokenError extends Error {
|
|
4
19
|
constructor(target, propertyKey) {
|
|
5
20
|
super(`Object isn't a valid token. Please check the token set on ${nameOf(classOf(target))}.${propertyKey}.\n- Check that it is not a circular reference.\n- Check that the token (class or symbol) exists`);
|
|
@@ -1,21 +1,34 @@
|
|
|
1
1
|
import { injector } from "./injector.js";
|
|
2
2
|
import { invokeOptions, localsContainer } from "./localsContainer.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Programmatically inject a provider instance.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Resolves and returns a provider instance using the global injector.
|
|
7
|
+
* Useful for injecting dependencies outside of decorators or in property initializers.
|
|
8
|
+
*
|
|
9
|
+
* ### Usage
|
|
7
10
|
*
|
|
8
11
|
* ```typescript
|
|
12
|
+
* import {inject, Injectable} from "@tsed/di";
|
|
13
|
+
*
|
|
9
14
|
* @Injectable()
|
|
10
15
|
* export class MyService {
|
|
16
|
+
* // Property injection
|
|
11
17
|
* connection = inject(CONNECTION);
|
|
18
|
+
*
|
|
19
|
+
* // Function injection
|
|
20
|
+
* getData() {
|
|
21
|
+
* const api = inject(ApiService);
|
|
22
|
+
* return api.fetch();
|
|
23
|
+
* }
|
|
12
24
|
* }
|
|
13
25
|
* ```
|
|
14
26
|
*
|
|
15
|
-
* @
|
|
16
|
-
* @param
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
27
|
+
* @typeParam TokenType The type of the injected provider
|
|
28
|
+
* @param token The provider token to resolve
|
|
29
|
+
* @param opts Optional invocation options (locals, rebuild, useOpts)
|
|
30
|
+
* @returns The resolved provider instance
|
|
31
|
+
* @public
|
|
19
32
|
*/
|
|
20
33
|
export function inject(token, opts) {
|
|
21
34
|
return injector().resolve(token, {
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { injector } from "./injector.js";
|
|
2
2
|
import { localsContainer } from "./localsContainer.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* Inject all providers matching a given token type.
|
|
5
|
+
*
|
|
6
|
+
* Resolves multiple provider instances that share the same type or group token.
|
|
7
|
+
* Useful for getting all providers of a specific category (e.g., all controllers, all middleware).
|
|
8
|
+
*
|
|
9
|
+
* ### Usage
|
|
10
|
+
*
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import {injectMany, ProviderType} from "@tsed/di";
|
|
13
|
+
*
|
|
14
|
+
* // Get all controllers
|
|
15
|
+
* const controllers = injectMany(ProviderType.CONTROLLER);
|
|
16
|
+
*
|
|
17
|
+
* // Get all providers of a custom type
|
|
18
|
+
* const plugins = injectMany(Symbol.for("PLUGIN"));
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @typeParam T The type of instances to return
|
|
22
|
+
* @param token The injection token or type to resolve
|
|
23
|
+
* @param opts Optional invocation options
|
|
24
|
+
* @param opts.useOpts Options passed to instance creation
|
|
25
|
+
* @param opts.rebuild Whether to rebuild instances
|
|
26
|
+
* @param opts.locals Local container overrides
|
|
10
27
|
* @returns Array of resolved instances
|
|
28
|
+
* @public
|
|
11
29
|
*/
|
|
12
30
|
export function injectMany(token, opts) {
|
|
13
31
|
return injector().getMany(token, { ...opts, locals: opts?.locals || localsContainer() });
|
|
@@ -1,10 +1,67 @@
|
|
|
1
1
|
import { ProviderType } from "../domain/ProviderType.js";
|
|
2
2
|
import { providerBuilder } from "../utils/providerBuilder.js";
|
|
3
3
|
const Props = ["type", "scope", "path", "alias", "hooks", "deps", "imports", "configuration", "priority"];
|
|
4
|
+
/**
|
|
5
|
+
* Fluent builder for registering providers programmatically.
|
|
6
|
+
*
|
|
7
|
+
* Creates or configures a provider with the specified options.
|
|
8
|
+
* Can be chained with additional configuration methods.
|
|
9
|
+
*
|
|
10
|
+
* ### Usage
|
|
11
|
+
*
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import {injectable} from "@tsed/di";
|
|
14
|
+
*
|
|
15
|
+
* injectable(MyService)
|
|
16
|
+
* .scope(ProviderScope.REQUEST)
|
|
17
|
+
* .deps([DatabaseService])
|
|
18
|
+
* .build();
|
|
19
|
+
*
|
|
20
|
+
* // With factory
|
|
21
|
+
* injectable("CONFIG")
|
|
22
|
+
* .factory(() => loadConfig())
|
|
23
|
+
* .build();
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
4
28
|
export const injectable = providerBuilder(Props);
|
|
29
|
+
/**
|
|
30
|
+
* Fluent builder for registering interceptor providers.
|
|
31
|
+
*
|
|
32
|
+
* Specialized version of `injectable` that automatically sets the provider type to `INTERCEPTOR`.
|
|
33
|
+
*
|
|
34
|
+
* ### Usage
|
|
35
|
+
*
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import {interceptor} from "@tsed/di";
|
|
38
|
+
*
|
|
39
|
+
* interceptor(LogInterceptor).build();
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
5
44
|
export const interceptor = providerBuilder(Props, {
|
|
6
45
|
type: ProviderType.INTERCEPTOR
|
|
7
46
|
});
|
|
47
|
+
/**
|
|
48
|
+
* Fluent builder for registering controller providers.
|
|
49
|
+
*
|
|
50
|
+
* Specialized version of `injectable` that automatically sets the provider type to `CONTROLLER`
|
|
51
|
+
* and supports controller-specific options like middlewares.
|
|
52
|
+
*
|
|
53
|
+
* ### Usage
|
|
54
|
+
*
|
|
55
|
+
* ```typescript
|
|
56
|
+
* import {controller} from "@tsed/di";
|
|
57
|
+
*
|
|
58
|
+
* controller(UsersController)
|
|
59
|
+
* .middlewares({useBefore: [AuthMiddleware]})
|
|
60
|
+
* .build();
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
8
65
|
export const controller = providerBuilder([...Props, "middlewares"], {
|
|
9
66
|
type: ProviderType.CONTROLLER
|
|
10
67
|
});
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { InjectorService } from "../services/InjectorService.js";
|
|
2
2
|
let globalInjector = new InjectorService();
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Get the global injector service instance.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Returns the singleton instance of `InjectorService` managing all registered providers.
|
|
7
|
+
* Use this to access the DI container programmatically.
|
|
8
|
+
*
|
|
9
|
+
* ### Usage
|
|
7
10
|
*
|
|
8
11
|
* ```typescript
|
|
9
12
|
* import {injector, Injectable} from "@tsed/di";
|
|
@@ -11,12 +14,28 @@ let globalInjector = new InjectorService();
|
|
|
11
14
|
* @Injectable()
|
|
12
15
|
* class MyService {
|
|
13
16
|
* injector = injector();
|
|
17
|
+
*
|
|
18
|
+
* getService() {
|
|
19
|
+
* return injector().get(OtherService);
|
|
20
|
+
* }
|
|
14
21
|
* }
|
|
15
22
|
* ```
|
|
23
|
+
*
|
|
24
|
+
* @returns The global injector service instance
|
|
25
|
+
* @public
|
|
16
26
|
*/
|
|
17
27
|
export function injector() {
|
|
18
28
|
return globalInjector;
|
|
19
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Destroy the current injector and create a fresh instance.
|
|
32
|
+
*
|
|
33
|
+
* Calls the `destroy()` lifecycle hook on all providers and resets the global injector.
|
|
34
|
+
* Primarily used in testing to reset the DI container between tests.
|
|
35
|
+
*
|
|
36
|
+
* @returns Promise that resolves when destruction is complete
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
20
39
|
export async function destroyInjector() {
|
|
21
40
|
await globalInjector.destroy();
|
|
22
41
|
globalInjector = new InjectorService();
|
|
@@ -2,7 +2,30 @@ import { isFunction } from "@tsed/core/utils/isFunction.js";
|
|
|
2
2
|
import { inject } from "./inject.js";
|
|
3
3
|
import { injector } from "./injector.js";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Lazily load and inject a provider from a dynamic import.
|
|
6
|
+
*
|
|
7
|
+
* Loads the provider module asynchronously, registers it if needed, calls `$onInit` if present,
|
|
8
|
+
* and returns the resolved instance. Useful for code splitting and lazy loading dependencies.
|
|
9
|
+
*
|
|
10
|
+
* ### Usage
|
|
11
|
+
*
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import {lazyInject} from "@tsed/di";
|
|
14
|
+
*
|
|
15
|
+
* // Lazy load a service
|
|
16
|
+
* const service = await lazyInject(() => import("./HeavyService"));
|
|
17
|
+
*
|
|
18
|
+
* // Use in a method
|
|
19
|
+
* async loadPlugin() {
|
|
20
|
+
* const plugin = await lazyInject(() => import("./plugins/MyPlugin"));
|
|
21
|
+
* return plugin.initialize();
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @typeParam Token The type of the provider to inject
|
|
26
|
+
* @param factory Function returning a dynamic import promise with a default export
|
|
27
|
+
* @returns Promise resolving to the provider instance
|
|
28
|
+
* @public
|
|
6
29
|
*/
|
|
7
30
|
export async function lazyInject(factory) {
|
|
8
31
|
const { default: token } = await factory();
|
|
@@ -15,6 +38,30 @@ export async function lazyInject(factory) {
|
|
|
15
38
|
}
|
|
16
39
|
return injector().get(token);
|
|
17
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Attempt to lazily load and inject a provider, returning undefined on failure.
|
|
43
|
+
*
|
|
44
|
+
* Similar to `lazyInject` but catches errors and returns undefined instead of throwing.
|
|
45
|
+
* Useful for optional dependencies that may not be available.
|
|
46
|
+
*
|
|
47
|
+
* ### Usage
|
|
48
|
+
*
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import {optionalLazyInject} from "@tsed/di";
|
|
51
|
+
*
|
|
52
|
+
* // Try to load optional plugin
|
|
53
|
+
* const plugin = await optionalLazyInject(() => import("./optional/Plugin"));
|
|
54
|
+
*
|
|
55
|
+
* if (plugin) {
|
|
56
|
+
* plugin.activate();
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @typeParam Token The type of the provider to inject
|
|
61
|
+
* @param factory Function returning a dynamic import promise with a default export
|
|
62
|
+
* @returns Promise resolving to the provider instance or undefined if loading fails
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
18
65
|
export async function optionalLazyInject(factory) {
|
|
19
66
|
try {
|
|
20
67
|
return await lazyInject(factory);
|
|
@@ -5,7 +5,31 @@ let globalLocals;
|
|
|
5
5
|
let globalInvOpts = {};
|
|
6
6
|
const stagedLocals = [];
|
|
7
7
|
/**
|
|
8
|
-
* Get the locals container
|
|
8
|
+
* Get or create the current locals container for request-scoped providers.
|
|
9
|
+
*
|
|
10
|
+
* Returns the global locals container used for storing request-scoped provider instances.
|
|
11
|
+
* Can optionally create a new container with custom providers.
|
|
12
|
+
*
|
|
13
|
+
* ### Usage
|
|
14
|
+
*
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import {localsContainer} from "@tsed/di";
|
|
17
|
+
*
|
|
18
|
+
* // Get current locals
|
|
19
|
+
* const locals = localsContainer();
|
|
20
|
+
*
|
|
21
|
+
* // Create with custom providers
|
|
22
|
+
* const locals = localsContainer({
|
|
23
|
+
* providers: [{token: MyService, use: mockInstance}],
|
|
24
|
+
* rebuild: true
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @param options Configuration options
|
|
29
|
+
* @param options.providers Optional array of provider overrides
|
|
30
|
+
* @param options.rebuild Whether to mark providers for rebuilding
|
|
31
|
+
* @returns The locals container instance
|
|
32
|
+
* @public
|
|
9
33
|
*/
|
|
10
34
|
export function localsContainer({ providers, rebuild } = {}) {
|
|
11
35
|
if (!globalLocals || providers) {
|
|
@@ -26,7 +50,12 @@ export function invokeOptions() {
|
|
|
26
50
|
return { ...globalInvOpts };
|
|
27
51
|
}
|
|
28
52
|
/**
|
|
29
|
-
*
|
|
53
|
+
* Detach and stage the current locals container.
|
|
54
|
+
*
|
|
55
|
+
* Removes the global locals reference and saves it for cleanup.
|
|
56
|
+
* Used internally to manage request scope lifecycle.
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
30
59
|
*/
|
|
31
60
|
export function detachLocalsContainer() {
|
|
32
61
|
globalLocals && stagedLocals.push(globalLocals);
|