1 | ### Plugin Library for node.js
|
2 |
|
3 | ### Motivation
|
4 |
|
5 | - Modularity - encourages code-reuse, abstraction, and encapsulation
|
6 | - Easily drop plugins in and out without breaking your program
|
7 | - Maintainability
|
8 | - Flexibility over dependencies
|
9 | - Asyncronously load remote plugins via [dnode](/substack/dnode) (*soon* - [now.js](/flotype/now), [beanpoll](beanpole)).
|
10 | - *soon* double as online async module loader (similar to [head](https://github.com/headjs/headjs)).
|
11 |
|
12 | ## Basic Usage
|
13 |
|
14 | A simple use case with express:
|
15 |
|
16 | ```javascript
|
17 |
|
18 | var plugin = require('plugin').loader(),
|
19 | server = require('express').createServer();
|
20 |
|
21 | plugin.options(server, true).
|
22 | require("path/to/plugins/dir");
|
23 |
|
24 | server.listen(8080);
|
25 |
|
26 | ```
|
27 |
|
28 | In your `hello world` plugin:
|
29 |
|
30 | ```javascript
|
31 |
|
32 | exports.plugin = function(server) {
|
33 |
|
34 | server.get('/', function(req, res) {
|
35 |
|
36 | res.send("Hello World!");
|
37 | });
|
38 | }
|
39 |
|
40 | ```
|
41 |
|
42 | ## Plugins
|
43 |
|
44 | - [plugin.dnode](/crcn/plugin.dnode) - dnode plugin
|
45 |
|
46 |
|
47 | ## Plugin API
|
48 |
|
49 | ### plugin.require(path)
|
50 |
|
51 | includes target dependencies
|
52 |
|
53 | ```javascript
|
54 | plugins.require('path/to/plugin.js'). // require one plugin
|
55 | require('path/to/plugins/dir'). // require all plugins in directory
|
56 | require('path/to/plugins/**/*.plugin.js'). // find plugins, and load them
|
57 | require('plugin1.js','plugin2.js','plugin3.js'). //multiple plugin args
|
58 | require('./config.json').load(); //load plugins in configuration file { plugins: ['my/plugin.js','...'] }
|
59 | ```
|
60 |
|
61 | ### plugin.paths(path)
|
62 |
|
63 | adds a path to scan when requiring plugins. Similar to the old `require.paths.unshift`
|
64 |
|
65 | ```javascript
|
66 | plugin.paths('/path/to/plugins').require('my-plugin');
|
67 |
|
68 | console.log(plugin.paths());// ['/path/to/plugins','/path/to/node_modules','...'];
|
69 | ```
|
70 |
|
71 | ### plugin.params(params)
|
72 |
|
73 | params specific to plugin - like constructor parameters
|
74 |
|
75 | bootstrap.js:
|
76 |
|
77 | ```javascript
|
78 | plugin.params({
|
79 | 'server': {
|
80 | 'port': 8080
|
81 | }
|
82 | }).
|
83 |
|
84 | //or
|
85 | params('server', { port: 8080 }).
|
86 | require('server');
|
87 | ```
|
88 |
|
89 | api.server/index.js:
|
90 |
|
91 | ```javascript
|
92 | exports.plugin = function(ops, params) {
|
93 | console.log(params.port); //8080
|
94 | }
|
95 | ```
|
96 |
|
97 |
|
98 | ### plugin.options(ops)
|
99 |
|
100 | Adds / returns options which are passed in the first parameter for each plugin.
|
101 |
|
102 | bootstrap.js:
|
103 |
|
104 | ```javascript
|
105 | plugin.options({ message: 'hello world!' }).require('hello.plugin.js');
|
106 | ```
|
107 |
|
108 | hello.plugin.js:
|
109 |
|
110 | ```javascript
|
111 | exports.plugin = function(ops) {
|
112 | console.log(ops.message); //hello world!
|
113 | }
|
114 | ```
|
115 |
|
116 | ### plugin.onLoad(pluginSearch, ret, callback)
|
117 |
|
118 | Listens for when a plugin is ready - useful especially if a dnode server resets
|
119 |
|
120 | ```javascript
|
121 |
|
122 | plugin.onLoad('my.plugin', function() {
|
123 |
|
124 | console.log("ready!");
|
125 | }).require('my.plugin');
|
126 | ```
|
127 |
|
128 | ### plugin.local plugin.remote
|
129 |
|
130 | remote/local collections. Same api as plugin (emit, plugin, plugins)
|
131 |
|
132 | ### plugin.emit(type, data)
|
133 |
|
134 | emits a method against all loaded plugins. If the method doesn't exist, it'll be ignored.
|
135 |
|
136 | bootstrap.js:
|
137 |
|
138 | ```javascript
|
139 | plugin.loader().require('api.server').load().emit('doStuff');
|
140 | ```
|
141 |
|
142 | api.server/index.js:
|
143 |
|
144 | ```javascript
|
145 | exports.plugin = function() {
|
146 |
|
147 | return {
|
148 | doStuff: function() {
|
149 | console.log("PREPARE");
|
150 | },
|
151 | init: function() {
|
152 | console.log("INIT");
|
153 | }
|
154 | };
|
155 | }
|
156 | ```
|
157 |
|
158 | ### plugin.load()
|
159 |
|
160 | Loads the plugins, and initializes them.
|
161 |
|
162 | ### plugin.next(callback)
|
163 |
|
164 | Queue function called after loading in all modules
|
165 |
|
166 | ### plugin.exports
|
167 |
|
168 | All the invokable methods against modules
|
169 |
|
170 |
|
171 |
|
172 |
|
173 | ### plugin.plugins(search)
|
174 |
|
175 | Returns *multiple* plugins based on the search criteria.
|
176 |
|
177 | ```
|
178 |
|
179 | var loader = plugin.loader();
|
180 |
|
181 | loader.require('oauth.part.twitter','oauth.part.facebook','oauth.core').
|
182 | load(function() {
|
183 | loader.plugins(/^oauth.part.\w+$/).forEach(function(service) {
|
184 |
|
185 | //do stuff with the oauth plugins
|
186 |
|
187 | });
|
188 | });
|
189 | ```
|
190 |
|
191 |
|
192 | ### plugin.plugin(search)
|
193 |
|
194 | Returns a *single* based on the search criteria given.
|
195 |
|
196 |
|
197 | ### plugin.loaders
|
198 |
|
199 | Loads plugins passed into `plugin.require()`.
|
200 |
|
201 | ```javascript
|
202 | //dnode plugin
|
203 | plugin.loaders.push({
|
204 | test: function(path) {
|
205 | return !!path.match(/dnode+\w+:\/\//); //dnode+https://my-dnode-server.com
|
206 | },
|
207 | load: function(path, callback) {
|
208 | //load dnode module here
|
209 | }
|
210 | });
|
211 | ```
|
212 |
|
213 | ### plugin.factory(fn)
|
214 |
|
215 | Plugin factory function
|
216 |
|
217 | plugin.factory(function(module, options, params) {
|
218 | return module(options, params); //instead of exports.plugin = function(){}, it would be module.exports = function(options, params)
|
219 | });
|
220 |
|
221 | ### plugin.newPlugin
|
222 |
|
223 | Plugin factory for plugin. Setting this method will change the way modules are loaded in.
|
224 |
|
225 | ```javascript
|
226 |
|
227 |
|
228 | plugin.newPlugin = function(module, options, params) {
|
229 | return module(options, params); //instead of exports.plugin = function(){}, it would be module.exports = function(options, params)
|
230 | };
|
231 |
|
232 | ```
|
233 |
|
234 |
|
235 | ## Plugins API
|
236 |
|
237 |
|
238 | ### exports.require
|
239 |
|
240 | Dependencies for the given plugin. This is checked once `plugin.call`, or `plugin.load` is invoked. An exception is thrown if there are any missing dependencies.
|
241 |
|
242 | ```javascript
|
243 |
|
244 | exports.require = ['api.services.photos.*','another-plugin']; //requires any photo services. E.g: api.services.photos.facebook, api.services.photos.flickr
|
245 |
|
246 | exports.require = [/api\.\w+/]; //regexp test
|
247 |
|
248 | exports.require = function(name) { //function test
|
249 | return name.indexOf('api.services.photos') > -1
|
250 | };
|
251 |
|
252 |
|
253 | ```
|
254 |
|
255 | You can also load in any given plugin via `exports.require`:
|
256 |
|
257 | ```javascript
|
258 |
|
259 | exports.require = 'my-plugin';
|
260 |
|
261 |
|
262 | exports.plugin = function() {
|
263 |
|
264 | var plugin = this;
|
265 |
|
266 | return {
|
267 | init: function() {
|
268 |
|
269 | plugin.plugin('my-plugin').doStuff();//return a single instance
|
270 | plugin.plugins('my-plugin').forEach(funtion(plugin) {//return multiple instances
|
271 | plugin.doStuff();
|
272 | });
|
273 | }
|
274 | }
|
275 | }
|
276 | ```
|
277 |
|
278 | ### exports.name
|
279 |
|
280 | Optional name for the plugin. The default value is name provided when requiring the plugin.
|
281 |
|
282 |
|
283 | ### Plugin exports.plugin(options, params, plugin)
|
284 |
|
285 | Called when the plugin is loaded.
|
286 |
|
287 | - `options` - options which are passed to the plugin, along with every other plugin.
|
288 | - `params` - parameters which are specific to the loaded plugin.
|
289 | - `plugin` - the plugin loader. Also accessible via `this`.
|
290 | - return type can be `void`, or an `object`.
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|