@node-red/runtime
Advanced tools
Comparing version 1.0.0-beta.2 to 1.0.0-beta.3
@@ -70,3 +70,3 @@ /** | ||
* @param {String} opts.key - the context key | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise} - the node information | ||
@@ -85,3 +85,3 @@ * @memberof @node-red/runtime_context | ||
if (store && availableStores.stores.indexOf(store) === -1) { | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}); | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -111,3 +111,3 @@ err.code = "not_found"; | ||
} | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}); | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}, opts.req); | ||
resolve(encoded); | ||
@@ -133,3 +133,3 @@ }); | ||
errorReported = true; | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"unexpected_error"}); | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"unexpected_error"}, opts.req); | ||
var err = new Error(); | ||
@@ -146,3 +146,3 @@ err.code = "unexpected_error"; | ||
if (!errorReported) { | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}); | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key},opts.req); | ||
resolve(result); | ||
@@ -155,3 +155,3 @@ } | ||
} else { | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key}); | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key},opts.req); | ||
resolve({}); | ||
@@ -170,3 +170,3 @@ } | ||
* @param {String} opts.key - the context key | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise} - the node information | ||
@@ -185,3 +185,3 @@ * @memberof @node-red/runtime_context | ||
if (store && availableStores.stores.indexOf(store) === -1) { | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}); | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"},opts.req); | ||
var err = new Error(); | ||
@@ -207,3 +207,3 @@ err.code = "not_found"; | ||
ctx.set(key,undefined,store,function(err) { | ||
runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key}); | ||
runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key},opts.req); | ||
resolve(); | ||
@@ -214,3 +214,3 @@ }); | ||
// TODO: support deleting whole context | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"}); | ||
runtime.log.audit({event: "context.get",scope:scope,id:id,store:store,key:key,error:"not_found"},opts.req); | ||
var err = new Error(); | ||
@@ -256,3 +256,3 @@ err.code = "not_found"; | ||
} else { | ||
runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key}); | ||
runtime.log.audit({event: "context.delete",scope:scope,id:id,store:store,key:key},opts.req); | ||
resolve(); | ||
@@ -259,0 +259,0 @@ } |
@@ -46,2 +46,3 @@ /** | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Flows>} - the active flow configuration | ||
@@ -52,3 +53,3 @@ * @memberof @node-red/runtime_flows | ||
return new Promise(function(resolve,reject) { | ||
runtime.log.audit({event: "flows.get"}/*,req*/); | ||
runtime.log.audit({event: "flows.get"}, opts.req); | ||
return resolve(runtime.nodes.getFlows()); | ||
@@ -61,2 +62,3 @@ }); | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Flows>} - the active flow configuration | ||
@@ -70,3 +72,3 @@ * @memberof @node-red/runtime_flows | ||
var deploymentType = opts.deploymentType||"full"; | ||
runtime.log.audit({event: "flows.set",type:deploymentType}/*,req*/); | ||
runtime.log.audit({event: "flows.set",type:deploymentType}, opts.req); | ||
@@ -105,2 +107,3 @@ var apiPromise; | ||
* @param {Object} opts.flow - the flow to add | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String>} - the id of the added flow | ||
@@ -113,6 +116,6 @@ * @memberof @node-red/runtime_flows | ||
runtime.nodes.addFlow(flow).then(function(id) { | ||
runtime.log.audit({event: "flow.add",id:id}); | ||
runtime.log.audit({event: "flow.add",id:id}, opts.req); | ||
return resolve(id); | ||
}).catch(function(err) { | ||
runtime.log.audit({event: "flow.add",error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "flow.add",error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -131,2 +134,3 @@ return reject(err); | ||
* @param {Object} opts.id - the id of the flow to retrieve | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Flow>} - the active flow configuration | ||
@@ -139,6 +143,6 @@ * @memberof @node-red/runtime_flows | ||
if (flow) { | ||
runtime.log.audit({event: "flow.get",id:opts.id}); | ||
runtime.log.audit({event: "flow.get",id:opts.id}, opts.req); | ||
return resolve(flow); | ||
} else { | ||
runtime.log.audit({event: "flow.get",id:opts.id,error:"not_found"}); | ||
runtime.log.audit({event: "flow.get",id:opts.id,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -158,2 +162,3 @@ err.code = "not_found"; | ||
* @param {Object} opts.flow - the flow configuration | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String>} - the id of the updated flow | ||
@@ -168,6 +173,6 @@ * @memberof @node-red/runtime_flows | ||
runtime.nodes.updateFlow(id,flow).then(function() { | ||
runtime.log.audit({event: "flow.update",id:id}); | ||
runtime.log.audit({event: "flow.update",id:id}, opts.req); | ||
return resolve(id); | ||
}).catch(function(err) { | ||
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -178,3 +183,3 @@ return reject(err); | ||
if (err.code === 404) { | ||
runtime.log.audit({event: "flow.update",id:id,error:"not_found"}); | ||
runtime.log.audit({event: "flow.update",id:id,error:"not_found"}, opts.req); | ||
// TODO: this swap around of .code and .status isn't ideal | ||
@@ -185,3 +190,3 @@ err.status = 404; | ||
} else { | ||
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "flow.update",error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -199,2 +204,3 @@ return reject(err); | ||
* @param {Object} opts.id - the id of the flow to delete | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise} - resolves if successful | ||
@@ -208,6 +214,6 @@ * @memberof @node-red/runtime_flows | ||
runtime.nodes.removeFlow(id).then(function() { | ||
runtime.log.audit({event: "flow.remove",id:id}); | ||
runtime.log.audit({event: "flow.remove",id:id}, opts.req); | ||
return resolve(); | ||
}).catch(function(err) { | ||
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -218,3 +224,3 @@ return reject(err); | ||
if (err.code === 404) { | ||
runtime.log.audit({event: "flow.remove",id:id,error:"not_found"}); | ||
runtime.log.audit({event: "flow.remove",id:id,error:"not_found"}, opts.req); | ||
// TODO: this swap around of .code and .status isn't ideal | ||
@@ -225,3 +231,3 @@ err.status = 404; | ||
} else { | ||
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "flow.remove",id:id,error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -240,2 +246,3 @@ return reject(err); | ||
* @param {String} opts.id - the node id | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the safe credentials | ||
@@ -246,3 +253,3 @@ * @memberof @node-red/runtime_flows | ||
return new Promise(function(resolve,reject) { | ||
runtime.log.audit({event: "credentials.get",type:opts.type,id:opts.id}); | ||
runtime.log.audit({event: "credentials.get",type:opts.type,id:opts.id}, opts.req); | ||
var credentials = runtime.nodes.getCredentials(opts.id); | ||
@@ -249,0 +256,0 @@ if (!credentials) { |
@@ -35,2 +35,3 @@ /** | ||
* @param {String} opts.path - the path of the entry | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String|Object>} - resolves when complete | ||
@@ -42,3 +43,3 @@ * @memberof @node-red/runtime_library | ||
runtime.library.getEntry(opts.library,opts.type,opts.path).then(function(result) { | ||
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path}); | ||
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path}, opts.req); | ||
return resolve(result); | ||
@@ -56,6 +57,6 @@ }).catch(function(err) { | ||
} | ||
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path,error:err.code}); | ||
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path,error:err.code}, opts.req); | ||
return reject(err); | ||
} | ||
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,error:"not_found"}); | ||
runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,error:"not_found"}, opts.req); | ||
var error = new Error(); | ||
@@ -78,2 +79,3 @@ error.code = "not_found"; | ||
* @param {String} opts.body - the body of the entry | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise} - resolves when complete | ||
@@ -85,3 +87,3 @@ * @memberof @node-red/runtime_library | ||
runtime.library.saveEntry(opts.library,opts.type,opts.path,opts.meta,opts.body).then(function() { | ||
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path}); | ||
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path}, opts.req); | ||
return resolve(); | ||
@@ -91,7 +93,7 @@ }).catch(function(err) { | ||
if (err.code === 'forbidden') { | ||
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"forbidden"}); | ||
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"forbidden"}, opts.req); | ||
err.status = 403; | ||
return reject(err); | ||
} | ||
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"unexpected_error",message:err.toString()}, opts.req); | ||
var error = new Error(); | ||
@@ -98,0 +100,0 @@ error.status = 400; |
@@ -51,2 +51,3 @@ /** | ||
* @param {String} opts.id - the id of the node set to return | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<NodeInfo>} - the node information | ||
@@ -60,7 +61,7 @@ * @memberof @node-red/runtime_nodes | ||
if (result) { | ||
runtime.log.audit({event: "nodes.info.get",id:id}); | ||
runtime.log.audit({event: "nodes.info.get",id:id}, opts.req); | ||
delete result.loaded; | ||
return resolve(result); | ||
} else { | ||
runtime.log.audit({event: "nodes.info.get",id:id,error:"not_found"}); | ||
runtime.log.audit({event: "nodes.info.get",id:id,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -78,2 +79,3 @@ err.code = "not_found"; | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<NodeList>} - the list of node modules | ||
@@ -84,3 +86,3 @@ * @memberof @node-red/runtime_nodes | ||
return new Promise(function(resolve,reject) { | ||
runtime.log.audit({event: "nodes.list.get"}); | ||
runtime.log.audit({event: "nodes.list.get"}, opts.req); | ||
return resolve(runtime.nodes.getNodeList()); | ||
@@ -96,2 +98,3 @@ }) | ||
* @param {String} opts.lang - the locale language to return | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String>} - the node html content | ||
@@ -106,6 +109,6 @@ * @memberof @node-red/runtime_nodes | ||
if (result) { | ||
runtime.log.audit({event: "nodes.config.get",id:id}); | ||
runtime.log.audit({event: "nodes.config.get",id:id}, opts.req); | ||
return resolve(result); | ||
} else { | ||
runtime.log.audit({event: "nodes.config.get",id:id,error:"not_found"}); | ||
runtime.log.audit({event: "nodes.config.get",id:id,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -123,2 +126,3 @@ err.code = "not_found"; | ||
* @param {String} opts.lang - the locale language to return | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String>} - the node html content | ||
@@ -129,3 +133,3 @@ * @memberof @node-red/runtime_nodes | ||
return new Promise(function(resolve,reject) { | ||
runtime.log.audit({event: "nodes.configs.get"}); | ||
runtime.log.audit({event: "nodes.configs.get"}, opts.req); | ||
return resolve(runtime.nodes.getNodeConfigs(opts.lang)); | ||
@@ -140,2 +144,3 @@ }); | ||
* @param {String} opts.module - the id of the module to return | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<ModuleInfo>} - the node module info | ||
@@ -148,6 +153,6 @@ * @memberof @node-red/runtime_nodes | ||
if (result) { | ||
runtime.log.audit({event: "nodes.module.get",id:opts.module}); | ||
runtime.log.audit({event: "nodes.module.get",id:opts.module}, opts.req); | ||
return resolve(result); | ||
} else { | ||
runtime.log.audit({event: "nodes.module.get",id:opts.module,error:"not_found"}); | ||
runtime.log.audit({event: "nodes.module.get",id:opts.module,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -167,2 +172,3 @@ err.code = "not_found"; | ||
* @param {String} opts.version - (optional) the version of the module to install | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<ModuleInfo>} - the node module info | ||
@@ -174,3 +180,3 @@ * @memberof @node-red/runtime_nodes | ||
if (!runtime.settings.available()) { | ||
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}); | ||
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req); | ||
var err = new Error("Settings unavailable"); | ||
@@ -185,3 +191,3 @@ err.code = "settings_unavailable"; | ||
if (!opts.version || existingModule.version === opts.version) { | ||
runtime.log.audit({event: "nodes.install",module:opts.module, version:opts.version, error:"module_already_loaded"}); | ||
runtime.log.audit({event: "nodes.install",module:opts.module, version:opts.version, error:"module_already_loaded"}, opts.req); | ||
var err = new Error("Module already loaded"); | ||
@@ -194,7 +200,7 @@ err.code = "module_already_loaded"; | ||
runtime.nodes.installModule(opts.module,opts.version).then(function(info) { | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version}); | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version}, opts.req); | ||
return resolve(info); | ||
}).catch(function(err) { | ||
if (err.code === 404) { | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:"not_found"}); | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:"not_found"}, opts.req); | ||
// TODO: code/status | ||
@@ -204,6 +210,6 @@ err.status = 404; | ||
err.status = 400; | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code}); | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code}, opts.req); | ||
} else { | ||
err.status = 400; | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
} | ||
@@ -213,3 +219,3 @@ return reject(err); | ||
} else { | ||
runtime.log.audit({event: "nodes.install",module:opts.module,error:"invalid_request"}); | ||
runtime.log.audit({event: "nodes.install",module:opts.module,error:"invalid_request"}, opts.req); | ||
var err = new Error("Invalid request"); | ||
@@ -228,2 +234,3 @@ err.code = "invalid_request"; | ||
* @param {String} opts.module - the id of the module to remove | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise} - resolves when complete | ||
@@ -235,3 +242,3 @@ * @memberof @node-red/runtime_nodes | ||
if (!runtime.settings.available()) { | ||
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}); | ||
runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req); | ||
var err = new Error("Settings unavailable"); | ||
@@ -244,3 +251,3 @@ err.code = "settings_unavailable"; | ||
if (!module) { | ||
runtime.log.audit({event: "nodes.remove",module:opts.module,error:"not_found"}); | ||
runtime.log.audit({event: "nodes.remove",module:opts.module,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -253,11 +260,11 @@ err.code = "not_found"; | ||
runtime.nodes.uninstallModule(opts.module).then(function() { | ||
runtime.log.audit({event: "nodes.remove",module:opts.module}); | ||
runtime.log.audit({event: "nodes.remove",module:opts.module}, opts.req); | ||
resolve(); | ||
}).catch(function(err) { | ||
err.status = 400; | ||
runtime.log.audit({event: "nodes.remove",module:opts.module,error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "nodes.remove",module:opts.module,error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
return reject(err); | ||
}) | ||
} catch(error) { | ||
runtime.log.audit({event: "nodes.remove",module:opts.module,error:error.code||"unexpected_error",message:error.toString()}); | ||
runtime.log.audit({event: "nodes.remove",module:opts.module,error:error.code||"unexpected_error",message:error.toString()}, opts.req); | ||
error.status = 400; | ||
@@ -275,2 +282,3 @@ return reject(error); | ||
* @param {String} opts.enabled - whether the module should be enabled or disabled | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<ModuleInfo>} - the module info object | ||
@@ -283,3 +291,3 @@ * @memberof @node-red/runtime_nodes | ||
if (!runtime.settings.available()) { | ||
runtime.log.audit({event: "nodes.module.set",error:"settings_unavailable"}); | ||
runtime.log.audit({event: "nodes.module.set",error:"settings_unavailable"}, opts.req); | ||
var err = new Error("Settings unavailable"); | ||
@@ -293,3 +301,3 @@ err.code = "settings_unavailable"; | ||
if (!module) { | ||
runtime.log.audit({event: "nodes.module.set",module:mod,error:"not_found"}); | ||
runtime.log.audit({event: "nodes.module.set",module:mod,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -313,3 +321,3 @@ err.code = "not_found"; | ||
} catch(error) { | ||
runtime.log.audit({event: "nodes.module.set",module:mod,enabled:opts.enabled,error:error.code||"unexpected_error",message:error.toString()}); | ||
runtime.log.audit({event: "nodes.module.set",module:mod,enabled:opts.enabled,error:error.code||"unexpected_error",message:error.toString()}, opts.req); | ||
error.status = 400; | ||
@@ -327,2 +335,3 @@ return reject(error); | ||
* @param {String} opts.enabled - whether the module should be enabled or disabled | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<ModuleInfo>} - the module info object | ||
@@ -334,3 +343,3 @@ * @memberof @node-red/runtime_nodes | ||
if (!runtime.settings.available()) { | ||
runtime.log.audit({event: "nodes.info.set",error:"settings_unavailable"}); | ||
runtime.log.audit({event: "nodes.info.set",error:"settings_unavailable"}, opts.req); | ||
var err = new Error("Settings unavailable"); | ||
@@ -347,3 +356,3 @@ err.code = "settings_unavailable"; | ||
if (!node) { | ||
runtime.log.audit({event: "nodes.info.set",id:id,error:"not_found"}); | ||
runtime.log.audit({event: "nodes.info.set",id:id,error:"not_found"}, opts.req); | ||
var err = new Error(); | ||
@@ -356,6 +365,6 @@ err.code = "not_found"; | ||
putNode(node,enabled).then(function(result) { | ||
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled}); | ||
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled}, opts.req); | ||
return resolve(result); | ||
}).catch(function(err) { | ||
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -366,3 +375,3 @@ return reject(err); | ||
} catch(error) { | ||
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:error.code||"unexpected_error",message:error.toString()}); | ||
runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:error.code||"unexpected_error",message:error.toString()}, opts.req); | ||
error.status = 400; | ||
@@ -379,2 +388,3 @@ return reject(error); | ||
* @param {User} opts.lang - the i18n language to return. If not set, uses runtime default (en-US) | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the message catalogs | ||
@@ -409,2 +419,3 @@ * @memberof @node-red/runtime_nodes | ||
* @param {User} opts.lang - the i18n language to return. If not set, uses runtime default (en-US) | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the message catalog | ||
@@ -431,2 +442,3 @@ * @memberof @node-red/runtime_nodes | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<IconList>} - the list of all icons | ||
@@ -437,3 +449,3 @@ * @memberof @node-red/runtime_nodes | ||
return new Promise(function(resolve,reject) { | ||
runtime.log.audit({event: "nodes.icons.get"}); | ||
runtime.log.audit({event: "nodes.icons.get"}, opts.req); | ||
return resolve(runtime.nodes.getNodeIcons()); | ||
@@ -449,2 +461,3 @@ }); | ||
* @param {String} opts.icon - the name of the icon | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Buffer>} - the icon file as a Buffer or null if no icon available | ||
@@ -451,0 +464,0 @@ * @memberof @node-red/runtime_nodes |
@@ -30,3 +30,2 @@ /** | ||
}, | ||
/** | ||
@@ -36,2 +35,4 @@ * List projects known to the runtime | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -61,2 +62,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {Object} opts.project - the project information | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -66,2 +68,3 @@ * @memberof @node-red/runtime_projects | ||
createProject: function(opts) { | ||
runtime.log.audit({event: "projects.create",name:opts.project?opts.project.name:"missing-name"}, opts.req); | ||
return runtime.storage.projects.createProject(opts.user, opts.project) | ||
@@ -76,2 +79,3 @@ }, | ||
* @param {Object} opts.project - the project information | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -82,2 +86,3 @@ * @memberof @node-red/runtime_projects | ||
// Initialised set when creating default files for an empty repo | ||
runtime.log.audit({event: "projects.initialise",id:opts.id}, opts.req); | ||
return runtime.storage.projects.initialiseProject(opts.user, opts.id, opts.project) | ||
@@ -90,2 +95,3 @@ }, | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the active project | ||
@@ -103,2 +109,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String} opts.id - the id of the project to activate | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -109,2 +116,3 @@ * @memberof @node-red/runtime_projects | ||
var currentProject = runtime.storage.projects.getActiveProject(opts.user); | ||
runtime.log.audit({event: "projects.set",id:opts.id}, opts.req); | ||
if (!currentProject || opts.id !== currentProject.name) { | ||
@@ -122,2 +130,3 @@ return runtime.storage.projects.setActiveProject(opts.user, opts.id); | ||
* @param {String} opts.id - the id of the project to get | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the project metadata | ||
@@ -136,2 +145,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {Object} opts.project - the project information | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -141,2 +151,3 @@ * @memberof @node-red/runtime_projects | ||
updateProject: function(opts) { | ||
runtime.log.audit({event: "projects.update",id:opts.id}, opts.req); | ||
return runtime.storage.projects.updateProject(opts.user, opts.id, opts.project); | ||
@@ -150,2 +161,3 @@ }, | ||
* @param {String} opts.id - the id of the project to update | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -155,2 +167,3 @@ * @memberof @node-red/runtime_projects | ||
deleteProject: function(opts) { | ||
runtime.log.audit({event: "projects.delete",id:opts.id}, opts.req); | ||
return runtime.storage.projects.deleteProject(opts.user, opts.id); | ||
@@ -165,2 +178,3 @@ }, | ||
* @param {Boolean} opts.remote - whether to include status of remote repos | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the project status | ||
@@ -179,2 +193,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {Boolean} opts.remote - whether to return remote branches (true) or local (false) | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - a list of the local branches | ||
@@ -193,2 +208,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String} opts.branch - the name of the branch | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the status of the branch | ||
@@ -208,2 +224,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {Boolean} opts.create - whether to create the branch if it doesn't exist | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -213,2 +230,3 @@ * @memberof @node-red/runtime_projects | ||
setBranch: function(opts) { | ||
runtime.log.audit({event: "projects.branch.set",id:opts.id, branch: opts.branch, create:opts.create}, opts.req); | ||
return runtime.storage.projects.setBranch(opts.user, opts.id, opts.branch, opts.create) | ||
@@ -224,2 +242,3 @@ }, | ||
* @param {Boolean} opts.force - whether to force delete | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -229,2 +248,3 @@ * @memberof @node-red/runtime_projects | ||
deleteBranch: function(opts) { | ||
runtime.log.audit({event: "projects.branch.delete",id:opts.id, branch: opts.branch, force:opts.force}, opts.req); | ||
return runtime.storage.projects.deleteBranch(opts.user, opts.id, opts.branch, false, opts.force); | ||
@@ -239,2 +259,3 @@ }, | ||
* @param {String} opts.message - the message to associate with the commit | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -244,2 +265,3 @@ * @memberof @node-red/runtime_projects | ||
commit: function(opts) { | ||
runtime.log.audit({event: "projects.commit",id:opts.id}, opts.req); | ||
return runtime.storage.projects.commit(opts.user, opts.id,{message: opts.message}); | ||
@@ -254,2 +276,3 @@ }, | ||
* @param {String} opts.sha - the sha of the commit to return | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the commit details | ||
@@ -269,2 +292,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String} opts.before - id of the commit to work back from | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Array>} - an array of commits | ||
@@ -285,2 +309,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String} opts.id - the id of the project | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -290,2 +315,3 @@ * @memberof @node-red/runtime_projects | ||
abortMerge: function(opts) { | ||
runtime.log.audit({event: "projects.merge.abort",id:opts.id}, opts.req); | ||
return runtime.storage.projects.abortMerge(opts.user, opts.id); | ||
@@ -301,2 +327,3 @@ }, | ||
* @param {String} opts.resolutions - how to resolve the merge conflict | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -306,2 +333,3 @@ * @memberof @node-red/runtime_projects | ||
resolveMerge: function(opts) { | ||
runtime.log.audit({event: "projects.merge.resolve",id:opts.id, file:opts.path}, opts.req); | ||
return runtime.storage.projects.resolveMerge(opts.user, opts.id, opts.path, opts.resolution); | ||
@@ -315,2 +343,3 @@ }, | ||
* @param {String} opts.id - the id of the project | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the file listing | ||
@@ -330,2 +359,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String} opts.tree - the version control tree to use | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String>} - the content of the file | ||
@@ -344,2 +374,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String|Array} opts.path - the path of the file, or an array of paths | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -349,2 +380,3 @@ * @memberof @node-red/runtime_projects | ||
stageFile: function(opts) { | ||
runtime.log.audit({event: "projects.file.stage",id:opts.id, file:opts.path}, opts.req); | ||
return runtime.storage.projects.stageFile(opts.user, opts.id, opts.path); | ||
@@ -359,2 +391,3 @@ }, | ||
* @param {String} opts.path - the path of the file. If not set, all staged files are unstaged | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -364,2 +397,3 @@ * @memberof @node-red/runtime_projects | ||
unstageFile: function(opts) { | ||
runtime.log.audit({event: "projects.file.unstage",id:opts.id, file:opts.path}, opts.req); | ||
return runtime.storage.projects.unstageFile(opts.user, opts.id, opts.path); | ||
@@ -374,2 +408,3 @@ }, | ||
* @param {String} opts.path - the path of the file | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -379,2 +414,3 @@ * @memberof @node-red/runtime_projects | ||
revertFile: function(opts) { | ||
runtime.log.audit({event: "projects.file.revert",id:opts.id, file:opts.path}, opts.req); | ||
return runtime.storage.projects.revertFile(opts.user, opts.id,opts.path) | ||
@@ -390,2 +426,3 @@ }, | ||
* @param {String} opts.type - the type of diff | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the requested diff | ||
@@ -403,2 +440,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String} opts.id - the id of the project | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - a list of project remotes | ||
@@ -420,2 +458,3 @@ * @memberof @node-red/runtime_projects | ||
* @param {String} opts.remote.url - the url of the remote | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -425,2 +464,3 @@ * @memberof @node-red/runtime_projects | ||
addRemote: function(opts) { | ||
runtime.log.audit({event: "projects.remote.add",id:opts.id, remote:opts.remote.name}, opts.req); | ||
return runtime.storage.projects.addRemote(opts.user, opts.id, opts.remote) | ||
@@ -435,2 +475,3 @@ }, | ||
* @param {String} opts.remote - the name of the remote | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -440,2 +481,3 @@ * @memberof @node-red/runtime_projects | ||
removeRemote: function(opts) { | ||
runtime.log.audit({event: "projects.remote.delete",id:opts.id, remote:opts.remote}, opts.req); | ||
return runtime.storage.projects.removeRemote(opts.user, opts.id, opts.remote); | ||
@@ -451,2 +493,3 @@ }, | ||
* @param {String} opts.remote.name - the name of the remote | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -456,2 +499,3 @@ * @memberof @node-red/runtime_projects | ||
updateRemote: function(opts) { | ||
runtime.log.audit({event: "projects.remote.update",id:opts.id, remote:opts.remote.name}, opts.req); | ||
return runtime.storage.projects.updateRemote(opts.user, opts.id, opts.remote.name, opts.remote) | ||
@@ -464,2 +508,6 @@ }, | ||
* @param {User} opts.user - the user calling the api | ||
* @param {String} opts.remote - the remote to pull | ||
* @param {Boolean} opts.track - whether to track this remote | ||
* @param {Boolean} opts.allowUnrelatedHistories - | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -469,2 +517,3 @@ * @memberof @node-red/runtime_projects | ||
pull: function(opts) { | ||
runtime.log.audit({event: "projects.pull",id:opts.id, remote: opts.remote, track:opts.track}, opts.req); | ||
return runtime.storage.projects.pull(opts.user, opts.id, opts.remote, opts.track, opts.allowUnrelatedHistories); | ||
@@ -480,2 +529,3 @@ }, | ||
* @param {String} opts.track - whether to set the remote as the upstream | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - resolves when complete | ||
@@ -485,2 +535,3 @@ * @memberof @node-red/runtime_projects | ||
push: function(opts) { | ||
runtime.log.audit({event: "projects.push",id:opts.id, remote: opts.remote, track:opts.track}, opts.req); | ||
return runtime.storage.projects.push(opts.user, opts.id, opts.remote, opts.track); | ||
@@ -487,0 +538,0 @@ } |
@@ -63,2 +63,3 @@ /** | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the runtime settings | ||
@@ -129,2 +130,3 @@ * @memberof @node-red/runtime_settings | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the user settings | ||
@@ -148,2 +150,3 @@ * @memberof @node-red/runtime_settings | ||
* @param {Object} opts.settings - the updates to the user settings | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the user settings | ||
@@ -164,6 +167,6 @@ * @memberof @node-red/runtime_settings | ||
runtime.settings.setUserSettings(username, currentSettings).then(function() { | ||
runtime.log.audit({event: "settings.update",username:username}); | ||
runtime.log.audit({event: "settings.update",username:username}, opts.req); | ||
return resolve(); | ||
}).catch(function(err) { | ||
runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -174,3 +177,3 @@ return reject(err); | ||
runtime.log.warn(runtime.log._("settings.user-not-available",{message:runtime.log._("settings.not-available")})); | ||
runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}); | ||
runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}, opts.req); | ||
err.status = 400; | ||
@@ -186,2 +189,3 @@ return reject(err); | ||
* @param {User} opts.user - the user calling the api | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<Object>} - the user's ssh keys | ||
@@ -207,2 +211,3 @@ * @memberof @node-red/runtime_settings | ||
* @param {User} opts.id - the id of the key to return | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String>} - the user's ssh public key | ||
@@ -239,2 +244,3 @@ * @memberof @node-red/runtime_settings | ||
* @param {User} opts.size - (optional) the size of the key. Default: 2048 | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise<String>} - the id of the generated key | ||
@@ -260,2 +266,3 @@ * @memberof @node-red/runtime_settings | ||
* @param {User} opts.id - the id of the key to delete | ||
* @param {Object} opts.req - the request to log (optional) | ||
* @return {Promise} - resolves when deleted | ||
@@ -262,0 +269,0 @@ * @memberof @node-red/runtime_settings |
@@ -132,3 +132,3 @@ /*! | ||
log.error("*****************************************************************"); | ||
log.error("* "+log._("runtime.unsupported_version",{component:"Node.js",version:process.version,requires: ">=4"})+" *"); | ||
log.error("* "+log._("runtime.unsupported_version",{component:"Node.js",version:process.version,requires: ">=8.9.0"})+" *"); | ||
log.error("*****************************************************************"); | ||
@@ -135,0 +135,0 @@ events.emit("runtime-event",{id:"runtime-unsupported-version",payload:{type:"error",text:"notification.errors.unsupportedVersion"},retain:true}); |
@@ -26,3 +26,3 @@ /** | ||
function getEntry(type,path) { | ||
var examples = runtime.nodes.getNodeExampleFlows(); | ||
var examples = runtime.nodes.getNodeExampleFlows()||{}; | ||
var result = []; | ||
@@ -29,0 +29,0 @@ if (path === "") { |
@@ -237,3 +237,3 @@ /** | ||
} | ||
value[0] = undefined; | ||
values[0] = undefined; | ||
} | ||
@@ -250,3 +250,3 @@ } | ||
} | ||
value[i] = undefined; | ||
values[i] = undefined; | ||
} | ||
@@ -253,0 +253,0 @@ } |
@@ -140,2 +140,12 @@ /** | ||
function writeFileAtomic(storagePath, content) { | ||
// To protect against file corruption, write to a tmp file first and then | ||
// rename to the destination file | ||
let finalFile = storagePath + ".json"; | ||
let tmpFile = finalFile + "."+Date.now()+".tmp"; | ||
return fs.outputFile(tmpFile, content, "utf8").then(function() { | ||
return fs.rename(tmpFile,finalFile); | ||
}) | ||
} | ||
function LocalFileSystem(config){ | ||
@@ -206,3 +216,3 @@ this.config = config; | ||
log.debug("Flushing localfilesystem context scope "+scope); | ||
promises.push(fs.outputFile(storagePath + ".json", stringifiedContext.json, "utf8")); | ||
promises.push(writeFileAtomic(storagePath, stringifiedContext.json)) | ||
}); | ||
@@ -324,3 +334,3 @@ delete self._pendingWriteTimeout; | ||
} | ||
return fs.outputFile(storagePath + ".json", stringifiedContext.json, "utf8"); | ||
return writeFileAtomic(storagePath, stringifiedContext.json); | ||
}).then(function(){ | ||
@@ -327,0 +337,0 @@ if(typeof callback === "function"){ |
@@ -26,2 +26,3 @@ /** | ||
var nodeCloseTimeout = 15000; | ||
var asyncMessageDelivery = true; | ||
@@ -129,2 +130,3 @@ /** | ||
this.statusNodes = []; | ||
this.completeNodeMap = {}; | ||
@@ -137,25 +139,35 @@ var configNodes = Object.keys(this.flow.configs); | ||
if (!this.activeNodes[id]) { | ||
var readyToCreate = true; | ||
// This node doesn't exist. | ||
// Check it doesn't reference another non-existent config node | ||
for (var prop in node) { | ||
if (node.hasOwnProperty(prop) && prop !== 'id' && prop !== 'wires' && prop !== '_users' && this.flow.configs[node[prop]]) { | ||
if (!this.activeNodes[node[prop]]) { | ||
// References a non-existent config node | ||
// Add it to the back of the list to try again later | ||
configNodes.push(id); | ||
configNodeAttempts[id] = (configNodeAttempts[id]||0)+1; | ||
if (configNodeAttempts[id] === 100) { | ||
throw new Error("Circular config node dependency detected: "+id); | ||
if (node.d !== true) { | ||
var readyToCreate = true; | ||
// This node doesn't exist. | ||
// Check it doesn't reference another non-existent config node | ||
for (var prop in node) { | ||
if (node.hasOwnProperty(prop) && | ||
prop !== 'id' && | ||
prop !== 'wires' && | ||
prop !== '_users' && | ||
this.flow.configs[node[prop]] && | ||
this.flow.configs[node[prop]].d !== true | ||
) { | ||
if (!this.activeNodes[node[prop]]) { | ||
// References a non-existent config node | ||
// Add it to the back of the list to try again later | ||
configNodes.push(id); | ||
configNodeAttempts[id] = (configNodeAttempts[id]||0)+1; | ||
if (configNodeAttempts[id] === 100) { | ||
throw new Error("Circular config node dependency detected: "+id); | ||
} | ||
readyToCreate = false; | ||
break; | ||
} | ||
readyToCreate = false; | ||
break; | ||
} | ||
} | ||
} | ||
if (readyToCreate) { | ||
newNode = flowUtil.createNode(this,node); | ||
if (newNode) { | ||
this.activeNodes[id] = newNode; | ||
if (readyToCreate) { | ||
newNode = flowUtil.createNode(this,node); | ||
if (newNode) { | ||
this.activeNodes[id] = newNode; | ||
} | ||
} | ||
} else { | ||
this.debug("not starting disabled config node : "+id); | ||
} | ||
@@ -177,35 +189,39 @@ } | ||
node = this.flow.nodes[id]; | ||
if (!node.subflow) { | ||
if (!this.activeNodes[id]) { | ||
newNode = flowUtil.createNode(this,node); | ||
if (newNode) { | ||
this.activeNodes[id] = newNode; | ||
if (node.d !== true) { | ||
if (!node.subflow) { | ||
if (!this.activeNodes[id]) { | ||
newNode = flowUtil.createNode(this,node); | ||
if (newNode) { | ||
this.activeNodes[id] = newNode; | ||
} | ||
} | ||
} | ||
} else { | ||
if (!this.subflowInstanceNodes[id]) { | ||
try { | ||
var subflowDefinition = this.flow.subflows[node.subflow]||this.global.subflows[node.subflow] | ||
// console.log("NEED TO CREATE A SUBFLOW",id,node.subflow); | ||
this.subflowInstanceNodes[id] = true; | ||
var subflow = Subflow.create( | ||
this, | ||
this.global, | ||
subflowDefinition, | ||
node | ||
); | ||
this.subflowInstanceNodes[id] = subflow; | ||
subflow.start(); | ||
this.activeNodes[id] = subflow.node; | ||
} else { | ||
if (!this.subflowInstanceNodes[id]) { | ||
try { | ||
var subflowDefinition = this.flow.subflows[node.subflow]||this.global.subflows[node.subflow] | ||
// console.log("NEED TO CREATE A SUBFLOW",id,node.subflow); | ||
this.subflowInstanceNodes[id] = true; | ||
var subflow = Subflow.create( | ||
this, | ||
this.global, | ||
subflowDefinition, | ||
node | ||
); | ||
this.subflowInstanceNodes[id] = subflow; | ||
subflow.start(); | ||
this.activeNodes[id] = subflow.node; | ||
// this.subflowInstanceNodes[id] = nodes.map(function(n) { return n.id}); | ||
// for (var i=0;i<nodes.length;i++) { | ||
// if (nodes[i]) { | ||
// this.activeNodes[nodes[i].id] = nodes[i]; | ||
// } | ||
// } | ||
} catch(err) { | ||
console.log(err.stack) | ||
// this.subflowInstanceNodes[id] = nodes.map(function(n) { return n.id}); | ||
// for (var i=0;i<nodes.length;i++) { | ||
// if (nodes[i]) { | ||
// this.activeNodes[nodes[i].id] = nodes[i]; | ||
// } | ||
// } | ||
} catch(err) { | ||
console.log(err.stack) | ||
} | ||
} | ||
} | ||
} else { | ||
this.debug("not starting disabled node : "+id); | ||
} | ||
@@ -221,3 +237,3 @@ } | ||
} | ||
// Build the map of catch/status nodes. | ||
// Build the map of catch/status/complete nodes. | ||
for (id in this.activeNodes) { | ||
@@ -231,2 +247,9 @@ if (this.activeNodes.hasOwnProperty(id)) { | ||
this.statusNodes.push(node); | ||
} else if (node.type === "complete") { | ||
if (node.scope) { | ||
node.scope.forEach(id => { | ||
this.completeNodeMap[id] = this.completeNodeMap[id] || []; | ||
this.completeNodeMap[id].push(node); | ||
}) | ||
} | ||
} | ||
@@ -286,3 +309,3 @@ } | ||
(function(subflow) { | ||
promises.push(stopNode(node,false).then(() => { subflow.stop() })); | ||
promises.push(stopNode(node,false).then(() => subflow.stop())); | ||
})(this.subflowInstanceNodes[stopList[i]]); | ||
@@ -512,2 +535,16 @@ } catch(err) { | ||
handleComplete(node,msg) { | ||
if (this.completeNodeMap[node.id]) { | ||
let toSend = msg; | ||
this.completeNodeMap[node.id].forEach((completeNode,index) => { | ||
toSend = redUtil.cloneMessage(msg); | ||
completeNode.receive(toSend); | ||
}) | ||
} | ||
} | ||
get asyncMessageDelivery() { | ||
return asyncMessageDelivery | ||
} | ||
dump() { | ||
@@ -559,2 +596,3 @@ console.log("==================") | ||
nodeCloseTimeout = runtime.settings.nodeCloseTimeout || 15000; | ||
asyncMessageDelivery = !runtime.settings.runtimeSyncDelivery | ||
Log = runtime.log; | ||
@@ -561,0 +599,0 @@ Subflow = require("./Subflow"); |
@@ -732,4 +732,8 @@ /** | ||
disableFlow:null, | ||
enableFlow:null | ||
enableFlow:null, | ||
isDeliveryModeAsync: function() { | ||
// If settings is null, this is likely being run by unit tests | ||
return !settings || !settings.runtimeSyncDelivery | ||
} | ||
}; |
@@ -27,4 +27,52 @@ /** | ||
/** | ||
* Create deep copy of object | ||
*/ | ||
function deepCopy(obj) { | ||
return JSON.parse(JSON.stringify(obj)); | ||
} | ||
/** | ||
* Evaluate Input Value | ||
*/ | ||
function evaluateInputValue(value, type, node) { | ||
if (type === "bool") { | ||
return (value === "true") || (value === true); | ||
} | ||
return redUtil.evaluateNodeProperty(value, type, node, null, null); | ||
} | ||
/** | ||
* Compose information object for env var | ||
*/ | ||
function composeInfo(info, val) { | ||
var result = { | ||
name: info.name, | ||
type: info.type, | ||
value: val, | ||
}; | ||
if (info.ui) { | ||
var ui = info.ui; | ||
result.ui = { | ||
hasUI: ui.hasUI, | ||
icon: ui.icon, | ||
labels: ui.labels, | ||
type: ui.type | ||
}; | ||
var retUI = result.ui; | ||
if (ui.type === "input") { | ||
retUI.inputTypes = ui.inputTypes; | ||
} | ||
if (ui.type === "select") { | ||
retUI.menu = ui.menu; | ||
} | ||
if (ui.type === "spinner") { | ||
retUI.spinner = ui.spinner; | ||
} | ||
} | ||
return result; | ||
} | ||
/** | ||
* This class represents a subflow - which is handled as a special type of Flow | ||
@@ -99,6 +147,15 @@ */ | ||
if (this.subflowDef.env) { | ||
this.subflowDef.env.forEach(e => { env[e.name] = e; }); | ||
this.subflowDef.env.forEach(e => { | ||
env[e.name] = e; | ||
}); | ||
} | ||
if (this.subflowInstance.env) { | ||
this.subflowInstance.env.forEach(e => { env[e.name] = e; }); | ||
this.subflowInstance.env.forEach(e => { | ||
var old = env[e.name]; | ||
var ui = old ? old.ui : null; | ||
env[e.name] = e; | ||
if (ui) { | ||
env[e.name].ui = ui; | ||
} | ||
}); | ||
} | ||
@@ -262,2 +319,3 @@ this.env = env; | ||
/** | ||
@@ -272,4 +330,12 @@ * Get environment variable of subflow | ||
var env = this.env; | ||
if (env && env.hasOwnProperty(name)) { | ||
var val = env[name]; | ||
var is_info = name.endsWith("_info"); | ||
var is_type = name.endsWith("_type"); | ||
var ename = (is_info || is_type) ? name.substring(0, name.length -5) : name; // 5 = length of "_info"/"_type" | ||
if (env && env.hasOwnProperty(ename)) { | ||
var val = env[ename]; | ||
if (is_type) { | ||
return val ? val.type : undefined; | ||
} | ||
// If this is an env type property we need to be careful not | ||
@@ -283,7 +349,11 @@ // to get into lookup loops. | ||
let value = val.value; | ||
if (val.type === 'env') { | ||
var type = val.type; | ||
if (type === 'env') { | ||
value = value.replace(new RegExp("\\${"+name+"}","g"),"${$parent."+name+"}"); | ||
} | ||
try { | ||
var ret = redUtil.evaluateNodeProperty(value, val.type, this.node, null, null); | ||
var ret = evaluateInputValue(value, type, this.node); | ||
if (is_info) { | ||
return composeInfo(val, ret); | ||
} | ||
return ret; | ||
@@ -417,3 +487,7 @@ } | ||
for (k=0;k<wires.length;k++) { | ||
outputs[j][k] = nodeMap[outputs[j][k]].id | ||
if (nodeMap[outputs[j][k]]) { | ||
outputs[j][k] = nodeMap[outputs[j][k]].id | ||
} else { | ||
outputs[j][k] = null; | ||
} | ||
} | ||
@@ -430,3 +504,2 @@ } | ||
if (nodeMap[node[prop]]) { | ||
//console.log("Mapped",node.type,node.id,prop,nodeMap[node[prop]].id); | ||
node[prop] = nodeMap[node[prop]].id; | ||
@@ -433,0 +506,0 @@ } |
@@ -21,6 +21,16 @@ /** | ||
var redUtil = require("@node-red/util").util; | ||
var Log = require("@node-red/util").log; // TODO: separate module | ||
var Log = require("@node-red/util").log; | ||
var context = require("./context"); | ||
var flows = require("./flows"); | ||
const NOOP_SEND = function() {} | ||
/** | ||
* The Node object is the heart of a Node-RED flow. It is the object that all | ||
* nodes extend. | ||
* | ||
* The Node object itself inherits from EventEmitter, although it provides | ||
* custom implementations of some of the EE functions in order to handle | ||
* `input` and `close` events properly. | ||
*/ | ||
function Node(n) { | ||
@@ -31,2 +41,4 @@ this.id = n.id; | ||
this._closeCallbacks = []; | ||
this._inputCallback = null; | ||
this._inputCallbacks = null; | ||
@@ -48,3 +60,7 @@ if (n.name) { | ||
Object.defineProperty(this,'_flow', {value: n._flow, enumerable: false, writable: true }) | ||
this._asyncDelivery = n._flow.asyncMessageDelivery; | ||
} | ||
if (this._asyncDelivery === undefined) { | ||
this._asyncDelivery = true; | ||
} | ||
this.updateWires(n.wires); | ||
@@ -55,2 +71,17 @@ } | ||
/** | ||
* Update the wiring configuration for this node. | ||
* | ||
* We try to optimise the message handling path. To do this there are three | ||
* cases to consider: | ||
* 1. this node is wired to nothing. In this case we replace node.send with a | ||
* NO-OP function. | ||
* 2. this node is wired to one other node. In this case we set `this._wire` | ||
* as a reference to the node it is wired to. This means we avoid unnecessary | ||
* iterations over what would otherwise be a 1-element array. | ||
* 3. this node is wired to multiple things. The normal node.send processing of | ||
* this.wires applies. | ||
* | ||
* @param {array} wires the new wiring configuration | ||
*/ | ||
Node.prototype.updateWires = function(wires) { | ||
@@ -68,3 +99,3 @@ //console.log("UPDATE",this.id); | ||
// With nothing wired to the node, no-op send | ||
this.send = function(msg) {} | ||
this.send = NOOP_SEND | ||
} else { | ||
@@ -80,2 +111,9 @@ this.send = Node.prototype.send; | ||
} | ||
/** | ||
* Get the context object for this node. | ||
* | ||
* As most nodes do not use context, this is a lazy function that will only | ||
* create a context instance for the node if it is needed. | ||
* @return {object} the context object | ||
*/ | ||
Node.prototype.context = function() { | ||
@@ -88,4 +126,28 @@ if (!this._context) { | ||
/** | ||
* Handle the complete event for a message | ||
* | ||
* @param {object} msg The message that has completed | ||
* @param {error} error (optional) an error hit whilst handling the message | ||
*/ | ||
Node.prototype._complete = function(msg,error) { | ||
if (error) { | ||
// For now, delegate this to this.error | ||
// But at some point, the timeout handling will need to know about | ||
// this as well. | ||
this.error(error,msg); | ||
} else { | ||
this._flow.handleComplete(this,msg); | ||
} | ||
} | ||
/** | ||
* An internal reference to the original EventEmitter.on() function | ||
*/ | ||
Node.prototype._on = Node.prototype.on; | ||
/** | ||
* Register a callback function for a named event. | ||
* 'close' and 'input' events are handled locally, other events defer to EventEmitter.on() | ||
*/ | ||
Node.prototype.on = function(event, callback) { | ||
@@ -95,2 +157,11 @@ var node = this; | ||
this._closeCallbacks.push(callback); | ||
} else if (event === "input") { | ||
if (this._inputCallback) { | ||
this._inputCallbacks = [this._inputCallback, callback]; | ||
this._inputCallback = null; | ||
} else if (this._inputCallbacks) { | ||
this._inputCallbacks.push(callback); | ||
} else { | ||
this._inputCallback = callback; | ||
} | ||
} else { | ||
@@ -101,2 +172,131 @@ this._on(event, callback); | ||
/** | ||
* An internal reference to the original EventEmitter.emit() function | ||
*/ | ||
Node.prototype._emit = Node.prototype.emit; | ||
/** | ||
* Emit an event to all registered listeners. | ||
*/ | ||
Node.prototype.emit = function(event,arg) { | ||
var node = this; | ||
if (event === "input") { | ||
// When Pluggable Message Routing arrives, this will be called from | ||
// that and will already be sync/async depending on the router. | ||
if (this._asyncDelivery) { | ||
setImmediate(function() { | ||
node._emitInput(arg); | ||
}); | ||
} else { | ||
this._emitInput(arg); | ||
} | ||
} else { | ||
this._emit(event,arg); | ||
} | ||
} | ||
/** | ||
* Handle the 'input' event. | ||
* | ||
* This will call all registered handlers for the 'input' event. | ||
*/ | ||
Node.prototype._emitInput = function(arg) { | ||
var node = this; | ||
if (node._inputCallback) { | ||
// Just one callback registered. | ||
try { | ||
node._inputCallback( | ||
arg, | ||
function() { node.send.apply(node,arguments) }, | ||
function(err) { node._complete(arg,err); } | ||
); | ||
} catch(err) { | ||
node.error(err,arg); | ||
} | ||
} else if (node._inputCallbacks) { | ||
// Multiple callbacks registered. Call each one, tracking eventual completion | ||
var c = node._inputCallbacks.length; | ||
for (var i=0;i<c;i++) { | ||
var cb = node._inputCallbacks[i]; | ||
if (cb.length === 2) { | ||
c++; | ||
} | ||
try { | ||
node._inputCallbacks[i]( | ||
arg, | ||
function() { node.send.apply(node,arguments) }, | ||
function(err) { | ||
c--; | ||
if (c === 0) { | ||
node._complete(arg,err); | ||
} | ||
} | ||
); | ||
} catch(err) { | ||
node.error(err,msg); | ||
} | ||
} | ||
} | ||
} | ||
/** | ||
* An internal reference to the original EventEmitter.removeListener() function | ||
*/ | ||
Node.prototype._removeListener = Node.prototype.removeListener; | ||
/** | ||
* Remove a listener for an event | ||
*/ | ||
Node.prototype.removeListener = function(name, listener) { | ||
var index; | ||
if (name === "input") { | ||
if (this._inputCallback && this._inputCallback === listener) { | ||
// Removing the only callback | ||
this._inputCallback = null; | ||
} else if (this._inputCallbacks) { | ||
// Removing one of many callbacks | ||
index = this._inputCallbacks.indexOf(listener); | ||
if (index > -1) { | ||
this._inputCallbacks.splice(index,1); | ||
} | ||
// Check if we can optimise back to a single callback | ||
if (this._inputCallbacks.length === 1) { | ||
this._inputCallback = this._inputCallbacks[0]; | ||
this._inputCallbacks = null; | ||
} | ||
} | ||
} else if (name === "close") { | ||
index = this._closeCallbacks.indexOf(listener); | ||
if (index > -1) { | ||
this._closeCallbacks.splice(index,1); | ||
} | ||
} else { | ||
this._removeListener(name, listener); | ||
} | ||
} | ||
/** | ||
* An internal reference to the original EventEmitter.removeAllListeners() function | ||
*/ | ||
Node.prototype._removeAllListeners = Node.prototype.removeAllListeners; | ||
/** | ||
* Remove all listeners for an event | ||
*/ | ||
Node.prototype.removeAllListeners = function(name) { | ||
if (name === "input") { | ||
this._inputCallback = null; | ||
this._inputCallbacks = null; | ||
} else if (name === "close") { | ||
this._closeCallbacks = []; | ||
} else { | ||
this._removeAllListeners(name); | ||
} | ||
} | ||
/** | ||
* Called when the node is being stopped | ||
* @param {boolean} removed Whether the node has been removed, or just being stopped | ||
* @return {Promise} resolves when the node has closed | ||
*/ | ||
Node.prototype.close = function(removed) { | ||
@@ -106,5 +306,7 @@ //console.log(this.type,this.id,removed); | ||
var node = this; | ||
// Call all registered close callbacks. | ||
for (var i=0;i<this._closeCallbacks.length;i++) { | ||
var callback = this._closeCallbacks[i]; | ||
if (callback.length > 0) { | ||
// The callback takes a 'done' callback and (maybe) the removed flag | ||
promises.push( | ||
@@ -115,2 +317,3 @@ new Promise((resolve) => { | ||
if (callback.length === 2) { | ||
// The listener expects the removed flag | ||
args.push(!!removed); | ||
@@ -130,2 +333,3 @@ } | ||
} else { | ||
// No done callback so handle synchronously | ||
try { | ||
@@ -153,2 +357,8 @@ callback.call(node); | ||
/** | ||
* Send a message to the nodes wired. | ||
* | ||
* | ||
* @param {object} msg A message or array of messages to send | ||
*/ | ||
Node.prototype.send = function(msg) { | ||
@@ -241,2 +451,8 @@ var msgSent = false; | ||
/** | ||
* Receive a message. | ||
* | ||
* This will emit the `input` event with the provided message. | ||
* As of 1.0, this will return *before* any 'input' callback handler is invoked. | ||
*/ | ||
Node.prototype.receive = function(msg) { | ||
@@ -250,7 +466,3 @@ if (!msg) { | ||
this.metric("receive",msg); | ||
try { | ||
this.emit("input", msg); | ||
} catch(err) { | ||
this.error(err,msg); | ||
} | ||
this.emit("input",msg); | ||
}; | ||
@@ -276,3 +488,5 @@ | ||
} | ||
/** | ||
* Log an INFO level message | ||
*/ | ||
Node.prototype.log = function(msg) { | ||
@@ -282,2 +496,5 @@ log_helper(this, Log.INFO, msg); | ||
/** | ||
* Log a WARN level message | ||
*/ | ||
Node.prototype.warn = function(msg) { | ||
@@ -287,2 +504,5 @@ log_helper(this, Log.WARN, msg); | ||
/** | ||
* Log an ERROR level message | ||
*/ | ||
Node.prototype.error = function(logMessage,msg) { | ||
@@ -293,3 +513,3 @@ if (typeof logMessage != 'boolean') { | ||
var handled = false; | ||
if (msg) { | ||
if (msg && typeof msg === 'object') { | ||
handled = this._flow.handleError(this,logMessage,msg); | ||
@@ -302,2 +522,5 @@ } | ||
/** | ||
* Log an DEBUG level message | ||
*/ | ||
Node.prototype.debug = function(msg) { | ||
@@ -307,2 +530,5 @@ log_helper(this, Log.DEBUG, msg); | ||
/** | ||
* Log an TRACE level message | ||
*/ | ||
Node.prototype.trace = function(msg) { | ||
@@ -313,2 +539,3 @@ log_helper(this, Log.TRACE, msg); | ||
/** | ||
* Log a metric event. | ||
* If called with no args, returns whether metric collection is enabled | ||
@@ -330,2 +557,4 @@ */ | ||
/** | ||
* Set the node's status object | ||
* | ||
* status: { fill:"red|green", shape:"dot|ring", text:"blah" } | ||
@@ -332,0 +561,0 @@ * or |
@@ -54,2 +54,8 @@ /** | ||
}); | ||
child.on('error', function(err) { | ||
if (/ENOENT/.test(err.toString())) { | ||
err.code = "command_not_found"; | ||
} | ||
reject(err); | ||
}); | ||
}); | ||
@@ -56,0 +62,0 @@ } |
{ | ||
"name": "@node-red/runtime", | ||
"version": "1.0.0-beta.2", | ||
"version": "1.0.0-beta.3", | ||
"license": "Apache-2.0", | ||
@@ -19,7 +19,7 @@ "main": "./lib/index.js", | ||
"dependencies": { | ||
"@node-red/registry": "1.0.0-beta.2", | ||
"@node-red/util": "1.0.0-beta.2", | ||
"@node-red/registry": "1.0.0-beta.3", | ||
"@node-red/util": "1.0.0-beta.3", | ||
"clone": "2.1.2", | ||
"express": "4.17.0", | ||
"fs-extra": "8.0.1", | ||
"express": "4.17.1", | ||
"fs-extra": "8.1.0", | ||
"json-stringify-safe": "5.0.1", | ||
@@ -26,0 +26,0 @@ "when": "3.7.8" |
461032
11152
+ Added@node-red/registry@1.0.0-beta.3(transitive)
+ Added@node-red/util@1.0.0-beta.3(transitive)
+ Addedexpress@4.17.1(transitive)
+ Addedfs-extra@8.1.0(transitive)
+ Addedjsonata@1.6.5(transitive)
+ Addedsemver@6.3.0(transitive)
+ Addeduglify-js@3.6.0(transitive)
- Removed@node-red/registry@1.0.0-beta.2(transitive)
- Removed@node-red/util@1.0.0-beta.2(transitive)
- Removedexpress@4.17.0(transitive)
- Removedfs-extra@8.0.1(transitive)
- Removedjsonata@1.6.4(transitive)
- Removedsemver@6.0.0(transitive)
- Removeduglify-js@3.5.15(transitive)
Updated@node-red/util@1.0.0-beta.3
Updatedexpress@4.17.1
Updatedfs-extra@8.1.0