-
Notifications
You must be signed in to change notification settings - Fork 144
/
extensions.js
109 lines (92 loc) · 3.38 KB
/
extensions.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
'use strict';
var EventEmitter = require('events').EventEmitter,
fs = require('fs'),
path = require('path'),
bundles = require('../bundles'),
ExtensionApi = require('../extension_api'),
log = require('../logger')('nodecg/lib/server/extensions');
var extensions = {};
var expressExtensions = [];
exports = new EventEmitter();
bundles.on('allLoaded', function(allBundles) {
log.trace('Starting extension mounting');
var unsatisfiedDeps = [];
function checkBundles(bundle) {
bundle.bundleDependencies.forEach(checkBundleDep);
log.warn('Extension for bundle %s could not be mounted, as it had unsatisfied dependencies:',
bundle.name, unsatisfiedDeps.join(', '));
bundles.remove(bundle.name);
}
function checkBundleDep(dep) {
if (extensions.hasOwnProperty(dep)) return;
unsatisfiedDeps.push(dep);
}
while(allBundles.length > 0) {
var startLen = allBundles.length;
for (var i = 0; i < startLen; i++) {
if (!allBundles[i].extension) {
allBundles.splice(i, 1);
break;
}
if (!allBundles[i].bundleDependencies) {
log.debug('Bundle %s has extension with no dependencies', allBundles[i].name);
_loadExtension(allBundles[i]);
allBundles.splice(i, 1);
break;
}
if (_bundleDepsSatisfied(allBundles[i])) {
log.debug('Bundle %s has extension with satisfied dependencies', allBundles[i].name);
_loadExtension(allBundles[i]);
allBundles.splice(i, 1);
break;
}
}
var endLen = allBundles.length;
if (startLen === endLen) {
allBundles.forEach(checkBundles);
log.warn('%d bundle(s) could not be loaded, as their dependencies were not satisfied', endLen);
break;
}
}
exports.emit('extensionsLoaded');
log.trace('Completed extension mounting');
});
exports.getExtensions = function() {
// TODO: return copy?
return extensions;
};
exports.getExpressExtensions = function() {
return expressExtensions;
};
function _loadExtension(bundle) {
var extPath = path.join(bundle.dir, bundle.extension.path);
if (fs.existsSync(extPath)) {
try {
var extension = require(extPath)(new ExtensionApi(bundle));
if (bundle.extension.express) {
expressExtensions.push([extension, bundle.name]);
log.info('Mounted %s extension as an express app', bundle.name);
} else {
log.info('Mounted %s extension as a generic extension', bundle.name);
}
extensions[bundle.name] = extension;
} catch (err) {
bundles.remove(bundle.name);
log.error('Failed to mount %s extension:', bundle.name, err.stack);
}
} else {
log.error('Specified entry point %s for %s does not exist. Skipped.', bundle.extension.path, bundle.name);
}
}
function _bundleDepsSatisfied(bundle) {
var deps = bundle.bundleDependencies;
for (var extName in extensions) {
if (!extensions.hasOwnProperty(extName)) continue;
var index = deps.indexOf(extName);
if (index > -1) {
deps.splice(index, 1);
}
}
return deps.length === 0;
}
module.exports = exports;