Rename DIContainer to TSInjex and refactor interfaces
- Renamed DIContainer class and related references to TSInjex to better indicate its purpose as a TypeScript-based dependency injection container. - Extracted IDependency interface to a separate file to improve modularity. - Split the ITSInjex interface into ITSInjexRegister and ITSInjexResolve, then extended them in a new ITSInjex interface to clarify the separation of concerns. - Updated tests and decorators to reflect the renaming and interface changes. - Adjusted helper, functions, and index export to align with the new TSInjex structure.
This commit is contained in:
@@ -1,27 +1,13 @@
|
|||||||
import { ImplementsStatic } from './helper/ImplementsStatic';
|
import { ImplementsStatic } from './helper/ImplementsStatic';
|
||||||
import { ITSInjex, ITSInjex_ } from './interfaces/IDIContainer';
|
import { IDependency } from './interfaces/IDependency';
|
||||||
|
import { ITSInjex, ITSInjex_ } from './interfaces/ITSInjex';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependency Entry Interface
|
* **TSInjex**: Dependency Injection Container
|
||||||
*/
|
|
||||||
interface IDependency {
|
|
||||||
/**
|
|
||||||
* The dependency itself
|
|
||||||
*/
|
|
||||||
dependency: unknown;
|
|
||||||
/**
|
|
||||||
* If true, the dependency is deprecated => a warning
|
|
||||||
* is logged when the dependency is resolved
|
|
||||||
*/
|
|
||||||
deprecated?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dependency Injection Container
|
|
||||||
*/
|
*/
|
||||||
@ImplementsStatic<ITSInjex_>()
|
@ImplementsStatic<ITSInjex_>()
|
||||||
export class DIContainer implements ITSInjex {
|
export class TSInjex implements ITSInjex {
|
||||||
private static _instance: DIContainer;
|
private static _instance: TSInjex;
|
||||||
private readonly _dependencies = new Map<string, IDependency>();
|
private readonly _dependencies = new Map<string, IDependency>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,22 +23,47 @@ export class DIContainer implements ITSInjex {
|
|||||||
*/
|
*/
|
||||||
public static getInstance(): ITSInjex {
|
public static getInstance(): ITSInjex {
|
||||||
if (this._instance == null) {
|
if (this._instance == null) {
|
||||||
this._instance = new DIContainer();
|
this._instance = new TSInjex();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._instance;
|
return this._instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
* @see {@link ITSInjexRegister.register}
|
||||||
|
*/
|
||||||
|
public static register<T>(
|
||||||
|
identifier: string,
|
||||||
|
dependency: T,
|
||||||
|
deprecated = false,
|
||||||
|
): void {
|
||||||
|
(TSInjex.getInstance() as TSInjex)._dependencies.set(identifier, {
|
||||||
|
dependency: dependency,
|
||||||
|
deprecated: deprecated,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
* @see {@link ITSInjexResolve.resolve}
|
||||||
|
*/
|
||||||
|
public static resolve<T>(
|
||||||
|
identifier: string,
|
||||||
|
necessary = true,
|
||||||
|
): T | undefined {
|
||||||
|
return (TSInjex.getInstance() as TSInjex).resolve<T>(
|
||||||
|
identifier,
|
||||||
|
necessary,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region IDIContainer
|
//#region IDIContainer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a dependency
|
* @inheritdoc
|
||||||
* @param identifier The identifier of the dependency
|
|
||||||
* @param dependency The dependency to register
|
|
||||||
* @param deprecated If true, the dependency is deprecated => a warning
|
|
||||||
* is logged when the dependency is resolved
|
|
||||||
*/
|
*/
|
||||||
public register<T>(
|
public register<T>(
|
||||||
identifier: string,
|
identifier: string,
|
||||||
@@ -66,11 +77,7 @@ export class DIContainer implements ITSInjex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a dependency
|
* @inheritdoc
|
||||||
* @param identifier The identifier of the dependency
|
|
||||||
* @param necessary If true, throws an error if the dependency is not found
|
|
||||||
* @returns The resolved dependency or undefined if the dependency is not found (if necessary is false)
|
|
||||||
* @throws Error if the dependency is not found (if necessary is true)
|
|
||||||
*/
|
*/
|
||||||
public resolve<T>(identifier: string, necessary = true): T | undefined {
|
public resolve<T>(identifier: string, necessary = true): T | undefined {
|
||||||
const dependency = this._dependencies.get(identifier);
|
const dependency = this._dependencies.get(identifier);
|
@@ -1,4 +1,4 @@
|
|||||||
import { test_IDIContainer } from './IDIContainer.spec';
|
import { test_IDIContainer } from './IDIContainer.spec';
|
||||||
import { DIContainer } from '../DIContainer';
|
import { TSInjex } from '../TSInjex';
|
||||||
|
|
||||||
test_IDIContainer(DIContainer);
|
test_IDIContainer(TSInjex);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { ITSInjex_, ITSInjex } from '../interfaces/IDIContainer';
|
import { ITSInjex_, ITSInjex } from '../interfaces/ITSInjex';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the implementation of a DIContainer
|
* Test the implementation of a DIContainer
|
||||||
@@ -24,10 +24,21 @@ export function test_IDIContainer(Container: ITSInjex_): void {
|
|||||||
expect(resolvedDependency).toBe(dependency);
|
expect(resolvedDependency).toBe(dependency);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error when resolving a non-registered dependency', () => {
|
it('should register and resolve a dependency static', () => {
|
||||||
|
const identifier = 'myDependency';
|
||||||
|
const dependency = { value: 42 };
|
||||||
|
|
||||||
|
Container.register(identifier, dependency);
|
||||||
|
|
||||||
|
const resolvedDependency =
|
||||||
|
Container.resolve<typeof dependency>(identifier);
|
||||||
|
expect(resolvedDependency).toBe(dependency);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when resolving a non-registered dependency static', () => {
|
||||||
const identifier = 'nonExistentDependency';
|
const identifier = 'nonExistentDependency';
|
||||||
|
|
||||||
expect(() => container.resolve<unknown>(identifier)).toThrow();
|
expect(() => Container.resolve<unknown>(identifier)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add more tests as necessary
|
// Add more tests as necessary
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DIContainer } from '../DIContainer';
|
import { TSInjex } from '../TSInjex';
|
||||||
import { InitDelegate } from '../types/InitDelegate';
|
import { InitDelegate } from '../types/InitDelegate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,7 +12,7 @@ import { InitDelegate } from '../types/InitDelegate';
|
|||||||
* - If `true`, an error will be thrown if the dependency cannot be resolved.
|
* - If `true`, an error will be thrown if the dependency cannot be resolved.
|
||||||
* - If `false`, `undefined` will be returned if the dependency cannot be resolved.
|
* - If `false`, `undefined` will be returned if the dependency cannot be resolved.
|
||||||
* @returns A decorator function to be applied on the class property.
|
* @returns A decorator function to be applied on the class property.
|
||||||
* @see {@link DIContainer}
|
* @see {@link TSInjex}
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* class MyClass {
|
* class MyClass {
|
||||||
@@ -37,7 +37,7 @@ export function Inject<T, U>(
|
|||||||
// Unique symbol to store the private property
|
// Unique symbol to store the private property
|
||||||
const privatePropertyKey: unique symbol = Symbol();
|
const privatePropertyKey: unique symbol = Symbol();
|
||||||
// Get the DI container instance
|
// Get the DI container instance
|
||||||
const diContainer = DIContainer.getInstance();
|
const diContainer = TSInjex.getInstance();
|
||||||
|
|
||||||
// Function to evaluate the dependency lazily
|
// Function to evaluate the dependency lazily
|
||||||
// to avoid circular dependencies, not found dependencies, etc.
|
// to avoid circular dependencies, not found dependencies, etc.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DIContainer } from '../DIContainer';
|
import { TSInjex } from '../TSInjex';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A decorator to register a class in the DI (Dependency Injection) container.
|
* A decorator to register a class in the DI (Dependency Injection) container.
|
||||||
@@ -20,7 +20,7 @@ export function Register<
|
|||||||
>(identifier: string, deprecated?: boolean) {
|
>(identifier: string, deprecated?: boolean) {
|
||||||
return function (constructor: TargetType, ...args: unknown[]): void {
|
return function (constructor: TargetType, ...args: unknown[]): void {
|
||||||
// Get the instance of the DI container
|
// Get the instance of the DI container
|
||||||
const diContainer = DIContainer.getInstance();
|
const diContainer = TSInjex.getInstance();
|
||||||
|
|
||||||
// Register the class in the DI container
|
// Register the class in the DI container
|
||||||
diContainer.register(identifier, constructor, deprecated);
|
diContainer.register(identifier, constructor, deprecated);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DIContainer } from '../DIContainer';
|
import { TSInjex } from '../TSInjex';
|
||||||
import { InitDelegate } from '../types/InitDelegate';
|
import { InitDelegate } from '../types/InitDelegate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +28,7 @@ export function RegisterInstance<
|
|||||||
) {
|
) {
|
||||||
return function (constructor: TargetType, ...args: unknown[]): void {
|
return function (constructor: TargetType, ...args: unknown[]): void {
|
||||||
// Get the instance of the DI container
|
// Get the instance of the DI container
|
||||||
const diContainer = DIContainer.getInstance();
|
const diContainer = TSInjex.getInstance();
|
||||||
|
|
||||||
// Create a proxy to instantiate the class when needed (Lazy Initialization)
|
// Create a proxy to instantiate the class when needed (Lazy Initialization)
|
||||||
let lazyProxy: unknown = new Proxy(
|
let lazyProxy: unknown = new Proxy(
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
import { DIContainer } from 'src/DIContainer';
|
import { TSInjex } from 'src/TSInjex';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a dependency.
|
* Register a dependency.
|
||||||
* @param identifier The identifier of the dependency.
|
* @param identifier The identifier of the dependency.
|
||||||
* @param dependency The dependency to register.
|
* @param dependency The dependency to register.
|
||||||
*/
|
*/
|
||||||
export function Register<T>(identifier: string, dependency: T): void;
|
export function register<T>(identifier: string, dependency: T): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a dependency.
|
* Register a dependency.
|
||||||
@@ -13,7 +13,7 @@ export function Register<T>(identifier: string, dependency: T): void;
|
|||||||
* @param dependency The dependency to register.
|
* @param dependency The dependency to register.
|
||||||
* @param deprecated A warning is logged when the dependency is resolved.
|
* @param deprecated A warning is logged when the dependency is resolved.
|
||||||
*/
|
*/
|
||||||
export function Register<T>(
|
export function register<T>(
|
||||||
identifier: string,
|
identifier: string,
|
||||||
dependency: T,
|
dependency: T,
|
||||||
deprecated?: true,
|
deprecated?: true,
|
||||||
@@ -26,10 +26,10 @@ export function Register<T>(
|
|||||||
* @param deprecated If true, the dependency is deprecated => a warning
|
* @param deprecated If true, the dependency is deprecated => a warning
|
||||||
* is logged when the dependency is resolved.
|
* is logged when the dependency is resolved.
|
||||||
*/
|
*/
|
||||||
export function Register<T>(
|
export function register<T>(
|
||||||
identifier: string,
|
identifier: string,
|
||||||
dependency: T,
|
dependency: T,
|
||||||
deprecated?: boolean,
|
deprecated?: boolean,
|
||||||
): void {
|
): void {
|
||||||
DIContainer.getInstance().register(identifier, dependency, deprecated);
|
TSInjex.getInstance().register(identifier, dependency, deprecated);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { DIContainer } from '../DIContainer';
|
|
||||||
import { DependencyResolutionError } from '../interfaces/Exceptions';
|
import { DependencyResolutionError } from '../interfaces/Exceptions';
|
||||||
|
import { TSInjex } from '../TSInjex';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a dependency.
|
* Resolve a dependency.
|
||||||
@@ -7,7 +7,7 @@ import { DependencyResolutionError } from '../interfaces/Exceptions';
|
|||||||
* @returns The resolved dependency.
|
* @returns The resolved dependency.
|
||||||
* @throws A {@link DependencyResolutionError} if the dependency is not found.
|
* @throws A {@link DependencyResolutionError} if the dependency is not found.
|
||||||
*/
|
*/
|
||||||
export function Resolve<T>(identifier: string): T;
|
export function resolve<T>(identifier: string): T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a dependency
|
* Resolve a dependency
|
||||||
@@ -15,7 +15,7 @@ export function Resolve<T>(identifier: string): T;
|
|||||||
* @param necessary The dependency is **not** necessary.
|
* @param necessary The dependency is **not** necessary.
|
||||||
* @returns The resolved dependency or undefined if the dependency is not found.
|
* @returns The resolved dependency or undefined if the dependency is not found.
|
||||||
*/
|
*/
|
||||||
export function Resolve<T>(identifier: string, necessary: false): T | undefined;
|
export function resolve<T>(identifier: string, necessary: false): T | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a dependency.
|
* Resolve a dependency.
|
||||||
@@ -25,9 +25,9 @@ export function Resolve<T>(identifier: string, necessary: false): T | undefined;
|
|||||||
* and not found, or throws an error if the dependency is necessary and not found.
|
* and not found, or throws an error if the dependency is necessary and not found.
|
||||||
* @throws A {@link DependencyResolutionError} if the dependency is not found and necessary.
|
* @throws A {@link DependencyResolutionError} if the dependency is not found and necessary.
|
||||||
*/
|
*/
|
||||||
export function Resolve<T>(
|
export function resolve<T>(
|
||||||
identifier: string,
|
identifier: string,
|
||||||
necessary?: boolean,
|
necessary?: boolean,
|
||||||
): T | undefined {
|
): T | undefined {
|
||||||
return DIContainer.getInstance().resolve<T>(identifier, necessary);
|
return TSInjex.getInstance().resolve<T>(identifier, necessary);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
export * from './TSInjex';
|
||||||
|
|
||||||
|
export * from './decorators/Inject';
|
||||||
|
export * from './decorators/Register';
|
||||||
|
export * from './decorators/RegisterInstance';
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { ITSInjex } from './IDIContainer';
|
import { ITSInjex } from './ITSInjex';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General error class for {@link ITSInjex} interface.
|
* General error class for {@link ITSInjex} interface.
|
||||||
|
14
src/interfaces/IDependency.ts
Normal file
14
src/interfaces/IDependency.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Dependency Entry Interface
|
||||||
|
*/
|
||||||
|
export interface IDependency {
|
||||||
|
/**
|
||||||
|
* The dependency itself
|
||||||
|
*/
|
||||||
|
dependency: unknown;
|
||||||
|
/**
|
||||||
|
* If true, the dependency is deprecated => a warning
|
||||||
|
* is logged when the dependency is resolved
|
||||||
|
*/
|
||||||
|
deprecated?: boolean;
|
||||||
|
}
|
@@ -1,17 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
* Static Dependency Injection Container Interface
|
* Static TSInjex Interface
|
||||||
*/
|
*/
|
||||||
export interface ITSInjex_ {
|
export interface ITSInjex_ extends ITSInjexRegister, ITSInjexResolve {
|
||||||
/**
|
/**
|
||||||
* Get the **singleton** Dependency Injection Container
|
* Get the **singleton** TSInjex instance.
|
||||||
*/
|
*/
|
||||||
getInstance(): ITSInjex;
|
getInstance(): ITSInjex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dependency Injection Container Interface
|
* Register method for static and instance Dependency Injection Container.
|
||||||
*/
|
*/
|
||||||
export interface ITSInjex {
|
export interface ITSInjexRegister {
|
||||||
/**
|
/**
|
||||||
* Register a dependency.
|
* Register a dependency.
|
||||||
* @param identifier The identifier of the dependency.
|
* @param identifier The identifier of the dependency.
|
||||||
@@ -34,7 +34,12 @@ export interface ITSInjex {
|
|||||||
* @param deprecated No warning is logged when the dependency is resolved.
|
* @param deprecated No warning is logged when the dependency is resolved.
|
||||||
*/
|
*/
|
||||||
register<T>(identifier: string, dependency: T, deprecated?: false): void;
|
register<T>(identifier: string, dependency: T, deprecated?: false): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve method for static and instance Dependency Injection Container.
|
||||||
|
*/
|
||||||
|
export interface ITSInjexResolve {
|
||||||
/**
|
/**
|
||||||
* Resolve a dependency
|
* Resolve a dependency
|
||||||
* @param identifier The identifier of the dependency
|
* @param identifier The identifier of the dependency
|
||||||
@@ -58,3 +63,8 @@ export interface ITSInjex {
|
|||||||
*/
|
*/
|
||||||
resolve<T>(identifier: string, necessary?: false): T | undefined;
|
resolve<T>(identifier: string, necessary?: false): T | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TSInjex Interface
|
||||||
|
*/
|
||||||
|
export interface ITSInjex extends ITSInjexRegister, ITSInjexResolve {}
|
Reference in New Issue
Block a user