mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Add plugin support to palette manager
This commit is contained in:
parent
eb940d6d57
commit
81937ddc45
@ -91,6 +91,7 @@ module.exports = {
|
|||||||
// Plugins
|
// Plugins
|
||||||
adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler);
|
adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler);
|
||||||
adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler);
|
adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler);
|
||||||
|
adminApp.get(/^\/plugins\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("plugins.read"),plugins.getConfig,apiUtil.errorHandler);
|
||||||
|
|
||||||
adminApp.get("/diagnostics", needsPermission("diagnostics.read"), diagnostics.getReport, apiUtil.errorHandler);
|
adminApp.get("/diagnostics", needsPermission("diagnostics.read"), diagnostics.getReport, apiUtil.errorHandler);
|
||||||
|
|
||||||
|
@ -40,5 +40,31 @@ module.exports = {
|
|||||||
console.log(err.stack);
|
console.log(err.stack);
|
||||||
apiUtils.rejectHandler(req,res,err);
|
apiUtils.rejectHandler(req,res,err);
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
getConfig: function(req, res) {
|
||||||
|
|
||||||
|
let opts = {
|
||||||
|
user: req.user,
|
||||||
|
module: req.params[0],
|
||||||
|
req: apiUtils.getRequestLogObject(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.get("accept") === "application/json") {
|
||||||
|
runtimeAPI.nodes.getNodeInfo(opts.module).then(function(result) {
|
||||||
|
res.send(result);
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||||
|
if (/[^0-9a-z=\-\*]/i.test(opts.lang)) {
|
||||||
|
opts.lang = "en-US";
|
||||||
|
}
|
||||||
|
runtimeAPI.plugins.getPluginConfig(opts).then(function(result) {
|
||||||
|
return res.send(result);
|
||||||
|
}).catch(function(err) {
|
||||||
|
apiUtils.rejectHandler(req,res,err);
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -591,6 +591,8 @@
|
|||||||
},
|
},
|
||||||
"nodeCount": "__label__ Node",
|
"nodeCount": "__label__ Node",
|
||||||
"nodeCount_plural": "__label__ Nodes",
|
"nodeCount_plural": "__label__ Nodes",
|
||||||
|
"pluginCount": "__count__ Plugin",
|
||||||
|
"pluginCount_plural": "__count__ Plugins",
|
||||||
"moduleCount": "__count__ Modul verfügbar",
|
"moduleCount": "__count__ Modul verfügbar",
|
||||||
"moduleCount_plural": "__count__ Module verfügbar",
|
"moduleCount_plural": "__count__ Module verfügbar",
|
||||||
"inuse": "In Gebrauch",
|
"inuse": "In Gebrauch",
|
||||||
|
@ -609,6 +609,8 @@
|
|||||||
},
|
},
|
||||||
"nodeCount": "__label__ node",
|
"nodeCount": "__label__ node",
|
||||||
"nodeCount_plural": "__label__ nodes",
|
"nodeCount_plural": "__label__ nodes",
|
||||||
|
"pluginCount": "__count__ plugin",
|
||||||
|
"pluginCount_plural": "__count__ plugins",
|
||||||
"moduleCount": "__count__ module available",
|
"moduleCount": "__count__ module available",
|
||||||
"moduleCount_plural": "__count__ modules available",
|
"moduleCount_plural": "__count__ modules available",
|
||||||
"inuse": "in use",
|
"inuse": "in use",
|
||||||
|
@ -124,6 +124,8 @@ RED.nodes = (function() {
|
|||||||
},
|
},
|
||||||
removeNodeSet: function(id) {
|
removeNodeSet: function(id) {
|
||||||
var ns = nodeSets[id];
|
var ns = nodeSets[id];
|
||||||
|
if (!ns) return {};
|
||||||
|
|
||||||
for (var j=0;j<ns.types.length;j++) {
|
for (var j=0;j<ns.types.length;j++) {
|
||||||
delete typeToId[ns.types[j]];
|
delete typeToId[ns.types[j]];
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
RED.plugins = (function() {
|
RED.plugins = (function() {
|
||||||
var plugins = {};
|
var plugins = {};
|
||||||
var pluginsByType = {};
|
var pluginsByType = {};
|
||||||
|
var moduleList = {};
|
||||||
|
|
||||||
function registerPlugin(id,definition) {
|
function registerPlugin(id,definition) {
|
||||||
plugins[id] = definition;
|
plugins[id] = definition;
|
||||||
@ -38,9 +39,43 @@ RED.plugins = (function() {
|
|||||||
function getPluginsByType(type) {
|
function getPluginsByType(type) {
|
||||||
return pluginsByType[type] || [];
|
return pluginsByType[type] || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setPluginList(list) {
|
||||||
|
for(let i=0;i<list.length;i++) {
|
||||||
|
let p = list[i];
|
||||||
|
addPlugin(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPlugin(p) {
|
||||||
|
|
||||||
|
moduleList[p.module] = moduleList[p.module] || {
|
||||||
|
name:p.module,
|
||||||
|
version:p.version,
|
||||||
|
local:p.local,
|
||||||
|
sets:{},
|
||||||
|
plugin: true,
|
||||||
|
id: p.id
|
||||||
|
};
|
||||||
|
if (p.pending_version) {
|
||||||
|
moduleList[p.module].pending_version = p.pending_version;
|
||||||
|
}
|
||||||
|
moduleList[p.module].sets[p.name] = p;
|
||||||
|
|
||||||
|
RED.events.emit("registry:plugin-module-added",p.module);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModule(module) {
|
||||||
|
return moduleList[module];
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
registerPlugin: registerPlugin,
|
registerPlugin: registerPlugin,
|
||||||
getPlugin: getPlugin,
|
getPlugin: getPlugin,
|
||||||
getPluginsByType: getPluginsByType
|
getPluginsByType: getPluginsByType,
|
||||||
|
|
||||||
|
setPluginList: setPluginList,
|
||||||
|
addPlugin: addPlugin,
|
||||||
|
getModule: getModule
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -25,6 +25,7 @@ var RED = (function() {
|
|||||||
cache: false,
|
cache: false,
|
||||||
url: 'plugins',
|
url: 'plugins',
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
|
RED.plugins.setPluginList(data);
|
||||||
loader.reportProgress(RED._("event.loadPlugins"), 13)
|
loader.reportProgress(RED._("event.loadPlugins"), 13)
|
||||||
RED.i18n.loadPluginCatalogs(function() {
|
RED.i18n.loadPluginCatalogs(function() {
|
||||||
loadPlugins(function() {
|
loadPlugins(function() {
|
||||||
@ -525,6 +526,41 @@ var RED = (function() {
|
|||||||
RED.view.redrawStatus(node);
|
RED.view.redrawStatus(node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
RED.comms.subscribe("notification/plugin/#",function(topic,msg) {
|
||||||
|
if (topic == "notification/plugin/added") {
|
||||||
|
RED.settings.refreshSettings(function(err, data) {
|
||||||
|
let addedPlugins = [];
|
||||||
|
msg.forEach(function(m) {
|
||||||
|
let id = m.id;
|
||||||
|
RED.plugins.addPlugin(m);
|
||||||
|
|
||||||
|
m.plugins.forEach((p) => {
|
||||||
|
addedPlugins.push(p.id);
|
||||||
|
})
|
||||||
|
|
||||||
|
RED.i18n.loadNodeCatalog(id, function() {
|
||||||
|
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
|
||||||
|
$.ajax({
|
||||||
|
headers: {
|
||||||
|
"Accept":"text/html",
|
||||||
|
"Accept-Language": lang
|
||||||
|
},
|
||||||
|
cache: false,
|
||||||
|
url: 'plugins/'+id,
|
||||||
|
success: function(data) {
|
||||||
|
appendPluginConfig(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (addedPlugins.length) {
|
||||||
|
let pluginList = "<ul><li>"+addedPlugins.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
|
||||||
|
// ToDo: Adapt notification (node -> plugin)
|
||||||
|
RED.notify(RED._("palette.event.nodeAdded", {count:addedPlugins.length})+pluginList,"success");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
RED.comms.subscribe("notification/node/#",function(topic,msg) {
|
RED.comms.subscribe("notification/node/#",function(topic,msg) {
|
||||||
var i,m;
|
var i,m;
|
||||||
var typeList;
|
var typeList;
|
||||||
|
@ -248,6 +248,24 @@ RED.palette.editor = (function() {
|
|||||||
var moduleInfo = nodeEntries[module].info;
|
var moduleInfo = nodeEntries[module].info;
|
||||||
var nodeEntry = nodeEntries[module].elements;
|
var nodeEntry = nodeEntries[module].elements;
|
||||||
if (nodeEntry) {
|
if (nodeEntry) {
|
||||||
|
if (moduleInfo.plugin) {
|
||||||
|
nodeEntry.enableButton.hide();
|
||||||
|
nodeEntry.removeButton.show();
|
||||||
|
|
||||||
|
let pluginCount = 0;
|
||||||
|
|
||||||
|
for (let setName in moduleInfo.sets) {
|
||||||
|
if (moduleInfo.sets.hasOwnProperty(setName)) {
|
||||||
|
let set = moduleInfo.sets[setName];
|
||||||
|
if (set.plugins) {
|
||||||
|
pluginCount += set.plugins.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeEntry.setCount.text(RED._('palette.editor.pluginCount',{count:pluginCount,label:pluginCount}));
|
||||||
|
|
||||||
|
} else {
|
||||||
var activeTypeCount = 0;
|
var activeTypeCount = 0;
|
||||||
var typeCount = 0;
|
var typeCount = 0;
|
||||||
var errorCount = 0;
|
var errorCount = 0;
|
||||||
@ -330,6 +348,7 @@ RED.palette.editor = (function() {
|
|||||||
nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0));
|
nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (moduleInfo.pending_version) {
|
if (moduleInfo.pending_version) {
|
||||||
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
|
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
|
||||||
nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').css('display', 'inline-block');
|
nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').css('display', 'inline-block');
|
||||||
@ -678,6 +697,33 @@ RED.palette.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
RED.events.on("registry:plugin-module-added", function(module) {
|
||||||
|
|
||||||
|
if (!nodeEntries.hasOwnProperty(module)) {
|
||||||
|
nodeEntries[module] = {info:RED.plugins.getModule(module)};
|
||||||
|
var index = [module];
|
||||||
|
for (var s in nodeEntries[module].info.sets) {
|
||||||
|
if (nodeEntries[module].info.sets.hasOwnProperty(s)) {
|
||||||
|
index.push(s);
|
||||||
|
index = index.concat(nodeEntries[module].info.sets[s].types)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodeEntries[module].index = index.join(",").toLowerCase();
|
||||||
|
nodeList.editableList('addItem', nodeEntries[module]);
|
||||||
|
} else {
|
||||||
|
_refreshNodeModule(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i=0;i<filteredList.length;i++) {
|
||||||
|
if (filteredList[i].info.id === module) {
|
||||||
|
var installButton = filteredList[i].elements.installButton;
|
||||||
|
installButton.addClass('disabled');
|
||||||
|
installButton.text(RED._('palette.editor.installed'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var settingsPane;
|
var settingsPane;
|
||||||
@ -804,6 +850,7 @@ RED.palette.editor = (function() {
|
|||||||
errorRow: errorRow,
|
errorRow: errorRow,
|
||||||
errorList: errorList,
|
errorList: errorList,
|
||||||
setCount: setCount,
|
setCount: setCount,
|
||||||
|
setButton: setButton,
|
||||||
container: container,
|
container: container,
|
||||||
shade: shade,
|
shade: shade,
|
||||||
versionSpan: versionSpan,
|
versionSpan: versionSpan,
|
||||||
@ -829,6 +876,7 @@ RED.palette.editor = (function() {
|
|||||||
var setRow = $('<div>',{class:"red-ui-palette-module-set"}).appendTo(contentRow);
|
var setRow = $('<div>',{class:"red-ui-palette-module-set"}).appendTo(contentRow);
|
||||||
var buttonGroup = $('<div>',{class:"red-ui-palette-module-set-button-group"}).appendTo(setRow);
|
var buttonGroup = $('<div>',{class:"red-ui-palette-module-set-button-group"}).appendTo(setRow);
|
||||||
var typeSwatches = {};
|
var typeSwatches = {};
|
||||||
|
if (set.types) {
|
||||||
set.types.forEach(function(t) {
|
set.types.forEach(function(t) {
|
||||||
var typeDiv = $('<div>',{class:"red-ui-palette-module-type"}).appendTo(setRow);
|
var typeDiv = $('<div>',{class:"red-ui-palette-module-type"}).appendTo(setRow);
|
||||||
typeSwatches[t] = $('<span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
|
typeSwatches[t] = $('<span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
|
||||||
@ -850,6 +898,14 @@ RED.palette.editor = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
} else if (set.plugins) {
|
||||||
|
set.plugins.forEach(function(p) {
|
||||||
|
var typeDiv = $('<div>',{class:"red-ui-palette-module-type"}).appendTo(setRow);
|
||||||
|
// typeSwatches[p.id] = $('<span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
|
||||||
|
$('<span><i class="fa fa-puzzle-piece" aria-hidden="true"></i> </span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
|
||||||
|
$('<span>',{class:"red-ui-palette-module-type-node"}).text(p.id).appendTo(typeDiv);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
object.elements.sets[set.name] = {
|
object.elements.sets[set.name] = {
|
||||||
setRow: setRow,
|
setRow: setRow,
|
||||||
@ -1226,7 +1282,55 @@ RED.palette.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}); }
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// dedicated list management for plugins
|
||||||
|
if (entry.plugin) {
|
||||||
|
|
||||||
|
let e = nodeEntries[entry.name];
|
||||||
|
if (e) {
|
||||||
|
nodeList.editableList('removeItem', e);
|
||||||
|
delete nodeEntries[entry.name];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We assume that a plugin that implements onremove
|
||||||
|
// cleans the editor accordingly of its left-overs.
|
||||||
|
let found_onremove = true;
|
||||||
|
|
||||||
|
let keys = Object.keys(entry.sets);
|
||||||
|
keys.forEach((key) => {
|
||||||
|
let set = entry.sets[key];
|
||||||
|
for (let i=0; i<set.plugins?.length; i++) {
|
||||||
|
let plgn = RED.plugins.getPlugin(set.plugins[i].id);
|
||||||
|
if (plgn && plgn.onremove && typeof plgn.onremove === 'function') {
|
||||||
|
plgn.onremove();
|
||||||
|
} else {
|
||||||
|
if (plgn && plgn.onadd && typeof plgn.onadd === 'function') {
|
||||||
|
// if there's no 'onadd', there shouldn't be any left-overs
|
||||||
|
found_onremove = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!found_onremove) {
|
||||||
|
let removeNotify = RED.notify("Removed plugin " + entry.name + ". Please reload the editor to clear left-overs.",{
|
||||||
|
modal: true,
|
||||||
|
fixed: true,
|
||||||
|
type: 'warning',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: "Understood",
|
||||||
|
class:"primary",
|
||||||
|
click: function(e) {
|
||||||
|
removeNotify.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
notification.close();
|
notification.close();
|
||||||
|
@ -319,6 +319,7 @@ module.exports = {
|
|||||||
getPluginsByType: plugins.getPluginsByType,
|
getPluginsByType: plugins.getPluginsByType,
|
||||||
getPluginList: plugins.getPluginList,
|
getPluginList: plugins.getPluginList,
|
||||||
getPluginConfigs: plugins.getPluginConfigs,
|
getPluginConfigs: plugins.getPluginConfigs,
|
||||||
|
getPluginConfig: plugins.getPluginConfig,
|
||||||
exportPluginSettings: plugins.exportPluginSettings,
|
exportPluginSettings: plugins.exportPluginSettings,
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ const child_process = require('child_process');
|
|||||||
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
||||||
let installerEnabled = false;
|
let installerEnabled = false;
|
||||||
|
|
||||||
|
const plugins = require("./plugins");
|
||||||
|
|
||||||
let settings;
|
let settings;
|
||||||
const moduleRe = /^(@[^/@]+?[/])?[^/@]+?$/;
|
const moduleRe = /^(@[^/@]+?[/])?[^/@]+?$/;
|
||||||
const slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/;
|
const slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/;
|
||||||
@ -330,10 +332,18 @@ function reportRemovedModules(removedNodes) {
|
|||||||
//comms.publish("node/removed",removedNodes,false);
|
//comms.publish("node/removed",removedNodes,false);
|
||||||
log.info(log._("server.removed-types"));
|
log.info(log._("server.removed-types"));
|
||||||
for (var j=0;j<removedNodes.length;j++) {
|
for (var j=0;j<removedNodes.length;j++) {
|
||||||
for (var i=0;i<removedNodes[j].types.length;i++) {
|
for (var i=0;i<removedNodes[j].types?.length;i++) {
|
||||||
log.info(" - "+(removedNodes[j].module?removedNodes[j].module+":":"")+removedNodes[j].types[i]);
|
log.info(" - "+(removedNodes[j].module?removedNodes[j].module+":":"")+removedNodes[j].types[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info(log._("server.removed-plugins"));
|
||||||
|
for (let j=0;j<removedNodes.length;j++) {
|
||||||
|
for (var i=0;i<removedNodes[j].plugins?.length;i++) {
|
||||||
|
log.info(" - "+(removedNodes[j].module?removedNodes[j].module+":":"")+removedNodes[j].plugins[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return removedNodes;
|
return removedNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +506,11 @@ function uninstallModule(module) {
|
|||||||
return reject(new Error(log._("server.install.uninstall-failed",{name:module})));
|
return reject(new Error(log._("server.install.uninstall-failed",{name:module})));
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = registry.removeModule(module);
|
// need to remove the plugins first,
|
||||||
|
// as registry data necessary to perform this operation
|
||||||
|
var list = plugins.removeModule(module);
|
||||||
|
list = list.concat(registry.removeModule(module));
|
||||||
|
|
||||||
log.info(log._("server.install.uninstalling",{name:module}));
|
log.info(log._("server.install.uninstalling",{name:module}));
|
||||||
|
|
||||||
let triggerPayload = {
|
let triggerPayload = {
|
||||||
|
@ -39,6 +39,8 @@ function registerPlugin(nodeSetId,id,definition) {
|
|||||||
pluginSettings[id] = definition.settings;
|
pluginSettings[id] = definition.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset the cache when a new plugin is incoming!
|
||||||
|
pluginConfigCache = {};
|
||||||
|
|
||||||
if (definition.onadd && typeof definition.onadd === 'function') {
|
if (definition.onadd && typeof definition.onadd === 'function') {
|
||||||
definition.onadd();
|
definition.onadd();
|
||||||
@ -55,29 +57,47 @@ function getPluginsByType(type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getPluginConfigs(lang) {
|
function getPluginConfigs(lang) {
|
||||||
|
// we're not re-using getPluginConfig() here,
|
||||||
|
// to avoid calling registry.getModuleList() multiple times!
|
||||||
|
|
||||||
if (!pluginConfigCache[lang]) {
|
if (!pluginConfigCache[lang]) {
|
||||||
var result = "";
|
var result = "";
|
||||||
var script = "";
|
|
||||||
var moduleConfigs = registry.getModuleList();
|
var moduleConfigs = registry.getModuleList();
|
||||||
for (var module in moduleConfigs) {
|
for (var module in moduleConfigs) {
|
||||||
/* istanbul ignore else */
|
/* istanbul ignore else */
|
||||||
if (moduleConfigs.hasOwnProperty(module)) {
|
if (moduleConfigs.hasOwnProperty(module)) {
|
||||||
var plugins = moduleConfigs[module].plugins;
|
result += get_config_of_plugins(moduleConfigs[module].plugins);
|
||||||
for (var plugin in plugins) {
|
|
||||||
if (plugins.hasOwnProperty(plugin)) {
|
|
||||||
var config = plugins[plugin];
|
|
||||||
if (config.enabled && !config.err && config.config) {
|
|
||||||
result += "\n<!-- --- [red-plugin:"+config.id+"] --- -->\n";
|
|
||||||
result += config.config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pluginConfigCache[lang] = result;
|
pluginConfigCache[lang] = result;
|
||||||
}
|
}
|
||||||
return pluginConfigCache[lang];
|
return pluginConfigCache[lang];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPluginConfig(id, lang) {
|
||||||
|
let result = '';
|
||||||
|
let moduleConfigs = registry.getModuleList();
|
||||||
|
if (moduleConfigs.hasOwnProperty(id)) {
|
||||||
|
result = get_config_of_plugins(moduleConfigs[id].plugins);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to avoid code duplication
|
||||||
|
function get_config_of_plugins(plugins) {
|
||||||
|
let result = '';
|
||||||
|
for (let plugin in plugins) {
|
||||||
|
if (plugins.hasOwnProperty(plugin)) {
|
||||||
|
let config = plugins[plugin];
|
||||||
|
if (config.enabled && !config.err && config.config) {
|
||||||
|
result += "\n<!-- --- [red-plugin:"+config.id+"] --- -->\n";
|
||||||
|
result += config.config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function getPluginList() {
|
function getPluginList() {
|
||||||
var list = [];
|
var list = [];
|
||||||
var moduleConfigs = registry.getModuleList();
|
var moduleConfigs = registry.getModuleList();
|
||||||
@ -142,12 +162,51 @@ function exportPluginSettings(safeSettings) {
|
|||||||
return safeSettings;
|
return safeSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeModule(moduleId) {
|
||||||
|
|
||||||
|
// clean the (plugin) registry when a module is removed / uninstalled
|
||||||
|
|
||||||
|
let pluginList = [];
|
||||||
|
let module = registry.getModule(moduleId);
|
||||||
|
let keys = Object.keys(module.plugins ?? {});
|
||||||
|
keys.forEach( key => {
|
||||||
|
let _plugins = module.plugins[key].plugins ?? [];
|
||||||
|
_plugins.forEach( plugin => {
|
||||||
|
let id = plugin.id;
|
||||||
|
|
||||||
|
if (plugin.onremove && typeof plugin.onremove === 'function') {
|
||||||
|
plugin.onremove();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pluginToId[id];
|
||||||
|
delete plugins[id];
|
||||||
|
delete pluginSettings[id];
|
||||||
|
pluginConfigCache = {};
|
||||||
|
|
||||||
|
let psbtype = pluginsByType[plugin.type] ?? [];
|
||||||
|
for (let i=psbtype.length; i>0; i--) {
|
||||||
|
let pbt = psbtype[i-1];
|
||||||
|
if (pbt.id == id) {
|
||||||
|
psbtype.splice(i-1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
pluginList.push(registry.filterNodeInfo(module.plugins[key]));
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return pluginList;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init,
|
init,
|
||||||
registerPlugin,
|
registerPlugin,
|
||||||
getPlugin,
|
getPlugin,
|
||||||
getPluginsByType,
|
getPluginsByType,
|
||||||
getPluginConfigs,
|
getPluginConfigs,
|
||||||
|
getPluginConfig,
|
||||||
getPluginList,
|
getPluginList,
|
||||||
exportPluginSettings
|
exportPluginSettings,
|
||||||
|
removeModule
|
||||||
}
|
}
|
||||||
|
@ -386,7 +386,8 @@ function getModuleInfo(module) {
|
|||||||
local: moduleConfigs[module].local,
|
local: moduleConfigs[module].local,
|
||||||
user: moduleConfigs[module].user,
|
user: moduleConfigs[module].user,
|
||||||
path: moduleConfigs[module].path,
|
path: moduleConfigs[module].path,
|
||||||
nodes: []
|
nodes: [],
|
||||||
|
plugins: []
|
||||||
};
|
};
|
||||||
if (moduleConfigs[module].dependencies) {
|
if (moduleConfigs[module].dependencies) {
|
||||||
m.dependencies = moduleConfigs[module].dependencies;
|
m.dependencies = moduleConfigs[module].dependencies;
|
||||||
@ -399,6 +400,14 @@ function getModuleInfo(module) {
|
|||||||
nodeInfo.version = m.version;
|
nodeInfo.version = m.version;
|
||||||
m.nodes.push(nodeInfo);
|
m.nodes.push(nodeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let plugins = Object.values(moduleConfigs[module].plugins);
|
||||||
|
plugins.forEach((plugin) => {
|
||||||
|
let nodeInfo = filterNodeInfo(plugin);
|
||||||
|
nodeInfo.version = m.version;
|
||||||
|
m.plugins.push(nodeInfo);
|
||||||
|
});
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -65,6 +65,25 @@ var api = module.exports = {
|
|||||||
runtime.log.audit({event: "plugins.configs.get"}, opts.req);
|
runtime.log.audit({event: "plugins.configs.get"}, opts.req);
|
||||||
return runtime.plugins.getPluginConfigs(opts.lang);
|
return runtime.plugins.getPluginConfigs(opts.lang);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the editor content for one registered plugin
|
||||||
|
* @param {Object} opts
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {User} opts.user - the user calling the api
|
||||||
|
* @param {Object} opts.req - the request to log (optional)
|
||||||
|
* @return {Promise<NodeInfo>} - the plugin information
|
||||||
|
* @memberof @node-red/runtime_plugins
|
||||||
|
*/
|
||||||
|
getPluginConfig: async function(opts) {
|
||||||
|
if (/[^0-9a-z=\-\*]/i.test(opts.lang)) {
|
||||||
|
throw new Error("Invalid language: "+opts.lang)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runtime.log.audit({event: "plugins.configs.get"}, opts.req);
|
||||||
|
return runtime.plugins.getPluginConfig(opts.module, opts.lang);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all registered module message catalogs
|
* Gets all registered module message catalogs
|
||||||
* @param {Object} opts
|
* @param {Object} opts
|
||||||
|
@ -172,9 +172,13 @@ function installModule(module,version,url) {
|
|||||||
return registry.installModule(module,version,url).then(function(info) {
|
return registry.installModule(module,version,url).then(function(info) {
|
||||||
if (info.pending_version) {
|
if (info.pending_version) {
|
||||||
events.emit("runtime-event",{id:"node/upgraded",retain:false,payload:{module:info.name,version:info.pending_version}});
|
events.emit("runtime-event",{id:"node/upgraded",retain:false,payload:{module:info.name,version:info.pending_version}});
|
||||||
|
} else {
|
||||||
|
if (!info.nodes.length && info.plugins.length) {
|
||||||
|
events.emit("runtime-event",{id:"plugin/added",retain:false,payload:info.plugins});
|
||||||
} else {
|
} else {
|
||||||
events.emit("runtime-event",{id:"node/added",retain:false,payload:info.nodes});
|
events.emit("runtime-event",{id:"node/added",retain:false,payload:info.nodes});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return info;
|
return info;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,6 @@ module.exports = {
|
|||||||
getPluginsByType: registry.getPluginsByType,
|
getPluginsByType: registry.getPluginsByType,
|
||||||
getPluginList: registry.getPluginList,
|
getPluginList: registry.getPluginList,
|
||||||
getPluginConfigs: registry.getPluginConfigs,
|
getPluginConfigs: registry.getPluginConfigs,
|
||||||
|
getPluginConfig: registry.getPluginConfig,
|
||||||
exportPluginSettings: registry.exportPluginSettings
|
exportPluginSettings: registry.exportPluginSettings
|
||||||
}
|
}
|
@ -25,6 +25,7 @@
|
|||||||
"removing-modules": "Removing modules from config",
|
"removing-modules": "Removing modules from config",
|
||||||
"added-types": "Added node types:",
|
"added-types": "Added node types:",
|
||||||
"removed-types": "Removed node types:",
|
"removed-types": "Removed node types:",
|
||||||
|
"removed-plugins": "Removed plugins:",
|
||||||
"install": {
|
"install": {
|
||||||
"invalid": "Invalid module name",
|
"invalid": "Invalid module name",
|
||||||
"installing": "Installing module: __name__, version: __version__",
|
"installing": "Installing module: __name__, version: __version__",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user