@@ -38,7 +38,11 @@ const fallbackKey = Symbol("fallback");
3838export const undefinedValueKey = Symbol ( "undefined" ) ;
3939export const ignoreValueKey = Symbol ( "ignore" ) ;
4040
41- type RequiredResolveOptions = { parent ?: unknown ; abstract ?: boolean } ;
41+ type RequiredResolveOptions = {
42+ parent ?: unknown ;
43+ abstract ?: boolean ;
44+ path ?: string [ ] ;
45+ } ;
4246type OptionalResolveOptions = RequiredResolveOptions & { optional : true } ;
4347type ResolveOptions = RequiredResolveOptions & { optional ?: boolean } ;
4448
@@ -116,15 +120,20 @@ export class IocContext {
116120 parent ?: unknown ;
117121 context ?: IocContext ;
118122 async ?: boolean ;
123+ path ?: string [ ] ;
119124 } = { } ,
120125 ) {
121126 const { parent } = options ;
122127 const context = options . context ?? this ;
123128 return param [ "isConfigurable" ] ( )
124- ? this . createConfigurableParam ( param , { parent, context } )
129+ ? this . createConfigurableParam ( param , {
130+ parent,
131+ context,
132+ path : options . path ,
133+ } )
125134 : context . dynamicResolve (
126135 param [ "getKey" ] ( ) ,
127- { parent, optional : param . options . optional } ,
136+ { parent, optional : param . options . optional , path : options . path } ,
128137 { async : options . async } ,
129138 ) ;
130139 }
@@ -133,6 +142,7 @@ export class IocContext {
133142 options : {
134143 context : IocContext ;
135144 parent ?: unknown ;
145+ path ?: string [ ] ;
136146 } ,
137147 ) {
138148 const registerKey = param [ "getKey" ] ( ) ;
@@ -152,8 +162,10 @@ export class IocContext {
152162 return ensureSync (
153163 ctx . resolve ( registerKey , {
154164 parent : options . parent ,
165+ path : options . path ,
155166 optional : param . options . optional as true ,
156167 } ) ,
168+ options . path ,
157169 ) ;
158170 } ;
159171 }
@@ -256,6 +268,7 @@ export class IocContext {
256268 options : {
257269 parent ?: any ;
258270 async ?: boolean ;
271+ path ?: string [ ] ;
259272 } ,
260273 ) {
261274 const { parent } = options ;
@@ -271,7 +284,7 @@ export class IocContext {
271284 const ctx = this . fork ( ) . register ( input as any , { value : ignoreValueKey } ) ;
272285 return ctx . dynamicResolve (
273286 data . useClass ,
274- { parent } ,
287+ { parent, path : options . path } ,
275288 { async : options . async } ,
276289 ) ;
277290 }
@@ -298,7 +311,7 @@ export class IocContext {
298311 ) :
299312 | {
300313 params : IocParamsConfig ;
301- paramOptions : { context : IocContext ; parent : unknown } ;
314+ paramOptions : { context : IocContext ; parent : unknown ; path ?: string [ ] } ;
302315 create : ( params : Record < string , any > ) => any ;
303316 }
304317 | undefined {
@@ -312,7 +325,7 @@ export class IocContext {
312325 iocObject = input ;
313326 create = ( params : any ) => input . bind ( params ) ;
314327 } else if ( ! options . optional ) {
315- throw createKeyError ( input as IocRegistryKey ) ;
328+ throw createKeyError ( input as IocRegistryKey , options . path ) ;
316329 } else {
317330 return ;
318331 }
@@ -323,7 +336,7 @@ export class IocContext {
323336 : this ;
324337 if ( ! onResolveIocObject || onResolveIocObject ( input ) ) {
325338 return {
326- paramOptions : { context, parent : input } ,
339+ paramOptions : { context, parent : input , path : options . path } ,
327340 params : iocObject . $ioc . params ,
328341 create,
329342 } ;
@@ -346,16 +359,22 @@ export class IocContext {
346359 options : {
347360 parent ?: unknown ;
348361 context ?: IocContext ;
362+ path ?: string [ ] ;
349363 } = { } ,
350364 ) : IocParams < T > {
351365 const config = normalizeIocParams ( input , false ) ;
366+ const prevPath = options . path ?? [ ] ;
352367 const params : Record < string , any > = { } ;
353368 for ( const name in config ) {
354369 const value = config [ name ] ;
370+ const path = [ ...prevPath , name ] ;
355371 if ( isPlainObject ( value ) ) {
356- params [ name ] = this . resolveParams ( value , options ) ;
372+ params [ name ] = this . resolveParams ( value , { ... options , path } ) ;
357373 } else {
358- params [ name ] = ensureSync ( this . createParam ( value , options ) ) ;
374+ params [ name ] = ensureSync (
375+ this . createParam ( value , { ...options , path } ) ,
376+ path ,
377+ ) ;
359378 }
360379 }
361380 return params as any ;
@@ -366,17 +385,24 @@ export class IocContext {
366385 options : {
367386 parent ?: unknown ;
368387 context ?: IocContext ;
388+ path ?: string [ ] ;
369389 } = { } ,
370390 ) : Promise < IocParams < T > > {
371391 const config = normalizeIocParams ( input , false ) ;
392+ const prevPath = options . path ?? [ ] ;
372393 const params : Record < string , any > = { } ;
373394 for ( const name in config ) {
374395 const value = config [ name ] ;
396+ const path = [ ...prevPath , name ] ;
375397 if ( isPlainObject ( value ) ) {
376- params [ name ] = await this . resolveAsyncParams ( value , options ) ;
398+ params [ name ] = await this . resolveAsyncParams ( value , {
399+ ...options ,
400+ path,
401+ } ) ;
377402 } else {
378403 params [ name ] = await this . createParam ( value , {
379404 ...options ,
405+ path,
380406 async : true ,
381407 } ) ;
382408 }
@@ -411,17 +437,26 @@ export class IocContext {
411437 input : Constructor | ( ( ...args : any [ ] ) => any ) | IocRegistryKey ,
412438 options : ResolveOptions = { } ,
413439 ) {
440+ const path = options . path ?? [
441+ typeof input === "function" ? input . name : `${ input } ` ,
442+ ] ;
414443 const data = this . find ( input as any ) ;
415444
416445 if ( data && this . shouldBeResolved ( input , data ) ) {
417446 const value = ensureSync (
418- this . resolveWithRegistryData ( input , data , { parent : options . parent } ) ,
447+ this . resolveWithRegistryData ( input , data , {
448+ parent : options . parent ,
449+ path,
450+ } ) ,
419451 ) ;
420452 const result = this . tryParseResolvedValue ( input , data , value ) ;
421453 if ( result ) return result . value ;
422454 }
423455
424- const object = this . tryParseIocObject ( input , options ) ;
456+ const object = this . tryParseIocObject ( input , {
457+ ...options ,
458+ path,
459+ } ) ;
425460
426461 if ( object ) {
427462 const params = this . resolveParams ( object . params , object . paramOptions ) ;
@@ -456,18 +491,26 @@ export class IocContext {
456491 input : Constructor | ( ( ...args : any [ ] ) => any ) | IocRegistryKey ,
457492 options : ResolveOptions = { } ,
458493 ) {
494+ const path = [
495+ ...( options . path ?? [ ] ) ,
496+ typeof input === "function" ? input . name : `${ input } ` ,
497+ ] ;
459498 const data = this . find ( input as any ) ;
460499
461500 if ( data && this . shouldBeResolved ( input , data ) ) {
462501 const value = await this . resolveWithRegistryData ( input , data , {
463502 parent : options . parent ,
503+ path,
464504 async : true ,
465505 } ) ;
466506 const result = this . tryParseResolvedValue ( input , data , value ) ;
467507 if ( result ) return result . value ;
468508 }
469509
470- const object = this . tryParseIocObject ( input , options ) ;
510+ const object = this . tryParseIocObject ( input , {
511+ ...options ,
512+ path,
513+ } ) ;
471514
472515 if ( object ) {
473516 const params = await this . resolveAsyncParams (
0 commit comments