Improve error context for DI
This commit is contained in:
parent
9b47d2ac99
commit
3d836afa59
@ -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",
|
||||
|
@ -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<ResolvedDependency>(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()
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -41,4 +41,16 @@ export abstract class AbstractFactory<T> {
|
||||
* @return 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