Merge pull request #2785 from node-red/library-plugins

Library plugins
This commit is contained in:
Nick O'Leary
2021-02-25 16:05:23 +00:00
committed by GitHub
22 changed files with 833 additions and 180 deletions

View File

@@ -0,0 +1,22 @@
<script type="text/javascript">
RED.plugins.registerPlugin("node-red-library-filestore", {
type: "node-red-library-source",
name: "Local File-System Library",
icon: "font-awesome/fa-hdd-o",
defaults: {
path: { value: ""},
// secret: { type: "password" }
}
})
RED.plugins.registerPlugin("node-red-library-dbstore", {
type: "node-red-library-source",
name: "Database Library",
icon: "font-awesome/fa-database",
defaults: {
connection: { value: ""}
}
})
</script>

View File

@@ -0,0 +1,37 @@
module.exports = function(RED) {
const PLUGIN_TYPE_ID = "node-red-library-filestore";
class FileStorePlugin {
constructor(config) {
this.type = PLUGIN_TYPE_ID;
this.id = config.id;
this.label = config.label;
this.config = config.config;
this.icon = config.icon;
console.log("FileStorePlugin",config)
}
async init() {
console.log("FileStorePlugin.init")
}
async getEntry(type,path) {
console.log("FileStorePlugin.getLibraryEntry",type,path)
return []
}
async saveEntry(type,path,meta,body) {
console.log("FileStorePlugin.saveLibraryEntry",type,path)
}
}
RED.plugins.registerPlugin(PLUGIN_TYPE_ID, {
type: "node-red-library-source",
class: FileStorePlugin,
defaults: {
"path": { value: "" },
// "secret": { type: "password" }
}
})
}

View File

@@ -0,0 +1,8 @@
{
"label": {
"path": "Path"
},
"desc": {
"path":"The local file-system path to the library"
}
}

View File

@@ -6,7 +6,8 @@
"plugins": {
"test": "test.js",
"test-editor-plugin": "test-editor-plugin.html",
"test-runtime-plugin": "test-runtime-plugin.js"
"test-runtime-plugin": "test-runtime-plugin.js",
"library-filestore": "library-filestore.js"
}
}
}

View File

@@ -44,6 +44,11 @@ describe("runtime-api/settings", function() {
paletteCategories :["red","blue","green"],
exportNodeSettings: (obj) => {
obj.testNodeSetting = "helloWorld";
},
},
plugins: {
exportPluginSettings: (obj) => {
obj.testPluginSettings = "helloPluginWorld";
}
},
nodes: {
@@ -51,13 +56,16 @@ describe("runtime-api/settings", function() {
installerEnabled: () => false,
getCredentialKeyType: () => "test-key-type"
},
library: {getLibraries: () => ["lib1"] },
storage: {}
})
return settings.getRuntimeSettings({}).then(result => {
result.should.have.property("httpNodeRoot","testHttpNodeRoot");
result.should.have.property("version","testVersion");
result.should.have.property("paletteCategories",["red","blue","green"]);
result.should.have.property("libraries",["lib1"]);
result.should.have.property("testNodeSetting","helloWorld");
result.should.have.property("testPluginSettings","helloPluginWorld");
result.should.not.have.property("foo",123);
result.should.have.property("flowEncryptionType","test-key-type");
result.should.not.have.property("user");
@@ -75,6 +83,11 @@ describe("runtime-api/settings", function() {
paletteCategories :["red","blue","green"],
exportNodeSettings: (obj) => {
obj.testNodeSetting = "helloWorld";
},
},
plugins: {
exportPluginSettings: (obj) => {
obj.testPluginSettings = "helloPluginWorld";
}
},
nodes: {
@@ -82,6 +95,7 @@ describe("runtime-api/settings", function() {
installerEnabled: () => false,
getCredentialKeyType: () => "test-key-type"
},
library: {getLibraries: () => { ["lib1"]} },
storage: {}
})
return settings.getRuntimeSettings({
@@ -111,6 +125,11 @@ describe("runtime-api/settings", function() {
paletteCategories :["red","blue","green"],
exportNodeSettings: (obj) => {
obj.testNodeSetting = "helloWorld";
},
},
plugins: {
exportPluginSettings: (obj) => {
obj.testPluginSettings = "helloPluginWorld";
}
},
nodes: {
@@ -118,6 +137,7 @@ describe("runtime-api/settings", function() {
installerEnabled: () => false,
getCredentialKeyType: () => "test-key-type"
},
library: {getLibraries: () => { ["lib1"]} },
storage: {
projects: {
getActiveProject: () => 'test-active-project',
@@ -162,6 +182,11 @@ describe("runtime-api/settings", function() {
paletteCategories :["red","blue","green"],
exportNodeSettings: (obj) => {
obj.testNodeSetting = "helloWorld";
},
},
plugins: {
exportPluginSettings: (obj) => {
obj.testPluginSettings = "helloPluginWorld";
}
},
nodes: {
@@ -169,6 +194,7 @@ describe("runtime-api/settings", function() {
installerEnabled: () => false,
getCredentialKeyType: () => "test-key-type"
},
library: {getLibraries: () => { ["lib1"]} },
storage: {
projects: {
getActiveProject: () => 'test-active-project',
@@ -203,6 +229,11 @@ describe("runtime-api/settings", function() {
paletteCategories :["red","blue","green"],
exportNodeSettings: (obj) => {
obj.testNodeSetting = "helloWorld";
},
},
plugins: {
exportPluginSettings: (obj) => {
obj.testPluginSettings = "helloPluginWorld";
}
},
nodes: {
@@ -210,6 +241,7 @@ describe("runtime-api/settings", function() {
installerEnabled: () => false,
getCredentialKeyType: () => "test-key-type"
},
library: {getLibraries: () => { ["lib1"]} },
storage: {
projects: {
flowFileExists: () => true,
@@ -248,6 +280,11 @@ describe("runtime-api/settings", function() {
paletteCategories :["red","blue","green"],
exportNodeSettings: (obj) => {
obj.testNodeSetting = "helloWorld";
},
},
plugins: {
exportPluginSettings: (obj) => {
obj.testPluginSettings = "helloPluginWorld";
}
},
nodes: {
@@ -255,6 +292,7 @@ describe("runtime-api/settings", function() {
installerEnabled: () => false,
getCredentialKeyType: () => "test-key-type"
},
library: {getLibraries: () => { ["lib1"]} },
storage: {
projects: {
flowFileExists: () => false,

View File

@@ -14,13 +14,14 @@
* limitations under the License.
**/
var should = require("should");
var sinon = require("sinon");
const should = require("should");
const sinon = require("sinon");
var NR_TEST_UTILS = require("nr-test-utils");
var library = NR_TEST_UTILS.require("@node-red/runtime/lib/library/index")
var localLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/local")
var examplesLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/examples")
const NR_TEST_UTILS = require("nr-test-utils");
const library = NR_TEST_UTILS.require("@node-red/runtime/lib/library/index")
const localLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/local")
const examplesLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/examples")
const events = NR_TEST_UTILS.require("@node-red/util/lib/events")
var mockLog = {
log: sinon.stub(),
@@ -72,6 +73,59 @@ describe("runtime/library", function() {
// should(()=>{library.register("unknown","/abc")} ).throw();
// })
})
describe("getLibraries", function() {
before(function() {
library.init({});
});
it('returns the default and examples libraries', function() {
const libs = library.getLibraries();
libs.should.have.length(2);
libs[0].should.have.property('id', 'local');
libs[0].should.have.property('label','editor:library.types.local');
libs[0].should.have.property("user", false);
libs[0].should.have.property('icon', 'font-awesome/fa-hdd-o');
libs[1].should.have.property('id', 'examples');
libs[1].should.have.property('label','editor:library.types.examples');
libs[1].should.have.property("user", false);
libs[1].should.have.property('icon', 'font-awesome/fa-life-ring');
libs[1].should.have.property('readOnly', true);
libs[1].should.have.property('types', ['flows']);
});
it('returns the libraries from settings', function() {
library.init({
plugins: {
getPlugin: id => { return {
id: "test-library-plugin",
type: "node-red-library-source",
class: function() {}
}
}
},
settings: {
editorTheme: {
library: {
sources: [
{id: "test-plugin-id", type:"test-library-plugin"}
]
}
}
}
});
let libs = library.getLibraries();
libs.should.have.length(2);
events.emit("registry:plugin-added","test-library-plugin" )
libs = library.getLibraries();
libs.should.have.length(3);
libs[2].should.have.property('id', 'test-plugin-id');
libs[2].should.have.property("user", false);
});
})
describe("getEntry", function() {
before(function() {
library.init({});
@@ -102,7 +156,7 @@ describe("runtime/library", function() {
});
it ('returns a flow example entry', function(done) {
library.getEntry("_examples_","flows","/test-module/abc").then(function(result) {
library.getEntry("examples","flows","/test-module/abc").then(function(result) {
result.should.have.property("library","_examples_")
result.should.have.property("path","/test-module/abc")
done();