-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
98 lines (61 loc) · 1.64 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
'use strict';
const utils = require('./lib/utils');
const PARAMS_SYMBOL = Symbol('MidgeInjectParams');
class DicInjector extends Map {
constructor() {
super();
this.set('$injector', this);
}
get(key, locals = {}) {
if(!locals.hasOwnProperty(key) && !this.has(key)) {
throw new Error(`Service '${key}' not found`);
}
return super.get(key);
}
invoke(fn, locals = {}) {
fn = utils.annotate(fn, PARAMS_SYMBOL);
try {
return fn(...fn[PARAMS_SYMBOL].map(key => this.get(key, locals)));
} catch(e) {
e.message += '\n--> ' + fn.toString() + '\n';
throw e;
}
}
}
module.exports = class Dic {
constructor() {
this._factories = new Map();
}
register(key, factory) {
if(key && !factory && key.name && key.factory) {
return this.register(key.name, key.factory);
}
this._factories.set(key, utils.annotate(factory, PARAMS_SYMBOL));
}
async boot() {
let edges = [];
for(let [key, factory] of this._factories) {
let params = ['__MIDGE_ROOT_NODE__', ...factory[PARAMS_SYMBOL]];
edges.push(...params.map(p => ([key, p])));
}
let bootOrder = utils.tsort(edges).reverse();
bootOrder.shift();
let injector = new DicInjector();
for(let key of bootOrder) {
if(injector.has(key)) {
continue;
}
if(!this._factories.has(key)) {
throw new Error(`Factory '${key}' not found`);
}
let factory = this._factories.get(key);
//console.log(`Creating service: ${key}`);
let service = await injector.invoke(factory);
if(service === undefined) {
throw new Error(`Factory '${key}' needs to return a service`);
}
injector.set(key, service);
}
return injector;
}
}