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 133 134 135 136 137 138 139 140 141 142 | 308x 308x 308x 1877x 1847x 30x 21x 9x 3050x 3050x 32x 29x 3x 3018x 8x 8x 2x 1x 1x 6x 793x 793x 793x 793x 793x 793x 734x 3x 3x 2x 2x 2x 2x 1x 2x 1x 1x 1x 1x 38x 38x 35x 36x 35x 35x 35x 35x 3x 1x 2x 19x | import type { ClassType, InjectionToken } from './injection-token.mjs'
import { InjectableScope, InjectableType } from '../enums/index.mjs'
export type FactoryRecord<Instance = any, Schema = any> = {
scope: InjectableScope
originalToken: InjectionToken<Instance, Schema>
target: ClassType
type: InjectableType
priority: number
}
export class Registry {
private readonly factories = new Map<string, FactoryRecord[]>()
private readonly highestPriority = new Map<string, FactoryRecord>()
constructor(private readonly parent?: Registry) {}
has(token: InjectionToken<any, any>): boolean {
if (this.factories.has(token.id)) {
return true
}
if (this.parent) {
return this.parent.has(token)
}
return false
}
get<Instance, Schema>(
token: InjectionToken<Instance, Schema>,
): FactoryRecord<Instance, Schema> {
const factory = this.highestPriority.get(token.id)
if (!factory) {
if (this.parent) {
return this.parent.get(token)
}
throw new Error(`[Registry] No factory found for ${token.toString()}`)
}
return factory
}
getAll<Instance, Schema>(
token: InjectionToken<Instance, Schema>,
): FactoryRecord<Instance, Schema>[] {
const records = this.factories.get(token.id)
if (!records || records.length === 0) {
if (this.parent) {
return this.parent.getAll(token)
}
return []
}
// Return sorted by priority (highest first)
return [...records].sort((a, b) => b.priority - a.priority)
}
set<Instance, Schema>(
token: InjectionToken<Instance, Schema>,
scope: InjectableScope,
target: ClassType,
type: InjectableType,
priority: number = 0,
) {
const record: FactoryRecord<Instance, Schema> = {
scope,
originalToken: token,
target,
type,
priority,
}
// Add to factories array
const existing = this.factories.get(token.id) || []
existing.push(record)
this.factories.set(token.id, existing)
// Update highest priority cache if needed
const currentHighest = this.highestPriority.get(token.id)
if (!currentHighest || priority > currentHighest.priority) {
this.highestPriority.set(token.id, record)
}
}
delete(token: InjectionToken<any, any>) {
const records = this.factories.get(token.id)
if (records) {
const deletedHighest = this.highestPriority.get(token.id)
this.factories.delete(token.id)
this.highestPriority.delete(token.id)
// If we deleted the highest priority record, recalculate from remaining records
if (deletedHighest && records.length > 1) {
const remaining = records.filter(
(r) =>
r.originalToken.id !== deletedHighest.originalToken.id ||
r.priority !== deletedHighest.priority,
)
Eif (remaining.length > 0) {
const newHighest = remaining.reduce((max, current) =>
current.priority > max.priority ? current : max,
)
this.highestPriority.set(token.id, newHighest)
this.factories.set(token.id, remaining)
}
}
}
}
/**
* Updates the scope of an already registered factory.
* This is useful when you need to dynamically change a service's scope
* (e.g., when a singleton controller has request-scoped dependencies).
*
* @param token The injection token to update
* @param scope The new scope to set
* @returns true if the scope was updated, false if the token was not found
*/
updateScope(
token: InjectionToken<any, any>,
scope: InjectableScope,
): boolean {
const records = this.factories.get(token.id)
if (records && records.length > 0) {
// Update all records
records.forEach((record) => {
record.scope = scope
})
// Update highest priority cache if it exists
const highest = this.highestPriority.get(token.id)
Eif (highest) {
highest.scope = scope
}
return true
}
if (this.parent) {
return this.parent.updateScope(token, scope)
}
return false
}
}
export const globalRegistry = /* #__PURE__ */ new Registry()
|