Add node module update api and expose in palette editor

This commit is contained in:
Nick O'Leary
2017-01-21 23:46:44 +00:00
parent 0720128bd4
commit e27f5d0460
10 changed files with 210 additions and 50 deletions

View File

@@ -24,12 +24,14 @@
"removed-types": "Removed node types:",
"install": {
"invalid": "Invalid module name",
"installing": "Installing module: __name__",
"installing": "Installing module: __name__, version: __version__",
"installed": "Installed module: __name__",
"install-failed": "Install failed",
"install-failed-long": "Installation of module __name__ failed:",
"install-failed-not-found": "$t(install-failed-long) module not found",
"upgrading": "Upgrading module: __name__ to version: __version__",
"upgraded": "Upgraded module: __name__. Restart Node-RED to use the new version",
"upgrade-failed-not-found": "$t(server.install.install-failed-long) version not found",
"uninstalling": "Uninstalling module: __name__",
"uninstall-failed": "Uninstall failed",
"uninstall-failed-long": "Uninstall of module __name__ failed:",

View File

@@ -76,7 +76,7 @@ module.exports = {
addModule: addModule,
removeModule: registry.removeModule,
installModule: installer.installModule,
uninstallModule: installer.uninstallModule,

View File

@@ -59,33 +59,44 @@ function checkModulePath(folder) {
return moduleName;
}
function checkExistingModule(module) {
if (registry.getModuleInfo(module)) {
// TODO: nls
var err = new Error("Module already loaded");
err.code = "module_already_loaded";
throw err;
function checkExistingModule(module,version) {
var info = registry.getModuleInfo(module);
if (info) {
if (!version || info.version === version) {
var err = new Error("Module already loaded");
err.code = "module_already_loaded";
throw err;
}
return true;
}
return false;
}
function installModule(module) {
function installModule(module,version) {
//TODO: ensure module is 'safe'
return when.promise(function(resolve,reject) {
var installName = module;
var isUpgrade = false;
try {
if (moduleRe.test(module)) {
// Simple module name - assume it can be npm installed
if (version) {
installName += "@"+version;
}
} else if (slashRe.test(module)) {
// A path - check if there's a valid package.json
installName = module;
module = checkModulePath(module);
}
checkExistingModule(module);
isUpgrade = checkExistingModule(module,version);
} catch(err) {
return reject(err);
}
log.info(log._("server.install.installing",{name: module}));
if (!isUpgrade) {
log.info(log._("server.install.installing",{name: module,version: version||"latest"}));
} else {
log.info(log._("server.install.upgrading",{name: module,version: version||"latest"}));
}
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
var child = child_process.execFile(npmCommand,['install','--production',installName],
@@ -94,10 +105,17 @@ function installModule(module) {
},
function(err, stdin, stdout) {
if (err) {
var lookFor404 = new RegExp(" 404 .*"+installName+"$","m");
var e;
var lookFor404 = new RegExp(" 404 .*"+module+"$","m");
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
if (lookFor404.test(stdout)) {
log.warn(log._("server.install.install-failed-not-found",{name:module}));
var e = new Error("Module not found");
e = new Error("Module not found");
e.code = 404;
reject(e);
} else if (isUpgrade && lookForVersionNotFound.test(stdout)) {
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
e = new Error("Module not found");
e.code = 404;
reject(e);
} else {
@@ -108,8 +126,14 @@ function installModule(module) {
reject(new Error(log._("server.install.install-failed")));
}
} else {
log.info(log._("server.install.installed",{name:module}));
resolve(require("./index").addModule(module).then(reportAddedModules));
if (!isUpgrade) {
log.info(log._("server.install.installed",{name:module}));
resolve(require("./index").addModule(module).then(reportAddedModules));
} else {
log.info(log._("server.install.upgraded",{name:module, version:version}));
events.emit("runtime-event",{id:"restart-required",type:"warning",text:"notification.warnings.restartRequired"});
resolve(require("./registry").setModulePendingUpdated(module,version));
}
}
}
);

View File

@@ -82,7 +82,8 @@ function getNode(id) {
function saveNodeList() {
var moduleList = {};
var hadPending = false;
var hasPending = false;
for (var module in moduleConfigs) {
/* istanbul ignore else */
if (moduleConfigs.hasOwnProperty(module)) {
@@ -94,6 +95,15 @@ function saveNodeList() {
local: moduleConfigs[module].local||false,
nodes: {}
};
if (moduleConfigs[module].hasOwnProperty('pending_version')) {
hadPending = true;
if (moduleConfigs[module].pending_version !== moduleConfigs[module].version) {
moduleList[module].pending_version = moduleConfigs[module].pending_version;
hasPending = true;
} else {
delete moduleConfigs[module].pending_version;
}
}
}
var nodes = moduleConfigs[module].nodes;
for(var node in nodes) {
@@ -111,6 +121,9 @@ function saveNodeList() {
}
}
}
if (hadPending && !hasPending) {
events.emit("runtime-event",{id:"restart-required"});
}
if (settings.available()) {
return settings.set("nodes",moduleList);
} else {
@@ -280,6 +293,9 @@ function getNodeList(filter) {
if (nodes.hasOwnProperty(node)) {
var nodeInfo = filterNodeInfo(nodes[node]);
nodeInfo.version = moduleConfigs[module].version;
if (moduleConfigs[module].pending_version) {
nodeInfo.pending_version = moduleConfigs[module].pending_version;
}
if (!filter || filter(nodes[node])) {
list.push(nodeInfo);
}
@@ -539,6 +555,12 @@ function cleanModuleList() {
saveNodeList();
}
}
function setModulePendingUpdated(module,version) {
moduleConfigs[module].pending_version = version;
return saveNodeList().then(function() {
return getModuleInfo(module);
});
}
var registry = module.exports = {
init: init,
@@ -552,6 +574,7 @@ var registry = module.exports = {
enableNodeSet: enableNodeSet,
disableNodeSet: disableNodeSet,
setModulePendingUpdated: setModulePendingUpdated,
removeModule: removeModule,
getNodeInfo: getNodeInfo,