mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-11-03 20:45:58 +01:00 
			
		
		
		
	issue #478 - hot-swapping of plugins
This commit is contained in:
		
							
								
								
									
										12
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,7 +1,3 @@
 | 
				
			|||||||
#################
 | 
					 | 
				
			||||||
## npm
 | 
					 | 
				
			||||||
#################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
npm-debug.log
 | 
					npm-debug.log
 | 
				
			||||||
node_modules/
 | 
					node_modules/
 | 
				
			||||||
sftp-config.json
 | 
					sftp-config.json
 | 
				
			||||||
@@ -9,12 +5,10 @@ config.json
 | 
				
			|||||||
public/src/nodebb.min.js
 | 
					public/src/nodebb.min.js
 | 
				
			||||||
public/config.json
 | 
					public/config.json
 | 
				
			||||||
public/css/*.css
 | 
					public/css/*.css
 | 
				
			||||||
public/themes/*
 | 
					 | 
				
			||||||
!/public/themes/vanilla
 | 
					 | 
				
			||||||
!/public/themes/cerulean
 | 
					 | 
				
			||||||
!/public/themes/modern
 | 
					 | 
				
			||||||
*.sublime-project
 | 
					*.sublime-project
 | 
				
			||||||
*.sublime-workspace
 | 
					*.sublime-workspace
 | 
				
			||||||
plugins/*
 | 
					 | 
				
			||||||
.project
 | 
					.project
 | 
				
			||||||
*.swp
 | 
					*.swp
 | 
				
			||||||
 | 
					Vagrantfile
 | 
				
			||||||
 | 
					.vagrant
 | 
				
			||||||
 | 
					provision.sh
 | 
				
			||||||
@@ -17,8 +17,31 @@ var fs = require('fs'),
 | 
				
			|||||||
			if (this.initialized) return;
 | 
								if (this.initialized) return;
 | 
				
			||||||
			if (global.env === 'development') winston.info('[plugins] Initializing plugins system');
 | 
								if (global.env === 'development') winston.info('[plugins] Initializing plugins system');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.reload(function(err) {
 | 
				
			||||||
 | 
									if (err) {
 | 
				
			||||||
 | 
										if (global.env === 'development') winston.info('[plugins] NodeBB encountered a problem while loading plugins', err.message);
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (global.env === 'development') winston.info('[plugins] Plugins OK');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									plugins.initialized = true;
 | 
				
			||||||
 | 
									plugins.readyEvent.emit('ready');
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							ready: function(callback) {
 | 
				
			||||||
 | 
								if (!this.initialized) this.readyEvent.once('ready', callback);
 | 
				
			||||||
 | 
								else callback();
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							initialized: false,
 | 
				
			||||||
 | 
							reload: function(callback) {
 | 
				
			||||||
			var _self = this;
 | 
								var _self = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Resetting all local plugin data
 | 
				
			||||||
 | 
								this.loadedHooks = {};
 | 
				
			||||||
 | 
								this.staticDirs = {};
 | 
				
			||||||
 | 
								this.cssFiles.length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Read the list of activated plugins and require their libraries
 | 
								// Read the list of activated plugins and require their libraries
 | 
				
			||||||
			async.waterfall([
 | 
								async.waterfall([
 | 
				
			||||||
				function(next) {
 | 
									function(next) {
 | 
				
			||||||
@@ -47,23 +70,8 @@ var fs = require('fs'),
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					next();
 | 
										next();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			], function(err) {
 | 
								], callback);
 | 
				
			||||||
				if (err) {
 | 
					 | 
				
			||||||
					if (global.env === 'development') winston.info('[plugins] NodeBB encountered a problem while loading plugins', err.message);
 | 
					 | 
				
			||||||
					return;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (global.env === 'development') winston.info('[plugins] Plugins OK');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				_self.initialized = true;
 | 
					 | 
				
			||||||
				_self.readyEvent.emit('ready');
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		ready: function(callback) {
 | 
					 | 
				
			||||||
			if (!this.initialized) this.readyEvent.once('ready', callback);
 | 
					 | 
				
			||||||
			else callback();
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		initialized: false,
 | 
					 | 
				
			||||||
		loadPlugin: function(pluginPath, callback) {
 | 
							loadPlugin: function(pluginPath, callback) {
 | 
				
			||||||
			var _self = this;
 | 
								var _self = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -80,16 +88,25 @@ var fs = require('fs'),
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
							fs.exists(libraryPath, function(exists) {
 | 
												fs.exists(libraryPath, function(exists) {
 | 
				
			||||||
								if (exists) {
 | 
													if (exists) {
 | 
				
			||||||
 | 
														if (!_self.libraries[pluginData.id]) {
 | 
				
			||||||
										_self.libraries[pluginData.id] = require(libraryPath);
 | 
															_self.libraries[pluginData.id] = require(libraryPath);
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														// Register hooks for this plugin
 | 
				
			||||||
									if (pluginData.hooks && Array.isArray(pluginData.hooks) && pluginData.hooks.length > 0) {
 | 
														if (pluginData.hooks && Array.isArray(pluginData.hooks) && pluginData.hooks.length > 0) {
 | 
				
			||||||
										async.each(pluginData.hooks, function(hook, next) {
 | 
															async.each(pluginData.hooks, function(hook, next) {
 | 
				
			||||||
											_self.registerHook(pluginData.id, hook, next);
 | 
																_self.registerHook(pluginData.id, hook, next);
 | 
				
			||||||
										}, next);
 | 
															}, next);
 | 
				
			||||||
									}
 | 
														}
 | 
				
			||||||
 | 
													} else {
 | 
				
			||||||
 | 
														winston.warn('[plugins.reload] Library not found for plugin: ' + pluginData.id);
 | 
				
			||||||
 | 
														next();
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							});
 | 
												});
 | 
				
			||||||
						} else next();
 | 
											} else {
 | 
				
			||||||
 | 
												winston.warn('[plugins.reload] Library not found for plugin: ' + pluginData.id);
 | 
				
			||||||
 | 
												next();
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					function(next) {
 | 
										function(next) {
 | 
				
			||||||
						// Static Directories for Plugins
 | 
											// Static Directories for Plugins
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								src/routes/plugins.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/routes/plugins.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					var	nconf = require('nconf'),
 | 
				
			||||||
 | 
						path = require('path'),
 | 
				
			||||||
 | 
						fs = require('fs'),
 | 
				
			||||||
 | 
						Plugins = require('../plugins'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PluginRoutes = function(app) {
 | 
				
			||||||
 | 
							// Static Assets
 | 
				
			||||||
 | 
							app.get('/plugins/:id/*', function(req, res) {
 | 
				
			||||||
 | 
								var	relPath = req.url.replace('/plugins/' + req.params.id, '');
 | 
				
			||||||
 | 
								if (Plugins.staticDirs[req.params.id]) {
 | 
				
			||||||
 | 
									var	fullPath = path.join(Plugins.staticDirs[req.params.id], relPath);
 | 
				
			||||||
 | 
									fs.exists(fullPath, function(exists) {
 | 
				
			||||||
 | 
										if (exists) {
 | 
				
			||||||
 | 
											res.sendfile(fullPath);
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											res.redirect('/404');
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									res.redirect('/404');
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = PluginRoutes;
 | 
				
			||||||
@@ -151,19 +151,6 @@ var express = require('express'),
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			function(next) {
 | 
								function(next) {
 | 
				
			||||||
				async.parallel([
 | 
									async.parallel([
 | 
				
			||||||
					function(next) {
 | 
					 | 
				
			||||||
						// Static Directories for NodeBB Plugins
 | 
					 | 
				
			||||||
						plugins.ready(function () {
 | 
					 | 
				
			||||||
							for (d in plugins.staticDirs) {
 | 
					 | 
				
			||||||
								app.use(nconf.get('relative_path') + '/plugins/' + d, express.static(plugins.staticDirs[d]));
 | 
					 | 
				
			||||||
								if (process.env.NODE_ENV === 'development') {
 | 
					 | 
				
			||||||
									winston.info('Static directory routed for plugin: ' + d);
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							next();
 | 
					 | 
				
			||||||
						});
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
					function(next) {
 | 
										function(next) {
 | 
				
			||||||
						// Theme configuration
 | 
											// Theme configuration
 | 
				
			||||||
						RDB.hmget('config', 'theme:type', 'theme:id', 'theme:staticDir', 'theme:templates', function(err, themeData) {
 | 
											RDB.hmget('config', 'theme:type', 'theme:id', 'theme:staticDir', 'theme:templates', function(err, themeData) {
 | 
				
			||||||
@@ -701,6 +688,9 @@ var express = require('express'),
 | 
				
			|||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Other routes
 | 
				
			||||||
 | 
							require('./routes/plugins')(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Debug routes
 | 
							// Debug routes
 | 
				
			||||||
		if (process.env.NODE_ENV === 'development') {
 | 
							if (process.env.NODE_ENV === 'development') {
 | 
				
			||||||
			require('./routes/debug')(app);
 | 
								require('./routes/debug')(app);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user