Rework Function node module integration

This commit is contained in:
Nick O'Leary
2021-02-12 18:14:13 +00:00
parent 4a1d66f210
commit 9c09ee3b71
20 changed files with 800 additions and 1384 deletions

View File

@@ -142,6 +142,7 @@
"nodeActionDisabled": "node actions disabled",
"nodeActionDisabledSubflow": "node actions disabled within subflow",
"missing-types": "<p>Flows stopped due to missing node types.</p>",
"missing-modules": "<p>Flows stopped due to missing modules.</p>",
"safe-mode":"<p>Flows stopped in safe mode.</p><p>You can modify your flows and deploy the changes to restart.</p>",
"restartRequired": "Node-RED must be restarted to enable upgraded modules",
"credentials_load_failed": "<p>Flows stopped as the credentials could not be decrypted.</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p>",

View File

@@ -248,6 +248,7 @@ var RED = (function() {
id: notificationId
}
if (notificationId === "runtime-state") {
RED.events.emit("runtime-state",msg);
if (msg.error === "safe-mode") {
options.buttons = [
{
@@ -280,6 +281,16 @@ var RED = (function() {
}
]
}
} else if (msg.error === "missing-modules") {
text+="<ul><li>"+msg.modules.map(function(m) { return RED.utils.sanitize(m.module)+(m.error?(" - <small>"+RED.utils.sanitize(""+m.error)+"</small>"):"")}).join("</li><li>")+"</li></ul>";
options.buttons = [
{
text: RED._("common.label.close"),
click: function() {
persistentNotifications[notificationId].hideNotification();
}
}
]
} else if (msg.error === "credentials_load_failed") {
if (RED.settings.theme("projects.enabled",false)) {
// projects enabled
@@ -370,6 +381,9 @@ var RED = (function() {
} else if (persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId].close();
delete persistentNotifications[notificationId];
if (notificationId === 'runtime-state') {
RED.events.emit("runtime-state",msg);
}
}
});
RED.comms.subscribe("status/#",function(topic,msg) {

View File

@@ -509,8 +509,8 @@ RED.tabs = (function() {
li.attr('id',"red-ui-tab-"+(tab.id.replace(".","-")));
li.data("tabId",tab.id);
if (options.maximumTabWidth) {
li.css("maxWidth",options.maximumTabWidth+"px");
if (options.maximumTabWidth || tab.maximumTabWidth) {
li.css("maxWidth",(options.maximumTabWidth || tab.maximumTabWidth) +"px");
}
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
if (tab.icon) {

View File

@@ -331,7 +331,7 @@ RED.palette.editor = (function() {
if (v.modules) {
var a = false;
v.modules = v.modules.filter(function(m) {
if (checkModuleAllowed(m.id,m.version,installAllowList,installDenyList)) {
if (RED.utils.checkModuleAllowed(m.id,m.version,installAllowList,installDenyList)) {
loadedIndex[m.id] = m;
m.index = [m.id];
if (m.keywords) {
@@ -445,68 +445,6 @@ RED.palette.editor = (function() {
var installAllowList = ['*'];
var installDenyList = [];
function parseModuleList(list) {
list = list || ["*"];
return list.map(function(rule) {
var m = /^(.+?)(?:@(.*))?$/.exec(rule);
var wildcardPos = m[1].indexOf("*");
wildcardPos = wildcardPos===-1?Infinity:wildcardPos;
return {
module: new RegExp("^"+m[1].replace(/\*/g,".*")+"$"),
version: m[2],
wildcardPos: wildcardPos
}
})
}
function checkAgainstList(module,version,list) {
for (var i=0;i<list.length;i++) {
var rule = list[i];
if (rule.module.test(module)) {
// Without a full semver library in the editor,
// we skip the version check.
// Not ideal - but will get caught in the runtime
// if the user tries to install.
return rule;
}
}
}
function checkModuleAllowed(module,version,allowList,denyList) {
if (!allowList && !denyList) {
// Default to allow
return true;
}
if (allowList.length === 0 && denyList.length === 0) {
return true;
}
var allowedRule = checkAgainstList(module,version,allowList);
var deniedRule = checkAgainstList(module,version,denyList);
// console.log("A",allowedRule)
// console.log("D",deniedRule)
if (allowedRule && !deniedRule) {
return true;
}
if (!allowedRule && deniedRule) {
return false;
}
if (!allowedRule && !deniedRule) {
return true;
}
if (allowedRule.wildcardPos !== deniedRule.wildcardPos) {
return allowedRule.wildcardPos > deniedRule.wildcardPos
} else {
// First wildcard in same position.
// Go with the longer matching rule. This isn't going to be 100%
// right, but we are deep into edge cases at this point.
return allowedRule.module.toString().length > deniedRule.module.toString().length
}
return false;
}
function init() {
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
return;
@@ -517,8 +455,8 @@ RED.palette.editor = (function() {
installAllowList = settingsAllowList;
installDenyList = settingsDenyList
}
installAllowList = parseModuleList(installAllowList);
installDenyList = parseModuleList(installDenyList);
installAllowList = RED.utils.parseModuleList(installAllowList);
installDenyList = RED.utils.parseModuleList(installDenyList);
createSettingsPane();

View File

@@ -1122,6 +1122,67 @@ RED.utils = (function() {
return '#'+'000000'.slice(0, 6-s.length)+s;
}
function parseModuleList(list) {
list = list || ["*"];
return list.map(function(rule) {
var m = /^(.+?)(?:@(.*))?$/.exec(rule);
var wildcardPos = m[1].indexOf("*");
wildcardPos = wildcardPos===-1?Infinity:wildcardPos;
return {
module: new RegExp("^"+m[1].replace(/\*/g,".*")+"$"),
version: m[2],
wildcardPos: wildcardPos
}
})
}
function checkAgainstList(module,version,list) {
for (var i=0;i<list.length;i++) {
var rule = list[i];
if (rule.module.test(module)) {
// Without a full semver library in the editor,
// we skip the version check.
// Not ideal - but will get caught in the runtime
// if the user tries to install.
return rule;
}
}
}
function checkModuleAllowed(module,version,allowList,denyList) {
if (!allowList && !denyList) {
// Default to allow
return true;
}
if (allowList.length === 0 && denyList.length === 0) {
return true;
}
var allowedRule = checkAgainstList(module,version,allowList);
var deniedRule = checkAgainstList(module,version,denyList);
// console.log("A",allowedRule)
// console.log("D",deniedRule)
if (allowedRule && !deniedRule) {
return true;
}
if (!allowedRule && deniedRule) {
return false;
}
if (!allowedRule && !deniedRule) {
return true;
}
if (allowedRule.wildcardPos !== deniedRule.wildcardPos) {
return allowedRule.wildcardPos > deniedRule.wildcardPos
} else {
// First wildcard in same position.
// Go with the longer matching rule. This isn't going to be 100%
// right, but we are deep into edge cases at this point.
return allowedRule.module.toString().length > deniedRule.module.toString().length
}
return false;
}
return {
createObjectElement: buildMessageElement,
getMessageProperty: getMessageProperty,
@@ -1141,6 +1202,8 @@ RED.utils = (function() {
sanitize: sanitize,
renderMarkdown: renderMarkdown,
createNodeIcon: createNodeIcon,
getDarkerColor: getDarkerColor
getDarkerColor: getDarkerColor,
parseModuleList: parseModuleList,
checkModuleAllowed: checkModuleAllowed
}
})();

View File

@@ -143,6 +143,13 @@
background-size: contain
}
.red-ui-font-code {
font-family: $monospace-font;
font-size: $primary-font-size;
color: $info-text-code-color;
white-space: nowrap;
}
code {
font-family: $monospace-font;
font-size: $primary-font-size;