Deprecate getAllFlows/getFlow/saveFlow storage functions

They were specialised versions of get/saveLibraryEntry that
complicated the interface.

This change removes them from localfilesystem, but the top
level module checks for their existence and uses them if
they are there - for backwards compatibility.
This commit is contained in:
Nick O'Leary 2015-04-03 23:05:56 +01:00
parent e543cc0fed
commit b96ea36b70
4 changed files with 181 additions and 132 deletions

View File

@ -92,21 +92,7 @@ var storageModuleInterface = {
},
/* Library Functions */
getAllFlows: function() {
return storageModule.getAllFlows();
},
getFlow: function(fn) {
if (is_malicious(fn)) {
return when.reject(new Error('forbidden flow name'));
}
return storageModule.getFlow(fn);
},
saveFlow: function(fn, data) {
if (is_malicious(fn)) {
return when.reject(new Error('forbidden flow name'));
}
return storageModule.saveFlow(fn, data);
},
getLibraryEntry: function(type, path) {
if (is_malicious(path)) {
return when.reject(new Error('forbidden flow name'));
@ -118,7 +104,78 @@ var storageModuleInterface = {
return when.reject(new Error('forbidden flow name'));
}
return storageModule.saveLibraryEntry(type, path, meta, body);
},
/* Deprecated functions */
getAllFlows: function() {
if (storageModule.hasOwnProperty("getAllFlows")) {
return storageModule.getAllFlows();
} else {
return listFlows("/");
}
},
getFlow: function(fn) {
if (is_malicious(fn)) {
return when.reject(new Error('forbidden flow name'));
}
if (storageModule.hasOwnProperty("getFlow")) {
return storageModule.getFlow(fn);
} else {
return storageModule.getLibraryEntry("flows",fn);
}
},
saveFlow: function(fn, data) {
if (is_malicious(fn)) {
return when.reject(new Error('forbidden flow name'));
}
if (storageModule.hasOwnProperty("saveFlow")) {
return storageModule.saveFlow(fn, data);
} else {
return storageModule.saveLibraryEntry("flows",fn,{},data);
}
}
/* End deprecated functions */
}
function listFlows(path) {
return storageModule.getLibraryEntry("flows",path).then(function(res) {
return when.promise(function(resolve) {
var promises = [];
res.forEach(function(r) {
if (typeof r === "string") {
promises.push(listFlows(path+r));
} else {
promises.push(when.resolve(r));
}
});
var i=0;
when.settle(promises).then(function(res2) {
var result = {};
res2.forEach(function(r) {
// TODO: name||fn
if (r.value.fn) {
var name = r.value.name;
if (!name) {
name = r.value.fn.split(".")[0];
}
result.f = result.f || [];
result.f.push(name);
} else {
result.d = result.d || {};
result.d[res[i]] = r.value;
//console.log(">",r.value);
}
i++;
});
resolve(result);
});
});
});
}
module.exports = storageModuleInterface;

View File

@ -37,27 +37,6 @@ var libDir;
var libFlowsDir;
var globalSettingsFile;
function listFiles(dir) {
var dirs = {};
var files = [];
var dirCount = 0;
return nodeFn.call(fs.readdir, dir).then(function (contents) {
contents.sort().forEach(function(fn) {
var stats = fs.lstatSync(dir+"/"+fn);
if (stats.isDirectory()) {
dirCount += 1;
dirs[fn] = listFiles(dir+"/"+fn)
} else {
files.push(fn.split(".")[0]);
}
})
var result = {};
if (dirCount > 0) { result.d = keys.all(dirs); }
if (files.length > 0) { result.f = when.resolve(files); }
return keys.all(result);
})
}
function getFileMeta(root,path) {
var fn = fspath.join(root,path);
var fd = fs.openSync(fn,"r");
@ -312,30 +291,6 @@ var localfilesystem = {
return writeFile(sessionsFile,JSON.stringify(sessions));
},
getAllFlows: function() {
return listFiles(libFlowsDir);
},
getFlow: function(fn) {
var defer = when.defer();
var file = fspath.join(libFlowsDir,fn+".json");
fs.exists(file, function(exists) {
if (exists) {
defer.resolve(nodeFn.call(fs.readFile,file,'utf8'));
} else {
defer.reject();
}
});
return defer.promise;
},
saveFlow: function(fn,data) {
var file = fspath.join(libFlowsDir,fn+".json");
return promiseDir(fspath.dirname(file)).then(function () {
return writeFile(file,data);
});
},
getLibraryEntry: function(type,path) {
var root = fspath.join(libDir,type);
var rootPath = fspath.join(libDir,type,path);
@ -366,6 +321,15 @@ var localfilesystem = {
});
return dirs.concat(files);
});
}).otherwise(function(err) {
if (type === "flows" && !/\.json$/.test(path)) {
return localfilesystem.getLibraryEntry(type,path+".json")
.otherwise(function(e) {
throw err;
});
} else {
throw err;
}
});
});
},

View File

@ -1,5 +1,5 @@
/**
* Copyright 2014 IBM Corp.
* Copyright 2014, 2015 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var when = require("when");
var should = require("should");
var storage = require("../../../red/storage/index");
@ -139,6 +140,81 @@ describe("red/storage/index", function() {
calledFlagGetAllFlows.should.be.true;
});
describe('respects deprecated flow library functions', function() {
var savePath;
var saveContent;
var saveMeta;
var saveType;
var interfaceCheckerModule = {
init : function (settings) {
settings.should.be.an.Object;
},
getLibraryEntry : function(type, path) {
if (type === "flows") {
if (path == "/") {
return when.resolve(["a",{fn:"test.json"}]);
} else if (path == "/a") {
return when.resolve([{fn:"test2.json"}]);
} else if (path == "/a/test2.json") {
return when.resolve("test content");
}
}
},
saveLibraryEntry : function(type, path, meta, body) {
saveType = type;
savePath = path;
saveContent = body;
saveMeta = meta;
return when.resolve();
}
};
var moduleToLoad = {
storageModule : interfaceCheckerModule
};
before(function() {
storage.init(moduleToLoad);
});
it('getAllFlows',function(done) {
storage.getAllFlows().then(function (res) {
try {
res.should.eql({ d: { a: { f: ['test2'] } }, f: [ 'test' ] });
done();
} catch(err) {
done(err);
}
});
});
it('getFlow',function(done) {
storage.getFlow("/a/test2.json").then(function(res) {
try {
res.should.eql("test content");
done();
} catch(err) {
done(err);
}
});
});
it ('saveFlow', function (done) {
storage.saveFlow("/a/test2.json","new content").then(function(res) {
try {
savePath.should.eql("/a/test2.json");
saveContent.should.eql("new content");
saveMeta.should.eql({});
saveType.should.eql("flows");
done();
} catch(err) {
done(err);
}
});
});
});
describe('handles missing settings/sessions interface', function() {
before(function() {
var interfaceCheckerModule = {

View File

@ -437,72 +437,6 @@ describe('LocalFileSystem', function() {
});
it('should return an empty list of library flows',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
localfilesystem.getAllFlows().then(function(flows) {
flows.should.eql({});
done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
});
it('should return a valid list of library flows',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
var flowLib = path.join(userDir,"lib","flows");
fs.closeSync(fs.openSync(path.join(flowLib,"A.json"),"w"));
fs.closeSync(fs.openSync(path.join(flowLib,"B.json"),"w"));
fs.mkdirSync(path.join(flowLib,"C"));
fs.closeSync(fs.openSync(path.join(flowLib,"C","D.json"),"w"));
var testFlowsList = {"d":{"C":{"f":["D"]}},"f":["A","B"]};
localfilesystem.getAllFlows().then(function(flows) {
flows.should.eql(testFlowsList);
done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
});
it('should fail a non-existent flow', function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
localfilesystem.getFlow("a/b/c.json").then(function(flow) {
should.fail(flow,"No flow","Flow found");
}).otherwise(function(err) {
// err should be null, so this will pass
done(err);
});
}).otherwise(function(err) {
done(err);
});
});
it('should return a flow',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
var testflowString = JSON.stringify(testFlow);
localfilesystem.saveFlow("a/b/c/d.json",testflowString).then(function() {
localfilesystem.getFlow("a/b/c/d.json").then(function(flow) {
flow.should.eql(testflowString);
done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
});
it('should return an empty list of library objects',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
localfilesystem.getLibraryEntry('object','').then(function(flows) {
@ -529,14 +463,19 @@ describe('LocalFileSystem', function() {
});
});
function createObjectLibrary() {
var objLib = path.join(userDir,"lib","object");
fs.mkdirSync(objLib);
function createObjectLibrary(type) {
type = type ||"object";
var objLib = path.join(userDir,"lib",type);
try {
fs.mkdirSync(objLib);
} catch(err) {
}
fs.mkdirSync(path.join(objLib,"A"));
fs.mkdirSync(path.join(objLib,"B"));
fs.mkdirSync(path.join(objLib,"B","C"));
fs.writeFileSync(path.join(objLib,"file1.js"),"// abc: def\n// not a metaline \n\n Hi",'utf8');
fs.writeFileSync(path.join(objLib,"B","file2.js"),"// ghi: jkl\n// not a metaline \n\n Hi",'utf8');
fs.writeFileSync(path.join(objLib,"B","flow.json"),"Hi",'utf8');
}
it('should return a directory listing of library objects',function(done) {
@ -546,7 +485,7 @@ describe('LocalFileSystem', function() {
localfilesystem.getLibraryEntry('object','').then(function(flows) {
flows.should.eql([ 'A', 'B', { abc: 'def', fn: 'file1.js' } ]);
localfilesystem.getLibraryEntry('object','B').then(function(flows) {
flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]);
flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' }, { fn: 'flow.json' } ]);
localfilesystem.getLibraryEntry('object','B/C').then(function(flows) {
flows.should.eql([]);
done();
@ -564,6 +503,19 @@ describe('LocalFileSystem', function() {
});
});
it('should load a flow library object with .json unspecified', function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
createObjectLibrary("flows");
localfilesystem.getLibraryEntry('flows','B/flow').then(function(flows) {
flows.should.eql("Hi");
done();
}).otherwise(function(err) {
done(err);
});
});
});
it('should return a library object',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
createObjectLibrary();
@ -582,7 +534,7 @@ describe('LocalFileSystem', function() {
localfilesystem.init({userDir:userDir}).then(function() {
createObjectLibrary();
localfilesystem.getLibraryEntry('object','B').then(function(flows) {
flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]);
flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' }, {fn:'flow.json'} ]);
localfilesystem.saveLibraryEntry('object','B/D/file3.js',{mno:'pqr'},"// another non meta line\n\n Hi There").then(function() {
localfilesystem.getLibraryEntry('object','B/D').then(function(flows) {
flows.should.eql([ { mno: 'pqr', fn: 'file3.js' } ]);