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 124 125 126 127 128 129 130 131 132 | 419x 419x 419x 419x 419x 419x 419x | import type { z } from 'zod/v4'
import type {
BaseInjectionTokenSchemaType,
ClassType,
ClassTypeWithArgument,
ClassTypeWithInstance,
ClassTypeWithInstanceAndArgument,
ClassTypeWithInstanceAndOptionalArgument,
ClassTypeWithOptionalArgument,
ClassTypeWithoutArguments,
InjectionTokenSchemaType,
OptionalInjectionTokenSchemaType,
} from '../token/injection-token.mjs'
import type { Registry } from '../token/registry.mjs'
import { InjectableScope, InjectableType } from '../enums/index.mjs'
import { InjectableTokenMeta } from '../symbols/index.mjs'
import { InjectionToken } from '../token/injection-token.mjs'
import { globalRegistry } from '../token/registry.mjs'
export interface InjectableOptions {
scope?: InjectableScope
token?: InjectionToken<any, any>
schema?: InjectionTokenSchemaType
registry?: Registry
priority?: number
}
// #1 Simple constructorless class
export function Injectable(): <T extends ClassTypeWithoutArguments>(
target: T,
context?: ClassDecoratorContext,
) => T
export function Injectable(options: {
scope?: InjectableScope
registry: Registry
priority?: number
}): <T extends ClassTypeWithoutArguments>(
target: T,
context?: ClassDecoratorContext,
) => T
export function Injectable(options: {
scope: InjectableScope
priority?: number
}): <T extends ClassTypeWithoutArguments>(
target: T,
context?: ClassDecoratorContext,
) => T
// #2 Class with schema
export function Injectable<Schema extends InjectionTokenSchemaType>(options: {
scope?: InjectableScope
schema: Schema
registry?: Registry
priority?: number
}): <T extends ClassTypeWithArgument<z.output<Schema>>>(
target: T,
context?: ClassDecoratorContext,
) => T
// #3 Class with typeless token and schema
export function Injectable<Type, Schema>(options: {
scope?: InjectableScope
token: InjectionToken<Type, Schema>
registry?: Registry
priority?: number
}): Schema extends BaseInjectionTokenSchemaType
? Type extends undefined
? <T extends ClassTypeWithArgument<z.output<Schema>>>(
target: T,
context?: ClassDecoratorContext,
) => T
: <T extends ClassTypeWithInstanceAndArgument<Type, z.output<Schema>>>(
target: T,
context?: ClassDecoratorContext,
) => T
: Schema extends OptionalInjectionTokenSchemaType
? Type extends undefined
? <T extends ClassTypeWithOptionalArgument<z.output<Schema>>>(
target: T,
context?: ClassDecoratorContext,
) => T
: <
T extends ClassTypeWithInstanceAndOptionalArgument<
Type,
z.output<Schema>
>,
>(
target: T,
context?: ClassDecoratorContext,
) => T
: Schema extends undefined
? <R extends ClassTypeWithInstance<Type>>(
target: R,
context?: ClassDecoratorContext,
) => R
: never
export function Injectable({
scope = InjectableScope.Singleton,
token,
schema,
registry = globalRegistry,
priority = 0,
}: InjectableOptions = {}) {
return <T extends ClassType>(
target: T,
context?: ClassDecoratorContext,
): T => {
Iif (
(context && context.kind !== 'class') ||
(target instanceof Function && !context)
) {
throw new Error('[DI] @Injectable decorator can only be used on classes.')
}
Iif (schema && token) {
throw new Error(
'[DI] @Injectable decorator cannot have both a token and a schema',
)
}
let injectableToken: InjectionToken<any, any> =
token ?? InjectionToken.create(target, schema as InjectionTokenSchemaType)
registry.set(injectableToken, scope, target, InjectableType.Class, priority)
// @ts-expect-error
target[InjectableTokenMeta] = injectableToken
return target
}
}
|