-
-
Notifications
You must be signed in to change notification settings - Fork 47
/
mod.ts
114 lines (90 loc) · 2.86 KB
/
mod.ts
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
const INJECTIONS = new WeakMap();
export interface InjectableObject {
inject: any[];
}
export function applyInjection(object: InjectableObject, v: any, context?: any) {
const injections: any[] = INJECTIONS.get(v) || [];
if (object?.inject) {
for (const injectionKey of object.inject) {
injections.push({ injectionKey, context });
}
}
INJECTIONS.set(v as any, injections);
}
function createInjections() {
function Injectable(object?: InjectableObject) {
return function applyInjection(v: any, context?: any) {
const injections: any[] = INJECTIONS.get(v) || [];
if (object?.inject) {
for (const injectionKey of object.inject) {
injections.push({ injectionKey, context });
}
}
INJECTIONS.set(v as any, injections);
};
}
function Inject(injectionKey: any) {
return function applyInjection(v: any, context: any) {
const injections: any[] = INJECTIONS.get(v) || [];
injections.push({ injectionKey, context });
};
}
return { Injectable, Inject };
}
export class Container {
private _parentContainer: Container | null = null;
registry = new Map();
register<T>(injectionKey: any, value: any) {
this.registry.set(injectionKey, value);
}
lookup<T>(injectionKey: any): T {
return this.registry.get(injectionKey) || this._parentContainer?.lookup(injectionKey);
}
create<T>(_class: any) {
const Class = this.lookup(_class) || _class;
const injections: any[] = INJECTIONS.get(Class) || [];
const constructorInjections = injections.filter(({ context }) => context.kind === "class");
const instance = new Class(...constructorInjections.map(({ injectionKey }) => this.lookup(injectionKey)));
for (const { injectionKey, context } of INJECTIONS.get(Class) || []) {
if (context !== undefined) {
instance[context] = this.lookup(injectionKey);
}
}
return instance;
}
public set parentContainer(container: Container) {
this._parentContainer = container;
}
createChildContainer(): Container {
const container = new Container();
container.parentContainer = this;
return container;
}
}
export const { Injectable, Inject } = createInjections();
export const SLContainer = new Container();
// // class Store {}
//
// @Injectable
// class C {
// @Inject('store') store: any;
// }
//
// let container = new Container();
// let store = new Store();
//
// container.register('store', store);
//
// let c = container.create(C);
//
// console.log(c.store === store); // true
export function getOrSetInjectId(context: { metadata?: Record<string | number | symbol, unknown> }): string {
context.metadata = context.metadata || {};
if (context.metadata._injectId) {
return context.metadata._injectId as string;
} else {
const id = crypto.randomUUID();
context.metadata["_injectId"] = id;
return id;
}
}