Improve error context for DI
This commit is contained in:
parent
9b47d2ac99
commit
3d836afa59
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@extollo/lib",
|
"name": "@extollo/lib",
|
||||||
"version": "0.13.9",
|
"version": "0.13.10",
|
||||||
"description": "The framework library that lifts up your code.",
|
"description": "The framework library that lifts up your code.",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
|
@ -8,7 +8,16 @@ import {
|
|||||||
TypedDependencyKey,
|
TypedDependencyKey,
|
||||||
} from './types'
|
} from './types'
|
||||||
import {AbstractFactory} from './factory/AbstractFactory'
|
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 {Factory} from './factory/Factory'
|
||||||
import {DuplicateFactoryKeyError} from './error/DuplicateFactoryKeyError'
|
import {DuplicateFactoryKeyError} from './error/DuplicateFactoryKeyError'
|
||||||
import {ClosureFactory} from './factory/ClosureFactory'
|
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,
|
* 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 {DependencyKey} key
|
||||||
* @param {...any} parameters
|
* @param {...any} parameters
|
||||||
*/
|
*/
|
||||||
@ -432,11 +441,16 @@ export class Container {
|
|||||||
// Create the dependencies for the factory
|
// Create the dependencies for the factory
|
||||||
const keys = factory.getDependencyKeys().filter(req => this.hasKey(req.key))
|
const keys = factory.getDependencyKeys().filter(req => this.hasKey(req.key))
|
||||||
const dependencies = keys.map<ResolvedDependency>(req => {
|
const dependencies = keys.map<ResolvedDependency>(req => {
|
||||||
|
return withErrorContext(() => {
|
||||||
return {
|
return {
|
||||||
paramIndex: req.paramIndex,
|
paramIndex: req.paramIndex,
|
||||||
key: req.key,
|
key: req.key,
|
||||||
resolved: this.resolveAndCreate(req.key),
|
resolved: this.resolveAndCreate(req.key),
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
producingToken: factory.getTokenName(),
|
||||||
|
constructorDependency: req,
|
||||||
|
})
|
||||||
}).sortBy('paramIndex')
|
}).sortBy('paramIndex')
|
||||||
|
|
||||||
// Build the arguments for the factory, using dependencies in the
|
// Build the arguments for the factory, using dependencies in the
|
||||||
@ -460,7 +474,12 @@ export class Container {
|
|||||||
factory.getInjectedProperties().each(dependency => {
|
factory.getInjectedProperties().each(dependency => {
|
||||||
logIfDebugging('extollo.di.injector', 'Resolving injected dependency:', dependency)
|
logIfDebugging('extollo.di.injector', 'Resolving injected dependency:', dependency)
|
||||||
if ( dependency.key && inst ) {
|
if ( dependency.key && inst ) {
|
||||||
|
withErrorContext(() => {
|
||||||
(inst as any)[dependency.property] = this.resolveAndCreate(dependency.key)
|
(inst as any)[dependency.property] = this.resolveAndCreate(dependency.key)
|
||||||
|
}, {
|
||||||
|
producingToken: factory.getTokenName(),
|
||||||
|
propertyDependency: dependency,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -499,15 +518,23 @@ export class Container {
|
|||||||
this.checkForMakeCycles()
|
this.checkForMakeCycles()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const result = withErrorContext(() => {
|
||||||
if (this.hasKey(target)) {
|
if (this.hasKey(target)) {
|
||||||
const realized = this.resolveAndCreate(target, ...parameters)
|
const realized = this.resolveAndCreate(target, ...parameters)
|
||||||
Container.makeStack.pop()
|
Container.makeStack?.pop()
|
||||||
return realized
|
return realized
|
||||||
} else if (typeof target !== 'string' && isInstantiable(target)) {
|
} else if (typeof target !== 'string' && isInstantiable(target)) {
|
||||||
const realized = this.produceFactory(new Factory(target), parameters)
|
const realized = this.produceFactory(new Factory(target), parameters)
|
||||||
Container.makeStack.pop()
|
Container.makeStack?.pop()
|
||||||
return realized
|
return realized
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
makeStack: Container.makeStack,
|
||||||
|
})
|
||||||
|
|
||||||
|
if ( result ) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
Container.makeStack.pop()
|
Container.makeStack.pop()
|
||||||
throw e
|
throw e
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import {DependencyKey} from '../types'
|
import {DependencyKey} from '../types'
|
||||||
|
import {ErrorWithContext} from '../../util'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error thrown when a dependency key that has not been registered is passed to a resolver.
|
* Error thrown when a dependency key that has not been registered is passed to a resolver.
|
||||||
* @extends Error
|
* @extends Error
|
||||||
*/
|
*/
|
||||||
export class InvalidDependencyKeyError extends Error {
|
export class InvalidDependencyKeyError extends ErrorWithContext {
|
||||||
constructor(key: DependencyKey) {
|
constructor(key: DependencyKey, context: {[key: string]: any} = {}) {
|
||||||
super(`No such dependency is registered with this container: ${key}`)
|
super(`No such dependency is registered with this container: ${key}`, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,4 +41,16 @@ export abstract class AbstractFactory<T> {
|
|||||||
* @return Collection<PropertyDependency>
|
* @return Collection<PropertyDependency>
|
||||||
*/
|
*/
|
||||||
abstract getInjectedProperties(): Collection<PropertyDependency>
|
abstract getInjectedProperties(): Collection<PropertyDependency>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user