Make storage.init return a promise to async initialisation

part of #62
This commit is contained in:
Nicholas O'Leary 2013-11-12 17:13:06 +00:00
parent 1536dcdf1e
commit 848a69dc26
6 changed files with 205 additions and 197 deletions

View File

@ -19,7 +19,7 @@ var storage = null;
function init() { function init() {
redApp = require("./server").app; redApp = require("./server").app;
storage = require("./storage").storage; storage = require("./storage");
// -------- Flow Library -------- // -------- Flow Library --------
redApp.post(new RegExp("/library/flows\/(.*)"), function(req,res) { redApp.post(new RegExp("/library/flows\/(.*)"), function(req,res) {

View File

@ -277,7 +277,7 @@ module.exports.setConfig = function(conf) {
if (!storage) { if (!storage) {
// Do this lazily to ensure the storage provider as been initialised // Do this lazily to ensure the storage provider as been initialised
storage = require("./storage").storage; storage = require("./storage");
} }
storage.getCredentials().then(function(creds) { storage.getCredentials().then(function(creds) {
credentials = creds; credentials = creds;

View File

@ -20,12 +20,13 @@ var redNodes = require("./nodes");
var app = null; var app = null;
var server = null; var server = null;
var settings = null;
var storage = null;
function createServer(_server,settings) { function createServer(_server,_settings) {
server = _server; server = _server;
settings = _settings;
storage = require("./storage").init(settings); storage = require("./storage");
app = createUI(settings); app = createUI(settings);
flowfile = settings.flowFile || 'flows_'+require('os').hostname()+'.json'; flowfile = settings.flowFile || 'flows_'+require('os').hostname()+'.json';
@ -61,25 +62,27 @@ function createServer(_server,settings) {
} }
function start() { function start() {
console.log("\nWelcome to Node-RED\n===================\n"); storage.init(settings).then(function() {
util.log("[red] Loading palette nodes"); console.log("\nWelcome to Node-RED\n===================\n");
util.log("------------------------------------------"); util.log("[red] Loading palette nodes");
redNodes.load(); util.log("------------------------------------------");
util.log(""); redNodes.load();
util.log('You may ignore any errors above here if they are for'); util.log("");
util.log('nodes you are not using. The nodes indicated will not'); util.log('You may ignore any errors above here if they are for');
util.log('be available in the main palette until any missing'); util.log('nodes you are not using. The nodes indicated will not');
util.log('modules are installed, typically by running:'); util.log('be available in the main palette until any missing');
util.log(' npm install {the module name}'); util.log('modules are installed, typically by running:');
util.log('or any other errors are resolved'); util.log(' npm install {the module name}');
util.log("------------------------------------------"); util.log('or any other errors are resolved');
util.log("------------------------------------------");
storage.getFlows().then(function(flows) {
if (flows.length > 0) { storage.getFlows().then(function(flows) {
redNodes.setConfig(flows); if (flows.length > 0) {
} redNodes.setConfig(flows);
}).otherwise(function(err) { }
util.log("[red] Error loading flows : "+err); }).otherwise(function(err) {
util.log("[red] Error loading flows : "+err);
});
}); });
} }

View File

@ -15,19 +15,9 @@
**/ **/
var settings; var settings = require('../red').settings;
var storage;
module.exports = { var storageType = settings.storageModule || "localfilesystem";
init: function(_settings) {
settings = _settings;
var storageType = settings.storageModule || "localfilesystem";
storage = require("./"+storageType).init(settings);
return storage;
},
};
module.exports.__defineGetter__("storage", function() { return storage; }); module.exports = require("./"+storageType);

View File

@ -160,7 +160,9 @@ var localfilesystem = {
if (!fs.existsSync(libFlowsDir)) { if (!fs.existsSync(libFlowsDir)) {
fs.mkdirSync(libFlowsDir); fs.mkdirSync(libFlowsDir);
} }
return this; var defer = when.defer();
defer.resolve();
return defer.promise;
}, },
getFlows: function() { getFlows: function() {
var defer = when.defer(); var defer = when.defer();

View File

@ -18,40 +18,42 @@ describe('LocalFileSystem', function() {
}); });
it('should initialise the user directory',function() { it('should initialise the user directory',function() {
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
fs.existsSync(path.join(userDir,"lib")).should.be.true; fs.existsSync(path.join(userDir,"lib")).should.be.true;
fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true; fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true;
});
}); });
it('should handle missing flow file',function(done) { it('should handle missing flow file',function(done) {
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
var flowFile = 'flows_'+require('os').hostname()+'.json'; var flowFile = 'flows_'+require('os').hostname()+'.json';
var flowFilePath = path.join(userDir,flowFile); var flowFilePath = path.join(userDir,flowFile);
fs.existsSync(flowFilePath).should.be.false; fs.existsSync(flowFilePath).should.be.false;
localfilesystem.getFlows().then(function(flows) {
flows.should.eql([]);
done();
}).otherwise(function(err) {
done(err);
});
});
it('should save flows to the default file',function(done) {
localfilesystem.init({userDir:userDir});
var flowFile = 'flows_'+require('os').hostname()+'.json';
var flowFilePath = path.join(userDir,flowFile);
fs.existsSync(flowFilePath).should.be.false;
localfilesystem.saveFlows(testFlow).then(function() {
fs.existsSync(flowFilePath).should.be.true;
localfilesystem.getFlows().then(function(flows) { localfilesystem.getFlows().then(function(flows) {
flows.should.eql(testFlow); flows.should.eql([]);
done(); done();
}).otherwise(function(err) { }).otherwise(function(err) {
done(err); done(err);
}); });
}).otherwise(function(err) { });
done(err); });
it('should save flows to the default file',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
var flowFile = 'flows_'+require('os').hostname()+'.json';
var flowFilePath = path.join(userDir,flowFile);
fs.existsSync(flowFilePath).should.be.false;
localfilesystem.saveFlows(testFlow).then(function() {
fs.existsSync(flowFilePath).should.be.true;
localfilesystem.getFlows().then(function(flows) {
flows.should.eql(testFlow);
done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
}); });
}); });
@ -61,129 +63,137 @@ describe('LocalFileSystem', function() {
var flowFile = 'test.json'; var flowFile = 'test.json';
var flowFilePath = path.join(userDir,flowFile); var flowFilePath = path.join(userDir,flowFile);
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}); localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() {
fs.existsSync(defaultFlowFilePath).should.be.false;
fs.existsSync(flowFilePath).should.be.false;
localfilesystem.saveFlows(testFlow).then(function() {
fs.existsSync(defaultFlowFilePath).should.be.false; fs.existsSync(defaultFlowFilePath).should.be.false;
fs.existsSync(flowFilePath).should.be.true; fs.existsSync(flowFilePath).should.be.false;
localfilesystem.getFlows().then(function(flows) {
flows.should.eql(testFlow); localfilesystem.saveFlows(testFlow).then(function() {
done(); fs.existsSync(defaultFlowFilePath).should.be.false;
fs.existsSync(flowFilePath).should.be.true;
localfilesystem.getFlows().then(function(flows) {
flows.should.eql(testFlow);
done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) { }).otherwise(function(err) {
done(err); done(err);
}); });
}).otherwise(function(err) {
done(err);
}); });
}); });
it('should handle missing credentials', function(done) { it('should handle missing credentials', function(done) {
var credFile = path.join(userDir,"credentials.json"); var credFile = path.join(userDir,"credentials.json");
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
fs.existsSync(credFile).should.be.false; fs.existsSync(credFile).should.be.false;
localfilesystem.getCredentials().then(function(creds) { localfilesystem.getCredentials().then(function(creds) {
creds.should.eql({}); creds.should.eql({});
done(); done();
}).otherwise(function(err) { }).otherwise(function(err) {
done(err); done(err);
});
}); });
}); });
it('should handle credentials', function(done) { it('should handle credentials', function(done) {
var credFile = path.join(userDir,"credentials.json"); var credFile = path.join(userDir,"credentials.json");
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
fs.existsSync(credFile).should.be.false; fs.existsSync(credFile).should.be.false;
var credentials = {"abc":{"type":"creds"}}; var credentials = {"abc":{"type":"creds"}};
localfilesystem.saveCredentials(credentials).then(function() { localfilesystem.saveCredentials(credentials).then(function() {
fs.existsSync(credFile).should.be.true; fs.existsSync(credFile).should.be.true;
localfilesystem.getCredentials().then(function(creds) { localfilesystem.getCredentials().then(function(creds) {
creds.should.eql(credentials); creds.should.eql(credentials);
done(); done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) { }).otherwise(function(err) {
done(err); done(err);
}); });
}).otherwise(function(err) {
done(err);
}); });
}); });
it('should return an empty list of library flows',function(done) { it('should return an empty list of library flows',function(done) {
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
localfilesystem.getAllFlows().then(function(flows) { localfilesystem.getAllFlows().then(function(flows) {
flows.should.eql({}); flows.should.eql({});
done();
}).otherwise(function(err) {
done(err);
});
});
it('should return a valid list of library flows',function(done) {
localfilesystem.init({userDir:userDir});
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);
});
});
it('should fail a non-existent flow', function(done) {
localfilesystem.init({userDir:userDir});
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);
});
});
it('should return a flow',function(done) {
localfilesystem.init({userDir:userDir});
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(); done();
}).otherwise(function(err) { }).otherwise(function(err) {
done(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);
});
});
});
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);
});
});
});
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);
});
}); });
}); });
it('should return an empty list of library objects',function(done) { it('should return an empty list of library objects',function(done) {
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
localfilesystem.getLibraryEntry('object','').then(function(flows) { localfilesystem.getLibraryEntry('object','').then(function(flows) {
flows.should.eql({}); flows.should.eql({});
done(); done();
}).otherwise(function(err) { }).otherwise(function(err) {
done(err); done(err);
});
}); });
}); });
it('should return an error for a non-existent library object',function(done) { it('should return an error for a non-existent library object',function(done) {
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
localfilesystem.getLibraryEntry('object','A/B').then(function(flows) { localfilesystem.getLibraryEntry('object','A/B').then(function(flows) {
should.fail(null,null,"non-existent flow"); should.fail(null,null,"non-existent flow");
}).otherwise(function(err) { }).otherwise(function(err) {
should.exist(err); should.exist(err);
done(); done();
});
}); });
}); });
@ -198,48 +208,15 @@ describe('LocalFileSystem', function() {
} }
it('should return a directory listing of library objects',function(done) { it('should return a directory listing of library objects',function(done) {
localfilesystem.init({userDir:userDir}); localfilesystem.init({userDir:userDir}).then(function() {
createObjectLibrary(); createObjectLibrary();
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' } ]);
localfilesystem.getLibraryEntry('object','B/C').then(function(flows) {
flows.should.eql([]);
done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
});
it('should return a library object',function(done) { localfilesystem.getLibraryEntry('object','').then(function(flows) {
localfilesystem.init({userDir:userDir}); flows.should.eql([ 'A', 'B', { abc: 'def', fn: 'file1.js' } ]);
createObjectLibrary(); localfilesystem.getLibraryEntry('object','B').then(function(flows) {
localfilesystem.getLibraryEntry('object','B/file2.js').then(function(body) { flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]);
body.should.eql("// not a metaline \n\n Hi"); localfilesystem.getLibraryEntry('object','B/C').then(function(flows) {
done(); flows.should.eql([]);
}).otherwise(function(err) {
done(err);
});
});
it('should return a newly saved library object',function(done) {
localfilesystem.init({userDir:userDir});
createObjectLibrary();
localfilesystem.getLibraryEntry('object','B').then(function(flows) {
flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]);
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' } ]);
localfilesystem.getLibraryEntry('object','B/D/file3.js').then(function(body) {
body.should.eql("// another non meta line\n\n Hi There");
done(); done();
}).otherwise(function(err) { }).otherwise(function(err) {
done(err); done(err);
@ -250,8 +227,44 @@ describe('LocalFileSystem', function() {
}).otherwise(function(err) { }).otherwise(function(err) {
done(err); done(err);
}); });
}).otherwise(function(err) { });
done(err); });
it('should return a library object',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
createObjectLibrary();
localfilesystem.getLibraryEntry('object','B/file2.js').then(function(body) {
body.should.eql("// not a metaline \n\n Hi");
done();
}).otherwise(function(err) {
done(err);
});
});
});
it('should return a newly saved library object',function(done) {
localfilesystem.init({userDir:userDir}).then(function() {
createObjectLibrary();
localfilesystem.getLibraryEntry('object','B').then(function(flows) {
flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]);
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' } ]);
localfilesystem.getLibraryEntry('object','B/D/file3.js').then(function(body) {
body.should.eql("// another non meta line\n\n Hi There");
done();
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
}).otherwise(function(err) {
done(err);
});
}); });
}); });