Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 1x 1x 1x 10x 10x 9x 7x 3x 1x 7x 6x 4x 2x 2x 7x 14x 14x 3x 2x 1x 3x 3x | import { TSinjex } from '../classes/TSinjex.js'; import { DependencyResolutionError, InitializationError, InjectorError, NoInstantiationMethodError, } from '../interfaces/Exceptions.js'; import { Identifier } from '../types/Identifier.js'; import { InitDelegate } from '../types/InitDelegate.js'; /** * A function to inject a dependency from a DI (Dependency Injection) container into a variable. * @template T The type of the dependency to be injected. * @template U The type of the property to be injected. * @param identifier The identifier used to resolve the class in the DI container. * @see {@link Identifier} for more information on identifiers. * @param init Optional an initializer function to transform the dependency before injection * or true to instantiate the dependency if it has a constructor. * @see {@link InitDelegate} for more information on initializer functions. * @param isNecessary If true, throws an error if the dependency is not found. * @returns The resolved dependency or undefined if the dependency is not necessary * and not found, or throws an error if the dependency is necessary and not found. * @throws **Only throws errors if the dependency is necessary.** * @throws A {@link DependencyResolutionError} if the dependency is not found. * @throws A {@link InjectorError} if an error occurs during the injection process. * @throws A {@link NoInstantiationMethodError} if the dependency does not have a constructor. * @throws An {@link InitializationError} if an error occurs during the initialization process. * @example * ```ts * let myDependency = inject<MyDependency>('MyDependencyIdentifier'); * ``` * @example * ```ts * let logger = inject<ILogger>('ILogger_', (x: ILogger_) => x.getLogger('Tags'), false); * ``` */ export function inject<T, U>( identifier: Identifier, init?: InitDelegate<T, U> | true, isNecessary = true, ): T | U | undefined { let instance: T | U | undefined; const dependency: T | undefined = tryAndCatch( () => TSinjex.getInstance().resolve<T>(identifier, isNecessary), isNecessary, identifier, DependencyResolutionError, ); if (dependency != null) { const initFunction: (() => U) | undefined = typeof init === 'function' && dependency != null ? (): U => init(dependency) : init === true && hasConstructor(dependency) ? (): U => new dependency() as U : undefined; if (init == null) instance = dependency; else if (initFunction != null) instance = tryAndCatch( initFunction, isNecessary, identifier, InitializationError, ); else if (isNecessary) throw new NoInstantiationMethodError(identifier); } else Iif (isNecessary) throw new DependencyResolutionError(identifier); return instance as T | U; } /** * Tries to execute a function and catches any errors that occur. * If the function is necessary and an error occurs, it throws the error * with the specified error class and identifier. * @param fn The function to execute. * @param necessary If true, throws an error if an error occurs. * @param identifier The identifier of the dependency. * @param errorClass The error class to throw if an error occurs. * @returns The result of the function or undefined if an error occurs and the function is not necessary. */ function tryAndCatch<ReturnType, ErrorType>( fn: () => ReturnType, necessary: boolean, identifier?: Identifier, errorClass?: ErrorType, ): ReturnType | undefined { try { return fn(); } catch (error) { if (necessary) throw new (errorClass != null ? errorClass : error)( identifier ?? 'not specified', error, ); else return undefined; } } /** * Checks if an object has a constructor. * @param obj The object to check. * @returns True if the object has a constructor, false otherwise. */ function hasConstructor<T>(obj: T): obj is T & { new (): unknown } { const _obj = obj as unknown as { prototype?: { constructor?: unknown } }; return ( _obj?.prototype != null && typeof _obj.prototype.constructor === 'function' ); } |