Skip to content

Commit b7488e6

Browse files
committed
Allow storing any value (not just objects) in the registry
1 parent 44af3b4 commit b7488e6

File tree

4 files changed

+86
-86
lines changed

4 files changed

+86
-86
lines changed

packages/v1/src/di/context.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ConstructorUnknown, ConstructorOf } from './constructor-of.type.js'
2-
import { ObjectRegistry } from './object-registry.js'
2+
import { ValueRegistry } from './value-registry.js'
33

44
class Logger {
55
constructor(protected readonly id: number) { }
@@ -20,13 +20,13 @@ export class Context {
2020
protected readonly injections = new Map<ConstructorUnknown, Injections>()
2121
protected readonly replacements = new Map<ConstructorUnknown, ConstructorUnknown>()
2222

23-
constructor(protected readonly registry = new ObjectRegistry()) { }
23+
constructor(protected readonly registry = new ValueRegistry()) { }
2424

2525
registerConstructor(Entity: ConstructorUnknown): this {
2626
this.logger.log(`Registering "${Entity.name}" …`)
2727

28-
if (!this.registry.hasObjectCreator(Entity)) {
29-
this.registry.addObjectCreator(Entity, async (...dependencies) => new Entity(...dependencies as never))
28+
if (!this.registry.hasCreator(Entity)) {
29+
this.registry.addCreator(Entity, async (...dependencies) => new Entity(...dependencies as never))
3030
}
3131

3232
return this
@@ -128,15 +128,15 @@ export class Context {
128128
Instance = Replacement as ConstructorOf<Instance, Dependencies>
129129
}
130130

131-
if (!this.registry.hasObject(Instance)) {
131+
if (!this.registry.has(Instance)) {
132132
const dependencies = await this.resolveDependencies(Instance)
133133

134134
this.logger.log(`Preparing instance of "${Instance.name}" …`)
135135

136-
await this.registry.prepareObject(Instance, dependencies)
136+
await this.registry.prepare(Instance, dependencies)
137137
}
138138

139-
const instance = this.registry.getObject<Instance>(Instance)
139+
const instance = this.registry.get<Instance>(Instance)
140140

141141
return instance
142142
}

packages/v1/src/di/main.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { ConstructorOf } from './constructor-of.type.js'
22
import { Context } from './context.js'
33
import { createDecorators } from './create-decorators.js'
4-
import { ObjectRegistry } from './object-registry.js'
4+
import { ValueRegistry } from './value-registry.js'
55

6-
const objectRegistry = new ObjectRegistry()
7-
const context = new Context(objectRegistry)
6+
const registry = new ValueRegistry()
7+
const context = new Context(registry)
88

99
export const {
1010
Instance,

packages/v1/src/di/object-registry.ts

Lines changed: 0 additions & 76 deletions
This file was deleted.

packages/v1/src/di/value-registry.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { MaybePromise } from './maybe-promise.type.js'
2+
3+
// We reasonably limit token types because we want to stringify them without heavy heuristics
4+
type Token = string | number | symbol | { readonly name: string }
5+
6+
function read(token: Token): string {
7+
return token instanceof Object ? token.name : token.toString()
8+
}
9+
10+
interface Creator<O, Dependencies extends readonly unknown[]> {
11+
(...deps: Dependencies): MaybePromise<O>
12+
}
13+
14+
export class ValueRegistry {
15+
protected readonly creators = new Map<Token, Creator<unknown, never>>()
16+
protected readonly values = new Map<Token, unknown>()
17+
18+
hasCreator(token: Token): boolean {
19+
return this.creators.has(token)
20+
}
21+
22+
addCreator<Value, Dependencies extends readonly unknown[]>(
23+
token: Token,
24+
creator: Creator<Value, Dependencies>,
25+
): void {
26+
if (this.hasCreator(token)) {
27+
throw new Error(`Cannot add creator: creator for "${read(token)}" already added`)
28+
}
29+
30+
this.creators.set(token, creator)
31+
}
32+
33+
replaceCreator(
34+
token: Token,
35+
creator: Creator<unknown, never>,
36+
): void {
37+
if (!this.hasCreator(token)) {
38+
throw new Error(`Cannot replace creator: creator for "${read(token)}" was not added`)
39+
}
40+
41+
this.creators.set(token, creator)
42+
}
43+
44+
has(token: Token): boolean {
45+
return this.values.has(token)
46+
}
47+
48+
async prepare<Dependencies extends readonly unknown[]>(
49+
token: Token,
50+
dependencies: Dependencies,
51+
): Promise<void> {
52+
if (this.has(token)) {
53+
throw new Error(`Cannot prepare value: "${read(token)}" is already prepared`)
54+
}
55+
56+
const create = this.creators.get(token)
57+
58+
if (!create) {
59+
throw new Error(`Cannot prepare value: creator for "${read(token)}" was not added`)
60+
}
61+
62+
const value = await create(...dependencies as never)
63+
64+
this.values.set(token, value)
65+
}
66+
67+
get<Value>(token: Token): Value {
68+
if (!this.has(token)) {
69+
throw new Error(`Cannot get value: "${read(token)}" was not prepared`)
70+
}
71+
72+
const value = this.values.get(token)!
73+
74+
return value as Value
75+
}
76+
}

0 commit comments

Comments
 (0)