mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Reorganise how adminApp is setup
This commit is contained in:
		
							
								
								
									
										37
									
								
								red/api/flows.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								red/api/flows.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 **/
 | 
			
		||||
var express = require('express');
 | 
			
		||||
var fs = require("fs");
 | 
			
		||||
var events = require("../events");
 | 
			
		||||
var path = require("path");
 | 
			
		||||
 | 
			
		||||
var redNodes = require("../nodes");
 | 
			
		||||
var settings = require("../settings");
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    get: function(req,res) {
 | 
			
		||||
        res.json(redNodes.getFlows());
 | 
			
		||||
    },
 | 
			
		||||
    post: function(req,res) {
 | 
			
		||||
        var flows = req.body;
 | 
			
		||||
        redNodes.setFlows(flows).then(function() {
 | 
			
		||||
            res.send(204);
 | 
			
		||||
        }).otherwise(function(err) {
 | 
			
		||||
            util.log("[red] Error saving flows : "+err);
 | 
			
		||||
            res.send(500,err.message);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								red/api/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								red/api/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
var express = require("express");
 | 
			
		||||
var util = require('util');
 | 
			
		||||
 | 
			
		||||
var ui = require("./ui");
 | 
			
		||||
var nodes = require("./nodes");
 | 
			
		||||
var flows = require("./flows");
 | 
			
		||||
var library = require("./library");
 | 
			
		||||
 | 
			
		||||
var settings = require("../settings");
 | 
			
		||||
 | 
			
		||||
var errorHandler = function(err,req,res,next) {
 | 
			
		||||
    //TODO: standardize json response
 | 
			
		||||
    res.send(400,err.toString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function init(adminApp) {
 | 
			
		||||
    
 | 
			
		||||
    library.init(adminApp);
 | 
			
		||||
    
 | 
			
		||||
    adminApp.use(express.json());
 | 
			
		||||
    
 | 
			
		||||
    // Editor
 | 
			
		||||
    if (!settings.disableEditor) {
 | 
			
		||||
        adminApp.get("/",ui.ensureSlash);
 | 
			
		||||
        adminApp.get("/icons/:icon",ui.icon);
 | 
			
		||||
        adminApp.get("/settings",ui.settings);
 | 
			
		||||
        adminApp.use("/",ui.editor);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Flows
 | 
			
		||||
    adminApp.get("/flows",flows.get);
 | 
			
		||||
    adminApp.post("/flows",flows.post);
 | 
			
		||||
    
 | 
			
		||||
    // Nodes
 | 
			
		||||
    adminApp.get("/nodes",nodes.getAll);
 | 
			
		||||
    adminApp.post("/nodes",nodes.post);
 | 
			
		||||
 | 
			
		||||
    adminApp.get("/nodes/:id",nodes.get);
 | 
			
		||||
    adminApp.put("/nodes/:id",nodes.put);
 | 
			
		||||
    adminApp.delete("/nodes/:id",nodes.delete);
 | 
			
		||||
    
 | 
			
		||||
    // Library
 | 
			
		||||
    adminApp.post(new RegExp("/library/flows\/(.*)"),library.post);
 | 
			
		||||
    adminApp.get("/library/flows",library.getAll);
 | 
			
		||||
    adminApp.get(new RegExp("/library/flows\/(.*)"),library.get);
 | 
			
		||||
    
 | 
			
		||||
    adminApp.use(errorHandler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    init: init
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										111
									
								
								red/api/library.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								red/api/library.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,111 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright 2013, 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
var util = require("util");
 | 
			
		||||
 | 
			
		||||
var redApp = null;
 | 
			
		||||
var storage = require("../storage");
 | 
			
		||||
 | 
			
		||||
function createLibrary(type) {
 | 
			
		||||
    
 | 
			
		||||
    redApp.get(new RegExp("/library/"+type+"($|\/(.*))"),function(req,res) {
 | 
			
		||||
        var path = req.params[1]||"";
 | 
			
		||||
        storage.getLibraryEntry(type,path).then(function(result) {
 | 
			
		||||
            if (typeof result === "string") {
 | 
			
		||||
                res.writeHead(200, {'Content-Type': 'text/plain'});
 | 
			
		||||
                res.write(result);
 | 
			
		||||
                res.end(); 
 | 
			
		||||
            } else {
 | 
			
		||||
                res.json(result);
 | 
			
		||||
            }
 | 
			
		||||
        }).otherwise(function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                util.log("[red] Error loading library entry '"+path+"' : "+err);
 | 
			
		||||
                if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                    res.send(403);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            res.send(404);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    redApp.post(new RegExp("/library/"+type+"\/(.*)"),function(req,res) {
 | 
			
		||||
        var path = req.params[0];
 | 
			
		||||
        var fullBody = '';
 | 
			
		||||
        req.on('data', function(chunk) {
 | 
			
		||||
                fullBody += chunk.toString();
 | 
			
		||||
        });
 | 
			
		||||
        req.on('end', function() {
 | 
			
		||||
                storage.saveLibraryEntry(type,path,req.query,fullBody).then(function() {
 | 
			
		||||
                    res.send(204);
 | 
			
		||||
                }).otherwise(function(err) {
 | 
			
		||||
                    util.log("[red] Error saving library entry '"+path+"' : "+err);
 | 
			
		||||
                    if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                        res.send(403);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    res.send(500);
 | 
			
		||||
                });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
module.exports = {
 | 
			
		||||
    init: function(app) {
 | 
			
		||||
        redApp = app;
 | 
			
		||||
    },
 | 
			
		||||
    register: createLibrary,
 | 
			
		||||
    
 | 
			
		||||
    getAll: function(req,res) {
 | 
			
		||||
        storage.getAllFlows().then(function(flows) {
 | 
			
		||||
            res.json(flows);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    get: function(req,res) {
 | 
			
		||||
        storage.getFlow(req.params[0]).then(function(data) {
 | 
			
		||||
            res.set('Content-Type', 'application/json');
 | 
			
		||||
            res.send(data);
 | 
			
		||||
        }).otherwise(function(err) {
 | 
			
		||||
            if (err) {
 | 
			
		||||
                util.log("[red] Error loading flow '"+req.params[0]+"' : "+err);
 | 
			
		||||
                if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                    res.send(403);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            res.send(404);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    post: function(req,res) {
 | 
			
		||||
        //TODO: do content-type properly
 | 
			
		||||
        var fullBody = '';
 | 
			
		||||
        req.on('data', function(chunk) {
 | 
			
		||||
            fullBody += chunk.toString();
 | 
			
		||||
        });
 | 
			
		||||
        req.on('end', function() {
 | 
			
		||||
            storage.saveFlow(req.params[0],fullBody).then(function() {
 | 
			
		||||
                res.send(204);
 | 
			
		||||
            }).otherwise(function(err) {
 | 
			
		||||
                util.log("[red] Error loading flow '"+req.params[0]+"' : "+err);
 | 
			
		||||
                if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                    res.send(403);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                res.send(500);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										156
									
								
								red/api/nodes.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								red/api/nodes.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,156 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 **/
 | 
			
		||||
var express = require('express');
 | 
			
		||||
var fs = require("fs");
 | 
			
		||||
var path = require("path");
 | 
			
		||||
var when = require('when');
 | 
			
		||||
var util = require('util');
 | 
			
		||||
 | 
			
		||||
var events = require("../events");
 | 
			
		||||
var redNodes = require("../nodes");
 | 
			
		||||
var comms = require("../comms");
 | 
			
		||||
var server = require("../server");
 | 
			
		||||
 | 
			
		||||
var settings = require("../settings");
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getAll: function(req,res) {
 | 
			
		||||
        if (req.get("accept") == "application/json") {
 | 
			
		||||
            res.json(redNodes.getNodeList());
 | 
			
		||||
        } else {
 | 
			
		||||
            res.send(redNodes.getNodeConfigs());
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    post: function(req,res) {
 | 
			
		||||
        if (!settings.available()) {
 | 
			
		||||
            res.send(400,new Error("Settings unavailable").toString());
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        var node = req.body;
 | 
			
		||||
        var promise;
 | 
			
		||||
        if (node.file) {
 | 
			
		||||
            promise = redNodes.addNode(node.file).then(server.reportAddedModules);
 | 
			
		||||
        } else if (node.module) {
 | 
			
		||||
            var module = redNodes.getNodeModuleInfo(node.module);
 | 
			
		||||
            if (module) {
 | 
			
		||||
                res.send(400,"Module already loaded");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            promise = server.installModule(node.module);
 | 
			
		||||
        } else {
 | 
			
		||||
            res.send(400,"Invalid request");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        promise.then(function(info) {
 | 
			
		||||
                res.json(info);
 | 
			
		||||
        }).otherwise(function(err) {
 | 
			
		||||
            if (err.code === 404) {
 | 
			
		||||
                res.send(404);
 | 
			
		||||
            } else {
 | 
			
		||||
                res.send(400,err.toString());
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    
 | 
			
		||||
    delete: function(req,res) {
 | 
			
		||||
        if (!settings.available()) {
 | 
			
		||||
            res.send(400,new Error("Settings unavailable").toString());
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        var id = req.params.id;
 | 
			
		||||
        var removedNodes = [];
 | 
			
		||||
        try {
 | 
			
		||||
            var node = redNodes.getNodeInfo(id);
 | 
			
		||||
            var promise = null;
 | 
			
		||||
            if (!node) {
 | 
			
		||||
                var module = redNodes.getNodeModuleInfo(id);
 | 
			
		||||
                if (!module) {
 | 
			
		||||
                    res.send(404);
 | 
			
		||||
                    return;
 | 
			
		||||
                } else {
 | 
			
		||||
                    promise = server.uninstallModule(id);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                promise = when.resolve([redNodes.removeNode(id)]).then(server.reportRemovedModules);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            promise.then(function(removedNodes) {
 | 
			
		||||
                res.json(removedNodes);
 | 
			
		||||
            }).otherwise(function(err) {
 | 
			
		||||
                console.log(err.stack);
 | 
			
		||||
                res.send(400,err.toString());
 | 
			
		||||
            });
 | 
			
		||||
        } catch(err) {
 | 
			
		||||
            res.send(400,err.toString());
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    
 | 
			
		||||
    get: function(req,res) {
 | 
			
		||||
        var id = req.params.id;
 | 
			
		||||
        var result = null;
 | 
			
		||||
        if (req.get("accept") == "application/json") {
 | 
			
		||||
            result = redNodes.getNodeInfo(id);
 | 
			
		||||
        } else {
 | 
			
		||||
            result = redNodes.getNodeConfig(id);
 | 
			
		||||
        }
 | 
			
		||||
        if (result) {
 | 
			
		||||
            res.send(result);
 | 
			
		||||
        } else {
 | 
			
		||||
            res.send(404);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    
 | 
			
		||||
    put: function(req,res) {
 | 
			
		||||
        if (!settings.available()) {
 | 
			
		||||
            res.send(400,new Error("Settings unavailable").toString());
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        var body = req.body;
 | 
			
		||||
        if (!body.hasOwnProperty("enabled")) {
 | 
			
		||||
            res.send(400,"Invalid request");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            var info;
 | 
			
		||||
            var id = req.params.id;
 | 
			
		||||
            var node = redNodes.getNodeInfo(id);
 | 
			
		||||
            if (!node) {
 | 
			
		||||
                res.send(404);
 | 
			
		||||
            } else if (!node.err && node.enabled === body.enabled) {
 | 
			
		||||
                res.json(node);
 | 
			
		||||
            } else {
 | 
			
		||||
                if (body.enabled) {
 | 
			
		||||
                    info = redNodes.enableNode(id);
 | 
			
		||||
                } else {
 | 
			
		||||
                    info = redNodes.disableNode(id);
 | 
			
		||||
                }
 | 
			
		||||
                if (info.enabled == body.enabled && !info.err) {
 | 
			
		||||
                    comms.publish("node/"+(body.enabled?"enabled":"disabled"),info,false);
 | 
			
		||||
                    util.log("[red] "+(body.enabled?"Enabled":"Disabled")+" node types:");
 | 
			
		||||
                    for (var i=0;i<info.types.length;i++) {
 | 
			
		||||
                        util.log("[red] - "+info.types[i]);
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (body.enabled && info.err) {
 | 
			
		||||
                    util.log("[red] Failed to enable node:");
 | 
			
		||||
                    util.log("[red] - "+info.name+" : "+info.err);
 | 
			
		||||
                }
 | 
			
		||||
                res.json(info);
 | 
			
		||||
            }
 | 
			
		||||
        } catch(err) {
 | 
			
		||||
            res.send(400,err.toString());
 | 
			
		||||
        }            
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -15,37 +15,29 @@
 | 
			
		||||
 **/
 | 
			
		||||
var express = require('express');
 | 
			
		||||
var fs = require("fs");
 | 
			
		||||
var events = require("./events");
 | 
			
		||||
var path = require("path");
 | 
			
		||||
 | 
			
		||||
var icon_paths = [path.resolve(__dirname + '/../public/icons')];
 | 
			
		||||
var events = require("../events");
 | 
			
		||||
var settings = require("../settings");
 | 
			
		||||
 | 
			
		||||
var settings; // settings has to be global, otherwise variable not in scope for express
 | 
			
		||||
var icon_paths = [path.resolve(__dirname + '/../../public/icons')];
 | 
			
		||||
var iconCache = {};
 | 
			
		||||
//TODO: create a default icon
 | 
			
		||||
var defaultIcon = path.resolve(__dirname + '/../../public/icons/arrow-in.png');
 | 
			
		||||
 | 
			
		||||
events.on("node-icon-dir",function(dir) {
 | 
			
		||||
    icon_paths.push(path.resolve(dir));
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function setupUI(_settings,app) {
 | 
			
		||||
    
 | 
			
		||||
    settings = _settings;
 | 
			
		||||
    
 | 
			
		||||
    // Need to ensure the url ends with a '/' so the static serving works
 | 
			
		||||
    // with relative paths
 | 
			
		||||
    app.get("/",function(req,res) {
 | 
			
		||||
module.exports = {
 | 
			
		||||
    ensureSlash: function(req,res,next) {
 | 
			
		||||
        if (req.originalUrl.slice(-1) != "/") {
 | 
			
		||||
            res.redirect(req.originalUrl+"/");
 | 
			
		||||
        } else {
 | 
			
		||||
            req.next();
 | 
			
		||||
            next();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    var iconCache = {};
 | 
			
		||||
    //TODO: create a default icon
 | 
			
		||||
    var defaultIcon = path.resolve(__dirname + '/../public/icons/arrow-in.png');
 | 
			
		||||
    
 | 
			
		||||
    app.get("/icons/:icon",function(req,res) {
 | 
			
		||||
    },
 | 
			
		||||
    icon: function(req,res) {
 | 
			
		||||
        if (iconCache[req.params.icon]) {
 | 
			
		||||
            res.sendfile(iconCache[req.params.icon]); // if not found, express prints this to the console and serves 404
 | 
			
		||||
        } else { 
 | 
			
		||||
@@ -59,19 +51,13 @@ function setupUI(_settings,app) {
 | 
			
		||||
            }
 | 
			
		||||
            res.sendfile(defaultIcon);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    app.get("/settings", function(req,res) {
 | 
			
		||||
    },
 | 
			
		||||
    settings: function(req,res) {
 | 
			
		||||
        var safeSettings = {
 | 
			
		||||
            httpNodeRoot: settings.httpNodeRoot,
 | 
			
		||||
            version: settings.version
 | 
			
		||||
        };
 | 
			
		||||
        res.json(safeSettings);
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    app.use("/",express.static(__dirname + '/../public'));
 | 
			
		||||
    
 | 
			
		||||
    return app;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = setupUI;
 | 
			
		||||
    },
 | 
			
		||||
    editor: express.static(__dirname + '/../../public')
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										117
									
								
								red/library.js
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								red/library.js
									
									
									
									
									
								
							@@ -1,117 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright 2013 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
var util = require("util");
 | 
			
		||||
 | 
			
		||||
var redApp = null;
 | 
			
		||||
var storage = null;
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
    redApp = require("./server").app;
 | 
			
		||||
    storage = require("./storage");
 | 
			
		||||
    
 | 
			
		||||
    // -------- Flow Library --------
 | 
			
		||||
    redApp.post(new RegExp("/library/flows\/(.*)"), function(req,res) {
 | 
			
		||||
            var fullBody = '';
 | 
			
		||||
            req.on('data', function(chunk) {
 | 
			
		||||
                fullBody += chunk.toString();
 | 
			
		||||
            });
 | 
			
		||||
            req.on('end', function() {
 | 
			
		||||
                storage.saveFlow(req.params[0],fullBody).then(function() {
 | 
			
		||||
                    res.send(204);
 | 
			
		||||
                }).otherwise(function(err) {
 | 
			
		||||
                    util.log("[red] Error loading flow '"+req.params[0]+"' : "+err);
 | 
			
		||||
                    if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                        res.send(403);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    res.send(500);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    redApp.get("/library/flows",function(req,res) {
 | 
			
		||||
            storage.getAllFlows().then(function(flows) {
 | 
			
		||||
                res.json(flows);
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    redApp.get(new RegExp("/library/flows\/(.*)"), function(req,res) {
 | 
			
		||||
            storage.getFlow(req.params[0]).then(function(data) {
 | 
			
		||||
                res.set('Content-Type', 'application/json');
 | 
			
		||||
                res.send(data);
 | 
			
		||||
            }).otherwise(function(err) {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    util.log("[red] Error loading flow '"+req.params[0]+"' : "+err);
 | 
			
		||||
                    if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                        res.send(403);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                res.send(404);
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    // ------------------------------
 | 
			
		||||
}    
 | 
			
		||||
 | 
			
		||||
function createLibrary(type) {
 | 
			
		||||
    
 | 
			
		||||
    redApp.get(new RegExp("/library/"+type+"($|\/(.*))"),function(req,res) {
 | 
			
		||||
            var path = req.params[1]||"";
 | 
			
		||||
            storage.getLibraryEntry(type,path).then(function(result) {
 | 
			
		||||
                if (typeof result === "string") {
 | 
			
		||||
                    res.writeHead(200, {'Content-Type': 'text/plain'});
 | 
			
		||||
                    res.write(result);
 | 
			
		||||
                    res.end(); 
 | 
			
		||||
                } else {
 | 
			
		||||
                    res.json(result);
 | 
			
		||||
                }
 | 
			
		||||
            }).otherwise(function(err) {
 | 
			
		||||
                if (err) {
 | 
			
		||||
                    util.log("[red] Error loading library entry '"+path+"' : "+err);
 | 
			
		||||
                    if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                        res.send(403);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                res.send(404);
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    redApp.post(new RegExp("/library/"+type+"\/(.*)"),function(req,res) {
 | 
			
		||||
            var path = req.params[0];
 | 
			
		||||
            var fullBody = '';
 | 
			
		||||
            req.on('data', function(chunk) {
 | 
			
		||||
                    fullBody += chunk.toString();
 | 
			
		||||
            });
 | 
			
		||||
            req.on('end', function() {
 | 
			
		||||
                    storage.saveLibraryEntry(type,path,req.query,fullBody).then(function() {
 | 
			
		||||
                        res.send(204);
 | 
			
		||||
                    }).otherwise(function(err) {
 | 
			
		||||
                        util.log("[red] Error saving library entry '"+path+"' : "+err);
 | 
			
		||||
                        if (err.message.indexOf('forbidden') === 0) {
 | 
			
		||||
                            res.send(403);
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                        res.send(500);
 | 
			
		||||
                    });
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.init = init;
 | 
			
		||||
module.exports.register = createLibrary;
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
var server = require("./server");
 | 
			
		||||
var nodes = require("./nodes");
 | 
			
		||||
var library = require("./library");
 | 
			
		||||
var library = require("./api/library");
 | 
			
		||||
var comms = require("./comms");
 | 
			
		||||
var log = require("./log");
 | 
			
		||||
var util = require("./util");
 | 
			
		||||
@@ -36,14 +36,13 @@ var RED = {
 | 
			
		||||
        userSettings.version = this.version();
 | 
			
		||||
        settings.init(userSettings);
 | 
			
		||||
        server.init(httpServer,settings);
 | 
			
		||||
        library.init();
 | 
			
		||||
        return server.app;
 | 
			
		||||
    },
 | 
			
		||||
    
 | 
			
		||||
    start: server.start,
 | 
			
		||||
    stop: server.stop,
 | 
			
		||||
    nodes: nodes,
 | 
			
		||||
    library: library,
 | 
			
		||||
    library: { register: library.register },
 | 
			
		||||
    credentials: credentials,
 | 
			
		||||
    events: events,
 | 
			
		||||
    log: log,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										318
									
								
								red/server.js
									
									
									
									
									
								
							
							
						
						
									
										318
									
								
								red/server.js
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright 2013 IBM Corp.
 | 
			
		||||
 * Copyright 2013, 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
@@ -19,7 +19,6 @@ var util = require('util');
 | 
			
		||||
var when = require('when');
 | 
			
		||||
var exec = require('child_process').exec;
 | 
			
		||||
 | 
			
		||||
var createUI = require("./ui");
 | 
			
		||||
var redNodes = require("./nodes");
 | 
			
		||||
var comms = require("./comms");
 | 
			
		||||
var storage = require("./storage");
 | 
			
		||||
@@ -37,178 +36,81 @@ function createServer(_server,_settings) {
 | 
			
		||||
    
 | 
			
		||||
    nodeApp = express();
 | 
			
		||||
    app = express();
 | 
			
		||||
        
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    if (settings.httpAdminRoot !== false) {
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        if (!settings.disableEditor) {
 | 
			
		||||
            createUI(settings,app);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        app.get("/flows",function(req,res) {
 | 
			
		||||
            res.json(redNodes.getFlows());
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        app.post("/flows",
 | 
			
		||||
            express.json(),
 | 
			
		||||
            function(req,res) {
 | 
			
		||||
                var flows = req.body;
 | 
			
		||||
                redNodes.setFlows(flows).then(function() {
 | 
			
		||||
                    res.send(204);
 | 
			
		||||
                }).otherwise(function(err) {
 | 
			
		||||
                    util.log("[red] Error saving flows : "+err);
 | 
			
		||||
                    res.send(500,err.message);
 | 
			
		||||
                });
 | 
			
		||||
            },
 | 
			
		||||
            function(error,req,res,next) {
 | 
			
		||||
                res.send(400,"Invalid Flow");
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
            
 | 
			
		||||
        app.get("/nodes",function(req,res) {
 | 
			
		||||
            if (req.get("accept") == "application/json") {
 | 
			
		||||
                res.json(redNodes.getNodeList());
 | 
			
		||||
            } else {
 | 
			
		||||
                res.send(redNodes.getNodeConfigs());
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        app.post("/nodes",
 | 
			
		||||
            express.json(),
 | 
			
		||||
            function(req,res) {
 | 
			
		||||
                if (!settings.available()) {
 | 
			
		||||
                    res.send(400,new Error("Settings unavailable").toString());
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var node = req.body;
 | 
			
		||||
                var promise;
 | 
			
		||||
                if (node.file) {
 | 
			
		||||
                    promise = redNodes.addNode(node.file).then(reportAddedModules);
 | 
			
		||||
                } else if (node.module) {
 | 
			
		||||
                    var module = redNodes.getNodeModuleInfo(node.module);
 | 
			
		||||
                    if (module) {
 | 
			
		||||
                        res.send(400,"Module already loaded");
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    promise = installModule(node.module);
 | 
			
		||||
                } else {
 | 
			
		||||
                    res.send(400,"Invalid request");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                promise.then(function(info) {
 | 
			
		||||
                    res.json(info);
 | 
			
		||||
                }).otherwise(function(err) {
 | 
			
		||||
                    if (err.code === 404) {
 | 
			
		||||
                        res.send(404);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        res.send(400,err.toString());
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            },
 | 
			
		||||
            function(err,req,res,next) {
 | 
			
		||||
                console.log(err.toString());
 | 
			
		||||
                res.send(400,err);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        app.delete("/nodes/:id",
 | 
			
		||||
            function(req,res) {
 | 
			
		||||
                if (!settings.available()) {
 | 
			
		||||
                    res.send(400,new Error("Settings unavailable").toString());
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var id = req.params.id;
 | 
			
		||||
                var removedNodes = [];
 | 
			
		||||
                try {
 | 
			
		||||
                    var node = redNodes.getNodeInfo(id);
 | 
			
		||||
                    var promise = null;
 | 
			
		||||
                    if (!node) {
 | 
			
		||||
                        var module = redNodes.getNodeModuleInfo(id);
 | 
			
		||||
                        if (!module) {
 | 
			
		||||
                            res.send(404);
 | 
			
		||||
                            return;
 | 
			
		||||
                        } else {
 | 
			
		||||
                            promise = uninstallModule(id);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        promise = when.resolve([redNodes.removeNode(id)]).then(reportRemovedModules);
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    promise.then(function(removedNodes) {
 | 
			
		||||
                        res.json(removedNodes);
 | 
			
		||||
                    }).otherwise(function(err) {
 | 
			
		||||
                        console.log(err.stack);
 | 
			
		||||
                        res.send(400,err.toString());
 | 
			
		||||
                    });
 | 
			
		||||
                } catch(err) {
 | 
			
		||||
                    res.send(400,err.toString());
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            function(err,req,res,next) {
 | 
			
		||||
                res.send(400,err);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        app.get("/nodes/:id", function(req,res) {
 | 
			
		||||
            var id = req.params.id;
 | 
			
		||||
            var result = null;
 | 
			
		||||
            if (req.get("accept") == "application/json") {
 | 
			
		||||
                result = redNodes.getNodeInfo(id);
 | 
			
		||||
            } else {
 | 
			
		||||
                result = redNodes.getNodeConfig(id);
 | 
			
		||||
            }
 | 
			
		||||
            if (result) {
 | 
			
		||||
                res.send(result);
 | 
			
		||||
            } else {
 | 
			
		||||
                res.send(404);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
        app.put("/nodes/:id", 
 | 
			
		||||
            express.json(),
 | 
			
		||||
            function(req,res) {
 | 
			
		||||
                if (!settings.available()) {
 | 
			
		||||
                    res.send(400,new Error("Settings unavailable").toString());
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var body = req.body;
 | 
			
		||||
                if (!body.hasOwnProperty("enabled")) {
 | 
			
		||||
                    res.send(400,"Invalid request");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                try {
 | 
			
		||||
                    var info;
 | 
			
		||||
                    var id = req.params.id;
 | 
			
		||||
                    var node = redNodes.getNodeInfo(id);
 | 
			
		||||
                    if (!node) {
 | 
			
		||||
                        res.send(404);
 | 
			
		||||
                    } else if (!node.err && node.enabled === body.enabled) {
 | 
			
		||||
                        res.json(node);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (body.enabled) {
 | 
			
		||||
                            info = redNodes.enableNode(id);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            info = redNodes.disableNode(id);
 | 
			
		||||
                        }
 | 
			
		||||
                        if (info.enabled == body.enabled && !info.err) {
 | 
			
		||||
                            comms.publish("node/"+(body.enabled?"enabled":"disabled"),info,false);
 | 
			
		||||
                            util.log("[red] "+(body.enabled?"Enabled":"Disabled")+" node types:");
 | 
			
		||||
                            for (var i=0;i<info.types.length;i++) {
 | 
			
		||||
                                util.log("[red] - "+info.types[i]);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else if (body.enabled && info.err) {
 | 
			
		||||
                            util.log("[red] Failed to enable node:");
 | 
			
		||||
                            util.log("[red] - "+info.name+" : "+info.err);
 | 
			
		||||
                        }
 | 
			
		||||
                        res.json(info);
 | 
			
		||||
                    }
 | 
			
		||||
                } catch(err) {
 | 
			
		||||
                    res.send(400,err.toString());
 | 
			
		||||
                }            
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        require("./api").init(app);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function start() {
 | 
			
		||||
    var defer = when.defer();
 | 
			
		||||
    
 | 
			
		||||
    storage.init(settings).then(function() {
 | 
			
		||||
        settings.load(storage).then(function() {
 | 
			
		||||
            console.log("\nWelcome to Node-RED\n===================\n");
 | 
			
		||||
            if (settings.version) {
 | 
			
		||||
                util.log("[red] Version: "+settings.version);
 | 
			
		||||
            }
 | 
			
		||||
            util.log("[red] Loading palette nodes");
 | 
			
		||||
            redNodes.init(settings,storage);
 | 
			
		||||
            redNodes.load().then(function() {
 | 
			
		||||
                var i;
 | 
			
		||||
                var nodes = redNodes.getNodeList();
 | 
			
		||||
                var nodeErrors = nodes.filter(function(n) { return n.err!=null;});
 | 
			
		||||
                var nodeMissing = nodes.filter(function(n) { return n.module && n.enabled && !n.loaded && !n.err;});
 | 
			
		||||
                if (nodeErrors.length > 0) {
 | 
			
		||||
                    util.log("------------------------------------------");
 | 
			
		||||
                    if (settings.verbose) {
 | 
			
		||||
                        for (i=0;i<nodeErrors.length;i+=1) {
 | 
			
		||||
                            util.log("["+nodeErrors[i].name+"] "+nodeErrors[i].err);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        util.log("[red] Failed to register "+nodeErrors.length+" node type"+(nodeErrors.length==1?"":"s"));
 | 
			
		||||
                        util.log("[red] Run with -v for details");
 | 
			
		||||
                    }
 | 
			
		||||
                    util.log("------------------------------------------");
 | 
			
		||||
                }
 | 
			
		||||
                if (nodeMissing.length > 0) {
 | 
			
		||||
                    util.log("[red] Missing node modules:");
 | 
			
		||||
                    var missingModules = {};
 | 
			
		||||
                    for (i=0;i<nodeMissing.length;i++) {
 | 
			
		||||
                        var missing = nodeMissing[i];
 | 
			
		||||
                        missingModules[missing.module] = (missingModules[missing.module]||[]).concat(missing.types);
 | 
			
		||||
                    }
 | 
			
		||||
                    var promises = [];
 | 
			
		||||
                    for (i in missingModules) {
 | 
			
		||||
                        if (missingModules.hasOwnProperty(i)) {
 | 
			
		||||
                            util.log("[red] - "+i+": "+missingModules[i].join(", "));
 | 
			
		||||
                            if (settings.autoInstallModules) {
 | 
			
		||||
                                installModule(i).otherwise(function(err) {
 | 
			
		||||
                                    // Error already reported. Need the otherwise handler
 | 
			
		||||
                                    // to stop the error propagating any further
 | 
			
		||||
                                });
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!settings.autoInstallModules) {
 | 
			
		||||
                        util.log("[red] Removing modules from config");
 | 
			
		||||
                        redNodes.cleanNodeList();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                defer.resolve();
 | 
			
		||||
                
 | 
			
		||||
                redNodes.loadFlows();
 | 
			
		||||
            }).otherwise(function(err) {
 | 
			
		||||
                console.log(err);
 | 
			
		||||
            });
 | 
			
		||||
            comms.start();
 | 
			
		||||
        });
 | 
			
		||||
    }).otherwise(function(err) {
 | 
			
		||||
        defer.reject(err);
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    return defer.promise;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function reportAddedModules(info) {
 | 
			
		||||
    comms.publish("node/added",info,false);
 | 
			
		||||
    if (info.length > 0) {
 | 
			
		||||
@@ -292,72 +194,7 @@ function uninstallModule(module) {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function start() {
 | 
			
		||||
    var defer = when.defer();
 | 
			
		||||
    
 | 
			
		||||
    storage.init(settings).then(function() {
 | 
			
		||||
        settings.load(storage).then(function() {
 | 
			
		||||
            console.log("\nWelcome to Node-RED\n===================\n");
 | 
			
		||||
            if (settings.version) {
 | 
			
		||||
                util.log("[red] Version: "+settings.version);
 | 
			
		||||
            }
 | 
			
		||||
            util.log("[red] Loading palette nodes");
 | 
			
		||||
            redNodes.init(settings,storage);
 | 
			
		||||
            redNodes.load().then(function() {
 | 
			
		||||
                var i;
 | 
			
		||||
                var nodes = redNodes.getNodeList();
 | 
			
		||||
                var nodeErrors = nodes.filter(function(n) { return n.err!=null;});
 | 
			
		||||
                var nodeMissing = nodes.filter(function(n) { return n.module && n.enabled && !n.loaded && !n.err;});
 | 
			
		||||
                if (nodeErrors.length > 0) {
 | 
			
		||||
                    util.log("------------------------------------------");
 | 
			
		||||
                    if (settings.verbose) {
 | 
			
		||||
                        for (i=0;i<nodeErrors.length;i+=1) {
 | 
			
		||||
                            util.log("["+nodeErrors[i].name+"] "+nodeErrors[i].err);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        util.log("[red] Failed to register "+nodeErrors.length+" node type"+(nodeErrors.length==1?"":"s"));
 | 
			
		||||
                        util.log("[red] Run with -v for details");
 | 
			
		||||
                    }
 | 
			
		||||
                    util.log("------------------------------------------");
 | 
			
		||||
                }
 | 
			
		||||
                if (nodeMissing.length > 0) {
 | 
			
		||||
                    util.log("[red] Missing node modules:");
 | 
			
		||||
                    var missingModules = {};
 | 
			
		||||
                    for (i=0;i<nodeMissing.length;i++) {
 | 
			
		||||
                        var missing = nodeMissing[i];
 | 
			
		||||
                        missingModules[missing.module] = (missingModules[missing.module]||[]).concat(missing.types);
 | 
			
		||||
                    }
 | 
			
		||||
                    var promises = [];
 | 
			
		||||
                    for (i in missingModules) {
 | 
			
		||||
                        if (missingModules.hasOwnProperty(i)) {
 | 
			
		||||
                            util.log("[red] - "+i+": "+missingModules[i].join(", "));
 | 
			
		||||
                            if (settings.autoInstallModules) {
 | 
			
		||||
                                installModule(i).otherwise(function(err) {
 | 
			
		||||
                                    // Error already reported. Need the otherwise handler
 | 
			
		||||
                                    // to stop the error propagating any further
 | 
			
		||||
                                });
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!settings.autoInstallModules) {
 | 
			
		||||
                        util.log("[red] Removing modules from config");
 | 
			
		||||
                        redNodes.cleanNodeList();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                defer.resolve();
 | 
			
		||||
                
 | 
			
		||||
                redNodes.loadFlows();
 | 
			
		||||
            }).otherwise(function(err) {
 | 
			
		||||
                console.log(err);
 | 
			
		||||
            });
 | 
			
		||||
            comms.start();
 | 
			
		||||
        });
 | 
			
		||||
    }).otherwise(function(err) {
 | 
			
		||||
        defer.reject(err);
 | 
			
		||||
    });
 | 
			
		||||
    
 | 
			
		||||
    return defer.promise;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function stop() {
 | 
			
		||||
    redNodes.stopFlows();
 | 
			
		||||
@@ -367,7 +204,12 @@ function stop() {
 | 
			
		||||
module.exports = { 
 | 
			
		||||
    init: createServer,
 | 
			
		||||
    start: start,
 | 
			
		||||
    stop: stop
 | 
			
		||||
    stop: stop,
 | 
			
		||||
    
 | 
			
		||||
    reportAddedModules: reportAddedModules,
 | 
			
		||||
    reportRemovedModules: reportRemovedModules,
 | 
			
		||||
    installModule: installModule,
 | 
			
		||||
    uninstallModule: uninstallModule
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.__defineGetter__("app", function() { return app });
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user