diff --git a/package.json b/package.json index 7151473..e8c74a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@extollo/lib", - "version": "0.13.9", + "version": "0.13.10", "description": "The framework library that lifts up your code.", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/di/Container.ts b/src/di/Container.ts index 3b2d55b..0580813 100644 --- a/src/di/Container.ts +++ b/src/di/Container.ts @@ -8,7 +8,16 @@ import { TypedDependencyKey, } from './types' import {AbstractFactory} from './factory/AbstractFactory' -import {Awaitable, collect, Collection, ErrorWithContext, globalRegistry, hasOwnProperty, logIfDebugging} from '../util' +import { + Awaitable, + collect, + Collection, + ErrorWithContext, + globalRegistry, + hasOwnProperty, + logIfDebugging, + withErrorContext, +} from '../util' import {Factory} from './factory/Factory' import {DuplicateFactoryKeyError} from './error/DuplicateFactoryKeyError' import {ClosureFactory} from './factory/ClosureFactory' @@ -376,7 +385,7 @@ export class Container { /** * Resolve the dependency key. If a singleton value for that key already exists in this container, - * return that value. Otherwise, use the factory an given parameters to produce and return the value. + * return that value. Otherwise, use the factory and given parameters to produce and return the value. * @param {DependencyKey} key * @param {...any} parameters */ @@ -432,11 +441,16 @@ export class Container { // Create the dependencies for the factory const keys = factory.getDependencyKeys().filter(req => this.hasKey(req.key)) const dependencies = keys.map(req => { - return { - paramIndex: req.paramIndex, - key: req.key, - resolved: this.resolveAndCreate(req.key), - } + return withErrorContext(() => { + return { + paramIndex: req.paramIndex, + key: req.key, + resolved: this.resolveAndCreate(req.key), + } + }, { + producingToken: factory.getTokenName(), + constructorDependency: req, + }) }).sortBy('paramIndex') // Build the arguments for the factory, using dependencies in the @@ -460,7 +474,12 @@ export class Container { factory.getInjectedProperties().each(dependency => { logIfDebugging('extollo.di.injector', 'Resolving injected dependency:', dependency) if ( dependency.key && inst ) { - (inst as any)[dependency.property] = this.resolveAndCreate(dependency.key) + withErrorContext(() => { + (inst as any)[dependency.property] = this.resolveAndCreate(dependency.key) + }, { + producingToken: factory.getTokenName(), + propertyDependency: dependency, + }) } }) @@ -499,14 +518,22 @@ export class Container { this.checkForMakeCycles() try { - if (this.hasKey(target)) { - const realized = this.resolveAndCreate(target, ...parameters) - Container.makeStack.pop() - return realized - } else if (typeof target !== 'string' && isInstantiable(target)) { - const realized = this.produceFactory(new Factory(target), parameters) - Container.makeStack.pop() - return realized + const result = withErrorContext(() => { + if (this.hasKey(target)) { + const realized = this.resolveAndCreate(target, ...parameters) + Container.makeStack?.pop() + return realized + } else if (typeof target !== 'string' && isInstantiable(target)) { + const realized = this.produceFactory(new Factory(target), parameters) + Container.makeStack?.pop() + return realized + } + }, { + makeStack: Container.makeStack, + }) + + if ( result ) { + return result } } catch (e: unknown) { Container.makeStack.pop() diff --git a/src/di/error/InvalidDependencyKeyError.ts b/src/di/error/InvalidDependencyKeyError.ts index b2ac47a..2666500 100644 --- a/src/di/error/InvalidDependencyKeyError.ts +++ b/src/di/error/InvalidDependencyKeyError.ts @@ -1,11 +1,12 @@ import {DependencyKey} from '../types' +import {ErrorWithContext} from '../../util' /** * Error thrown when a dependency key that has not been registered is passed to a resolver. * @extends Error */ -export class InvalidDependencyKeyError extends Error { - constructor(key: DependencyKey) { - super(`No such dependency is registered with this container: ${key}`) +export class InvalidDependencyKeyError extends ErrorWithContext { + constructor(key: DependencyKey, context: {[key: string]: any} = {}) { + super(`No such dependency is registered with this container: ${key}`, context) } } diff --git a/src/di/factory/AbstractFactory.ts b/src/di/factory/AbstractFactory.ts index b4ffc9f..585d2bf 100644 --- a/src/di/factory/AbstractFactory.ts +++ b/src/di/factory/AbstractFactory.ts @@ -41,4 +41,16 @@ export abstract class AbstractFactory { * @return Collection */ abstract getInjectedProperties(): Collection + + /** + * Get a human-readable name of the token this factory produces. + * This is meant for debugging output only. + */ + public getTokenName(): string { + if ( typeof this.token === 'string' ) { + return this.token + } + + return this.token.name ?? '(unknown token)' + } }