-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
121 lines (98 loc) · 3.71 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
var debug = require('debug')('plug'),
path = require('path'),
fs = require('fs'),
events = require('events'),
util = require('util');
var Plugger = exports.Plugger = function() {
this.activePlugins = {};
this.args = Array.prototype.slice.call(arguments, 0);
}; // PluginLoader
util.inherits(Plugger, events.EventEmitter);
Plugger.prototype.activate = function(pluginName, plugin, modulePath, data) {
// update the active plugins
this.activePlugins[pluginName] = {
data: data,
module: plugin,
path: modulePath
};
// emit the connect event
debug('!! CONNECT: plugin "' + pluginName + '" load fired callback, completed');
this.emit('connect', pluginName, data || {}, modulePath);
};
Plugger.prototype.drop = function(pluginName) {
var activePlugin = this.activePlugins[pluginName],
loader = this;
// if the plugin is already loaded, then drop it
debug('check if drop required for plugin: ' + pluginName);
if (activePlugin) {
var dropActions = [];
debug('!! DROP: active plugin found for "' + pluginName + '", attempting drop');
if (activePlugin.module.drop) {
dropActions = activePlugin.module.drop.apply(null, this.args) || [];
if (! Array.isArray(dropActions)) {
dropActions = [dropActions];
}
}
// emit the drop event
this.emit('drop', pluginName, activePlugin, dropActions);
// iterate through the drop actions and fire events for each action
dropActions.forEach(function(actionData) {
if (actionData.action) {
loader.emit(actionData.action, actionData);
}
});
// delete the active plugin
delete this.activePlugins[pluginName];
}
};
Plugger.prototype.find = function(pluginPath) {
var loader = this;
debug('looking for app plugins in: ' + pluginPath);
fs.readdir(pluginPath, function(err, files) {
(files || []).forEach(function(file) {
loader.load(path.join(pluginPath, file));
});
});
};
Plugger.prototype.load = function(modulePath) {
// grab the base name of the plugin
var pluginName = path.basename(modulePath, '.js'),
plugin, connectArgs = this.args,
loader = this;
// drop the existing plugin if it exists
loader.drop(pluginName, plugin);
debug('loading plugin "' + pluginName + '" from: ' + modulePath);
require.cache[modulePath] = undefined;
try {
// load the plugin
plugin = require(modulePath);
}
catch (e) {
loader.emit('error', e);
}
if (plugin && plugin.connect) {
var haveCallback = plugin.connect.length > this.args.length,
connectResult;
// if the function has a callback parameter, then append the callback arg
if (haveCallback) {
// add the callback to the connect args
connectArgs = this.args.concat(function(pluginData) {
loader.activate(pluginName, plugin, modulePath, pluginData || connectResult);
});
}
// call the connect method
connectResult = plugin.connect.apply(null, connectArgs);
// if we didn't have a callback, then emit the connect event
if (! haveCallback) {
loader.activate(pluginName, plugin, modulePath, connectResult);
}
}
};
exports.create = function() {
// create the new plugger
var instance = new Plugger();
// apply the constructor to pass through the arguments
Plugger.apply(instance, Array.prototype.slice.call(arguments, 0));
// return the new instance
return instance;
};