-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.mjs
81 lines (69 loc) · 2.17 KB
/
index.mjs
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
export const createActivator = (namespace = "unknown") => {
const INIT_SERVICE_FN = Symbol('init-service-fn');
const INIT_CALL_FN = Symbol('init-call-fn');
const accessorMap = new Map();
const factoryMap = new Map();
const instanceMap = new Map();
const singleshot = (run) => {
let isInitComplete = false;
let runValue = undefined;
return () => {
if (isInitComplete) {
return runValue;
}
isInitComplete = true;
return runValue = run();
}
};
const getInstance = (name) => {
if (instanceMap.has(name)) {
return instanceMap.get(name);
}
if (factoryMap.has(name)) {
const instance = factoryMap.get(name)();
instanceMap.set(name, instance);
return instance;
}
console.warn(`di-kit namespace=${namespace} name=${String(name)} not provided`);
return {};
}
const createService = (name, self) =>
singleshot(() => {
Object.setPrototypeOf(self, getInstance(name));
});
const createInitializer = (self) =>
singleshot(() => {
self.init && self.init();
});
class InstanceAccessor {
constructor(name) {
this.name = name;
this[INIT_SERVICE_FN] = createService(name, this);
this[INIT_CALL_FN] = createInitializer(this);
}
}
const provide = (name, ctor) => {
if (typeof ctor === "function") {
factoryMap.set(name, ctor);
return;
}
instanceMap.set(name, ctor);
};
const inject = (name) => accessorMap.has(name)
? accessorMap.get(name)
: accessorMap.set(name, new InstanceAccessor(name)).get(name);
const init = () => {
for (const accessor of accessorMap.values()) {
accessor[INIT_SERVICE_FN]();
}
for (const accessor of accessorMap.values()) {
accessor[INIT_CALL_FN]();
}
};
return {
provide,
inject,
init,
};
}
export const { provide, inject, init } = createActivator('root');