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 115 116 117 118 119 120 121 122 123 | 286x 1532x 704x 828x 2456x 37x 2419x 1303x 998x 998x 672x 998x 998x 12x 986x 9x 5x 4x 994x 960x 34x 998x 5x 5x 29x | import type {
AnyInjectableType,
InjectionTokenType,
} from '../../token/injection-token.mjs'
import { DIError } from '../../errors/index.mjs'
import {
BoundInjectionToken,
FactoryInjectionToken,
InjectionToken,
} from '../../token/injection-token.mjs'
import { getInjectableToken } from '../../utils/index.mjs'
/**
* Handles token validation and resolution.
*
* Focuses on token validation, normalization, and argument validation.
* Name generation is handled by NameResolver.
*/
export class TokenResolver {
constructor(private readonly logger: Console | null = null) {}
// ============================================================================
// TOKEN NORMALIZATION
// ============================================================================
/**
* Normalizes a token to an InjectionToken.
* Handles class constructors by getting their injectable token.
*
* @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken
* @returns The normalized InjectionTokenType
*/
normalizeToken(token: AnyInjectableType): InjectionTokenType {
if (typeof token === 'function') {
return getInjectableToken(token)
}
return token as InjectionTokenType
}
/**
* Gets the underlying "real" token from wrapped tokens.
* For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.
* For other tokens, returns the token itself.
*
* @param token The token to unwrap
* @returns The underlying InjectionToken
*/
getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T> {
if (
token instanceof BoundInjectionToken ||
token instanceof FactoryInjectionToken
) {
return token.token as InjectionToken<T>
}
return token as InjectionToken<T>
}
/**
* Convenience method that normalizes a token and then gets the real token.
* Useful for checking registry entries where you need the actual registered token.
*
* @param token Any injectable type
* @returns The underlying InjectionToken
*/
getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T> {
return this.getRealToken(this.normalizeToken(token))
}
// ============================================================================
// TOKEN VALIDATION
// ============================================================================
/**
* Validates and resolves token arguments, handling factory token resolution and validation.
*
* @param token The token to validate
* @param args Optional arguments
* @returns [error, { actualToken, validatedArgs }]
*/
validateAndResolveTokenArgs(
token: AnyInjectableType,
args?: any,
): [
DIError | undefined,
{ actualToken: InjectionTokenType; validatedArgs?: any },
] {
let actualToken = token as InjectionToken<any, any>
if (typeof token === 'function') {
actualToken = getInjectableToken(token)
}
let realArgs = args
if (actualToken instanceof BoundInjectionToken) {
realArgs = actualToken.value
} else if (actualToken instanceof FactoryInjectionToken) {
if (actualToken.resolved) {
realArgs = actualToken.value
} else {
return [DIError.factoryTokenNotResolved(token.name), { actualToken }]
}
}
if (!actualToken.schema) {
return [undefined, { actualToken, validatedArgs: realArgs }]
}
const validatedArgs = actualToken.schema?.safeParse(realArgs)
if (validatedArgs && !validatedArgs.success) {
this.logger?.error(
`[TokenResolver]#validateAndResolveTokenArgs(): Error validating args for ${actualToken.name.toString()}`,
validatedArgs.error,
)
return [
DIError.tokenValidationError(
`Validation failed for ${actualToken.name.toString()}`,
actualToken.schema,
realArgs,
),
{ actualToken },
]
}
return [undefined, { actualToken, validatedArgs: validatedArgs?.data }]
}
}
|