UNPKG

node-red-contrib-xstorage

Version:

A Node-RED storageModule for load flows from xStorage and save flows at xStorage.

413 lines (361 loc) 11.4 kB
var when = require('when'); var nodeFn = require('when/node/function'); var keys = require('when/keys'); var fs = require('fs-extra'); var fspath = require("path"); var mkdirp = fs.mkdirs; var crypto = require('crypto'); var mc = require('./lib/mcClient.js'); var caller = { SetConfig: mc.set, GetConfig: mc.get, call: mc.call, reged: mc.reged } var initialFlowLoadComplete = false; var settings; var runtime; var flowsFile; var projectFile; var flowsFullPath; var flowsFileBackup; var credentialsFile; var credentialsFileBackup; var oldCredentialsFile; var sessionsFile; var libDir; var libFlowsDir; var globalSettingsFile; var qName; var qCode; var eiName; var promiseDir = nodeFn.lift(mkdirp); function escapeRegExp(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } function loadObjMMS(){ return when.promise(async function(resolve, reject){ let payload = { type: "flow" }; if(qCode) payload.qcode = qCode; else if(qName) payload.qname = qName; else reject('QCODE or QNAME is required.'); while(1){ if(caller.reged() != ""){ break; } await new Promise(resolve => setTimeout(resolve, 500)); } caller.call('', process.env.OBJMMS_DDN || '>svc/objstore', 'obj://get', payload).then(reply => { if (reply) { let result; if (typeof reply == 'object') result = reply; else result = reply[0]; if (Array.isArray(result)) result = result[0]; if(!result.Reply){ reject(result.IN.State.ErrMsg); }else{ result = result.Reply; } if (result.ErrMsg != 'OK') { reject(result.ErrMsg); } else if (result.ErrMsg == 'OK') { result = result.Data; if(result && result.data.flow) resolve(result.data.flow); else{ reject(`Flow not found: QNAME = ${qName} QCODE = ${qCode}`); } } } else { reject("Call objmms not response") } }).catch(err => { console.log(err); reject(err.message); }); }) } function objLoad(type, path) { if (!initialFlowLoadComplete) { initialFlowLoadComplete = true; } return when.promise(async function(resolve, reject) { if(type == 'flows'){ loadObjMMS().then((reply)=>{ if(reply && reply.length > 0){ console.log("Flow loaded from obj-mms: QNAME = %s QCODE = %s", qName, qCode); objSave('flows', '/', reply).then((result)=>{ console.log("Flow stored at xstorage: QNAME = %s QCODE = %s EINAME = ", qName, qCode, eiName); resolve(reply); }).catch((err)=>{ console.log("Flow can't store at xstorage: QNAME = %s QCODE =%s EINAME = ", qName, qCode, eiName); console.log(err); reject(err.message); }); } }).catch((err) => { console.log("Flow can't load from obj-mms: QNAME = %s QCODE = %s", qName, qCode); console.log(err); let payload = { catalog: 'flow', idname: eiName }; caller.GetConfig(payload).then((reply) => { if (reply) { let result; if (typeof reply == 'object') result = reply; else result = reply[0]; if (Array.isArray(result)) result = result[0]; if (result.ErrMsg != 'OK') { reject(result.ErrMsg); } else if (result.ErrMsg == 'OK') { console.log("Flow load from xstorage: QNAME = %s QCODE = %s EINAME = ", qName, qCode, eiName); if(result.result) resolve(result.result); else if(type == 'flows'){ resolve([]); } else{ resolve([]); } } } else { console.log("Flow can't load from xstorage: QNAME = %s QCODE = %s EINAME = ", qName, qCode, eiName); reject("Call xstorage not response") } }); }); }else{ let idname = type; if(path) idname += `_${path}`; let payload = { catalog: type == 'flows' ? 'flow' : type, idname: idname }; caller.GetConfig(payload).then((reply) => { if (reply) { let result; if (typeof reply == 'object') result = reply; else result = reply[0]; if (Array.isArray(result)) result = result[0]; if (result.ErrMsg != 'OK') { reject(result.ErrMsg); } else if (result.ErrMsg == 'OK') { if(result.result) resolve(result.result); else if(type == 'flows'){ resolve([]); } else{ resolve([]); } } } else { reject("Call xstorage not response") } }); } }); } function objSave(type, path, blob) { //need to check return when.promise(function(resolve, reject) { let idname = type; if(path) idname += `_${path}`; if(type == 'flows'){ idname = eiName; } let payload = { catalog: type == 'flows' ? 'flow' : type, idname: idname, data: blob }; caller.SetConfig(payload).then((reply) => { if (reply) { let result; if (typeof reply == 'object') result = reply; else result = reply[0]; if (Array.isArray(result)) result = result[0]; if (result.ErrMsg != 'OK') { reject(result.ErrMsg); } else if (result.ErrMsg == 'OK') { resolve('OK') } } else { reject('Call xstorage not response'); } }); }); } var xStorage = { init: function(_settings, _runtime) { var promises = []; settings = _settings; runtime = _runtime; if (!settings.userDir) { try { fs.statSync(fspath.join(process.env.NODE_RED_HOME,".config.json")); settings.userDir = process.env.NODE_RED_HOME; } catch(err) { settings.userDir = fspath.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE || process.env.NODE_RED_HOME,".node-red"); if (!settings.readOnly) { promises.push(promiseDir(fspath.join(settings.userDir,"node_modules"))); } } } if (process.env.FLOW_FILE || settings.flowFile) { flowsFile = process.env.FBOT_FLOWFILE || settings.flowFile; // handle Unix and Windows "C:\" if ((flowsFile[0] == "/") || (flowsFile[1] == ":")) { // Absolute path flowsFullPath = flowsFile; } else if (flowsFile.substring(0,2) === "./") { // Relative to cwd flowsFullPath = fspath.join(process.cwd(),flowsFile); } else { try { fs.statSync(fspath.join(process.cwd(),flowsFile)); // Found in cwd flowsFullPath = fspath.join(process.cwd(),flowsFile); } catch(err) { // Use userDir flowsFullPath = fspath.join(settings.userDir,flowsFile); } } } else { flowsFile = 'flows_'+require('os').hostname()+'.json'; flowsFullPath = fspath.join(settings.userDir,flowsFile); } var ffExt = fspath.extname(flowsFullPath); var ffName = fspath.basename(flowsFullPath); var ffBase = fspath.basename(flowsFullPath,ffExt); var ffDir = fspath.dirname(flowsFullPath); credentialsFile = fspath.join(settings.userDir,ffBase+"_cred"+ffExt); credentialsFileBackup = fspath.join(settings.userDir,"."+ffBase+"_cred"+ffExt+".backup"); oldCredentialsFile = fspath.join(settings.userDir,"credentials.json"); //flowsFileBackup = fspath.join(ffDir,"."+ffName+".backup"); sessionsFile = fspath.join(settings.userDir,".sessions.json"); //projectFile = fspath.join(settings.userDir,"projects.json"); libDir = fspath.join(settings.userDir,"lib"); libFlowsDir = fspath.join(libDir,"flows"); globalSettingsFile = fspath.join(settings.userDir,".config.json"); if (!settings.readOnly) { promises.push(promiseDir(libFlowsDir)); } qName = process.env.FBOT_QNAME; qCode = process.env.FBOT_QCODE; eiName = process.env.MCHAT_EINAME; promises.push(mc.setup()); return when.all(promises); }, getFlows: function() { return objLoad('flows', '/'); }, saveFlows: function(flows) { return objSave('flows', '/', flows); }, getCredentials: function() { return objLoad('credentials', '/'); }, saveCredentials: function(credentials) { return objSave('credentials', '/', credentials); }, getSettings: function() { return objLoad('settings', '/'); }, saveSettings: function(settings) { return objSave('settings', '/', settings); }, getSessions: function() { return objLoad('sessions', '/'); }, saveSessions: function(sessions) { return objSave('sessions', '/', sessions); }, getLibraryEntry: function(type, path) { return when.promise(function(resolve, reject) { let idname = 'library'; if(type) idname += `_${type}`; if(path) idname += `_${path}`; let payload = { catalog: type, idname: idname } caller.GetConfig(payload).then((reply) => { if (reply) { let result; if (typeof reply == 'object') result = reply; else result = reply[0]; if (Array.isArray(result)) result = result[0]; if (result.ErrMsg != 'OK') { reject(result.ErrMsg); } else if (result.ErrMsg == 'OK') { resolve(result.result || {}); } } else { reject("Call xstorage not response") } }); }); }, saveLibraryEntry: function(type, path, meta, body) { return when.promise(function(resolve, reject) { let idname = type; if(path) idname += `_${path}`; let payload = { catalog: type, idname: idname, data: {meta : meta, body: body} }; caller.SetConfig(payload).then((reply) => { if (reply) { let result; if (typeof reply == 'object') result = reply; else result = reply[0]; if (Array.isArray(result)) result = result[0]; if (result.ErrMsg != 'OK') { reject(result.ErrMsg); } else if (result.ErrMsg == 'OK') { resolve('OK') } } else { reject('Call xstorage not response'); } }); }); } }; module.exports = xStorage;