import {
Injectable,
InjectableRegistryImp,
InjectablesRegistry,
} from "./registry";
/**
* @description Central registry for managing injectable dependencies.
* @summary Static class holding the access to the injectables functions. Provides methods for registering,
* retrieving, and building injectable objects.
* @template T Type of the injectable object
*
* @class Injectables
*
* @example
* // Define an injectable class
* @injectable()
* class MyService {
* doSomething() {
* return 'Hello World';
* }
* }
*
* // Inject the service into another class
* class MyComponent {
* @inject()
* private service!: MyService;
*
* useService() {
* return this.service.doSomething();
* }
* }
*
* @mermaid
* sequenceDiagram
* participant Client
* participant Injectables
* participant Registry
*
* Client->>Injectables: register(MyService)
* Injectables->>Registry: register(MyService)
* Registry-->>Injectables: void
*
* Client->>Injectables: get("MyService")
* Injectables->>Registry: get("MyService")
* Registry-->>Injectables: MyService instance
* Injectables-->>Client: MyService instance
*/
export class Injectables {
private static actingInjectablesRegistry?: InjectablesRegistry = undefined;
private constructor() {}
/**
* @description Fetches an injectable instance by its registered name.
* @summary Retrieves the named {@link Injectable} from the registry. If the injectable is a singleton,
* returns the existing instance. Otherwise, creates a new instance.
* @template T Type of the injectable object to retrieve
* @param {string} name The registered name of the injectable to retrieve
* @param {any[]} args Constructor arguments to pass when instantiating the injectable
* @return {Injectable<T> | undefined} The injectable instance or undefined if not found
*/
static get<T>(name: string, ...args: any[]): Injectable<T> | undefined {
return Injectables.getRegistry().get(name, ...args);
}
/**
* @description Adds a class or object to the injectable registry.
* @summary Registers an injectable constructor or instance with the registry, making it available for injection.
* @template T Type of the injectable object to register
* @param {Injectable<T>} constructor The class constructor or object instance to register
* @param {any[]} args Additional arguments for registration (category, singleton flag, etc.)
* @return {void}
*/
static register<T>(constructor: Injectable<T>, ...args: any[]): void {
return Injectables.getRegistry().register(constructor, ...args);
}
/**
* @description Creates a new instance of an injectable class.
* @summary Instantiates an injectable class using its constructor and the provided arguments.
* @template T Type of the object to build
* @param {Record<string, any>} obj Object containing the name of the injectable to build
* @param {any[]} args Constructor arguments to pass when instantiating the injectable
* @return {T} The newly created instance
*/
static build<T>(obj: Record<string, any>, ...args: any[]): T {
return Injectables.getRegistry().build(obj, ...args);
}
/**
* @description Replaces the current registry implementation.
* @summary Sets a new {@link InjectablesRegistry} implementation, allowing for custom registry behavior.
* @param {InjectablesRegistry} operationsRegistry The new implementation of Registry to use
* @return {void}
*/
static setRegistry(operationsRegistry: InjectablesRegistry) {
Injectables.actingInjectablesRegistry = operationsRegistry;
}
/**
* @description Provides access to the current registry instance.
* @summary Returns the current {@link InjectablesRegistry} or creates a default one if none exists.
* @return {InjectablesRegistry} The current registry instance
*/
private static getRegistry() {
if (!Injectables.actingInjectablesRegistry)
Injectables.actingInjectablesRegistry = new InjectableRegistryImp();
return Injectables.actingInjectablesRegistry;
}
/**
* @description Clears all registered injectables.
* @summary Resets the registry to a clean state by creating a new empty registry instance.
* @return {void}
*/
static reset() {
Injectables.setRegistry(new InjectableRegistryImp());
}
/**
* @description Removes specific injectables from the registry based on a pattern.
* @summary Selectively resets the registry by removing only the injectables whose names match the provided pattern.
* @param {string | RegExp} match A string or regular expression pattern to match against injectable names
* @return {void}
*/
static selectiveReset(match: string | RegExp) {
const regexp = typeof match === "string" ? new RegExp(match) : match;
(Injectables.actingInjectablesRegistry as any)["cache"] = Object.entries(
(Injectables.actingInjectablesRegistry as any)["cache"]
).reduce((accum: Record<string, any>, [key, val]) => {
if (!key.match(regexp)) accum[key] = val;
return accum;
}, {});
}
}
Source