-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
100 lines (90 loc) · 2.24 KB
/
index.js
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
/**
* The class for constructing a dependency container.
* @class Injector
* @property {Object} container - The container instance.
*/
class Injector {
constructor() {
this.container = Object.create(null);
}
/**
* Define a constant on the injector's container.
* @param {string} name
* @param {*} value
* @returns {Injector} The Injector instance.
*/
constant(name, value) {
constant(name, value, this.container);
return this;
}
/**
* Define a service on the injector's container.
* @param {Function} Class
* @param {string[]} dependencies
* @returns {Injector} The Injector instance.
*/
service(Class, dependencies) {
service(Class, dependencies, this.container);
return this;
}
}
module.exports = {
Injector,
constant,
service
};
/**
* Define a constant on a container.
* @param {string} name
* @param {*} value
* @param {Object} container
* @returns {Object} The container instance.
*/
function constant(name, value, container) {
if (arguments.length === 2) {
return constant.bind(null, name, value);
}
Object.defineProperty(container, name, { value });
return container;
}
/**
* Resolve an instance on a container.
* @private
* @param {string} name
* @param {Object} container
* @returns {Object} The resolved instance.
*/
function resolve(name, container) {
const instance = container[name];
if (instance === undefined) {
throw new Error(`Could not resolve '${name}'.`);
}
return instance;
}
/**
* Define a service on a container.
* @param {Function} Class
* @param {string[]} dependencies
* @param {Object} container
* @returns {Object} The container instance.
*/
function service(Class, dependencies, container) {
if (arguments.length === 2) {
return service.bind(null, Class, dependencies);
}
let instance;
Object.defineProperty(container, Class.name, {
get() {
if (instance === undefined) {
let resolving = dependencies.length;
const resolvedDeps = new Array(resolving);
while (resolving--) {
resolvedDeps[resolving] = resolve(dependencies[resolving], container);
}
instance = new Class(...resolvedDeps);
}
return instance;
}
});
return container;
}