-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathloader.js
135 lines (127 loc) · 3.62 KB
/
loader.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
'use strict';
// Don't run in parallel
const fs = require('fs');
const debug = require('debug')('loader');
const chalk = require('chalk');
var toLoadModules = [];
var availableMeta = [];
function _done(){
// For counting phases
var phase = 0;
// No of retries
while (phase < 100){
availableMeta.push('PHASE_' + phase);
phase++;
var unchanged = 1;
while (unchanged < 2){
var canLoadModules = toLoadModules
.filter((a) => { return !a.loaded && _canLoadModule(a); });
// If none in can load modules we are locked
if (canLoadModules.length === 0){
// Merge availableMeta to create new metas
for (let i in availableMeta){
var i1 = availableMeta[i].indexOf('.');
if (i1 === -1){
i1 = availableMeta[i].indexOf('/');
}
if (i1 !== -1)
availableMeta[i] = availableMeta[i].substr(0, i1);
}
}
unchanged += 1;
for (let i in canLoadModules){
canLoadModules[i].loaded = true;
availableMeta = availableMeta.concat(canLoadModules[i][1].gives);
try {
canLoadModules[i][1].init();
} catch (err){
console.log(err);
continue;
};
debug(canLoadModules[i][0], 'loaded');
unchanged = 0;
}
}
}
if (!toLoadModules.every((a) => a.loaded)){
debug('Not all modules are loaded');
debug('Requires');
toLoadModules
.filter(a => !a.loaded)
.map(a => [a[0], a[1].requires.filter(a => !availableMeta.includes(a))])
.map(a => debug(a[0], ':', chalk.redBright(a[1])));
debug('Available');
debug(availableMeta
.filter(a => !a.startsWith('PHASE_'))
.concat(['PHASE_XX']),
);
console.log(chalk.red('Not all modules are loaded'));
}
}
// Check if all requires are available
function _canLoadModule(mod){
let check = mod[1].requires.every((req) => availableMeta.includes(req));
if (!check)
return false;
return mod[1].gives.every((a) => {
let doti = a.indexOf('.');
if (doti === -1)
return true;
return (toLoadModules
.filter(a => !a.loaded)
.map(a => a[1].gives)
.flat()
.filter(r => {
let doti2 = r.indexOf('.');
if ((doti2 !== -1) && (r.substr(0, doti2) === a.substr(0, doti)))
return r < a;
else
return false;
})
.length === 0
);
});
}
function loadPlugins(dir, files){
for (let i in files){
// Index.js must be loaded previously
var fname = files[i];
if (fname === 'index.js')
continue;
try {
var meta = require(dir + '/' + fname);
} catch (e) {
console.log(e);
continue;
}
// If folder open it
if (meta.submodules)
loadPlugins(dir + '/' + fname, meta.submodules);
// If not init function then no need to load it
if (!meta.init && typeof (meta.init) !== 'function')
continue;
if (!meta.gives)
meta.gives = [];
// Folder
loadPlugins(dir + '/' + fname, meta.submodules);
// File
// If not mount point is given mount at last
if (!meta.requires || meta.requires.length === 0)
meta.requires = ['PHASE_99'];
toLoadModules.push([dir + '/' + fname, meta]);
}
}
function loadPluginsFromDir(dir, done = () => {}){
fs.readdir(dir, (err, files) => {
if (err){
console.error(err);
} else {
debug('started');
loadPlugins(dir, files);
_done();
debug('completed');
done();
}
});
}
module.exports = loadPluginsFromDir;