diff --git a/API.md b/API.md index f349ea8fe..692a34723 100644 --- a/API.md +++ b/API.md @@ -10,6 +10,6 @@ Module | Description [@node-red/editor-api](@node-red_editor-api.html) | an Express application that serves the Node-RED editor and provides the Admin HTTP API [@node-red/runtime](@node-red_runtime.html) | the core runtime of Node-RED [@node-red/util](@node-red_util.html) | common utilities for the Node-RED runtime and editor modules -@node-red/registry | the internal node registry +[@node-red/registry](@node-red_registry.html) | the internal node registry @node-red/nodes | the default set of core nodes @node-red/editor-client | the client-side resources of the Node-RED editor application diff --git a/Gruntfile.js b/Gruntfile.js index b01763ab0..2bdc2e3aa 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -461,7 +461,8 @@ module.exports = function(grunt) { 'packages/node_modules/@node-red/runtime/lib/hooks.js', 'packages/node_modules/@node-red/util/**/*.js', 'packages/node_modules/@node-red/editor-api/lib/index.js', - 'packages/node_modules/@node-red/editor-api/lib/auth/index.js' + 'packages/node_modules/@node-red/editor-api/lib/auth/index.js', + 'packages/node_modules/@node-red/registry/lib/index.js' ], options: { destination: 'docs', diff --git a/package.json b/package.json index 3ff26d859..b1981d8cc 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,6 @@ "semver": "6.3.0", "tar": "6.0.5", "uglify-js": "3.11.6", - "when": "3.7.8", "ws": "6.2.1", "xml2js": "0.4.23" }, diff --git a/packages/node_modules/@node-red/editor-api/lib/editor/library.js b/packages/node_modules/@node-red/editor-api/lib/editor/library.js index 47a41bb7b..89b92fd11 100644 --- a/packages/node_modules/@node-red/editor-api/lib/editor/library.js +++ b/packages/node_modules/@node-red/editor-api/lib/editor/library.js @@ -17,7 +17,6 @@ var apiUtils = require("../util"); var fs = require('fs'); var fspath = require('path'); -var when = require('when'); var runtimeAPI; diff --git a/packages/node_modules/@node-red/editor-api/lib/index.js b/packages/node_modules/@node-red/editor-api/lib/index.js index 457b99cc9..972e8daa6 100644 --- a/packages/node_modules/@node-red/editor-api/lib/index.js +++ b/packages/node_modules/@node-red/editor-api/lib/index.js @@ -28,7 +28,6 @@ var express = require("express"); var bodyParser = require("body-parser"); var util = require('util'); var passport = require('passport'); -var when = require('when'); var cors = require('cors'); var auth = require("./auth"); @@ -111,11 +110,9 @@ function init(settings,_server,storage,runtimeAPI) { * @return {Promise} resolves when the application is ready to handle requests * @memberof @node-red/editor-api */ -function start() { +async function start() { if (editor) { return editor.start(); - } else { - return when.resolve(); } } @@ -124,11 +121,10 @@ function start() { * @return {Promise} resolves when the application is stopped * @memberof @node-red/editor-api */ -function stop() { +async function stop() { if (editor) { editor.stop(); } - return when.resolve(); } module.exports = { init: init, diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json index 6885aaabb..516532e37 100644 --- a/packages/node_modules/@node-red/editor-api/package.json +++ b/packages/node_modules/@node-red/editor-api/package.json @@ -32,7 +32,6 @@ "passport-http-bearer": "1.0.1", "passport-oauth2-client-password": "0.1.2", "passport": "0.4.1", - "when": "3.7.8", "ws": "6.2.1" }, "optionalDependencies": { diff --git a/packages/node_modules/@node-red/registry/lib/index.js b/packages/node_modules/@node-red/registry/lib/index.js index 2805534a2..3632f40cf 100644 --- a/packages/node_modules/@node-red/registry/lib/index.js +++ b/packages/node_modules/@node-red/registry/lib/index.js @@ -1,4 +1,4 @@ -/** +/*! * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,16 +29,27 @@ var loader = require("./loader"); var installer = require("./installer"); var library = require("./library"); -var settings; - +/** + * Initialise the registry with a reference to a runtime object + * @param {Object} runtime - a runtime object + * @memberof @node-red/registry + */ function init(runtime) { - settings = runtime.settings; - installer.init(runtime); + installer.init(runtime.settings); + // Loader requires the full runtime object because it initialises + // the util module it. The Util module is responsible for constructing the + // RED object passed to node modules when they are loaded. loader.init(runtime); - registry.init(settings,loader,runtime.events); + registry.init(runtime.settings,loader); library.init(); } +/** + * Triggers the intial discovery and loading of all Node-RED node modules. + * found on the node path. + * @return {Promise} - resolves when the registry has finised discovering node modules. + * @memberof @node-red/registry + */ function load() { registry.load(); return installer.checkPrereq().then(loader.load); @@ -66,34 +77,221 @@ module.exports = { init:init, load:load, clear: registry.clear, + + /** + * Register a node constructor function. + * + * @param {Object} nodeSet - the Node Set object the constructor is for + * @param {String} type - the node type + * @param {Function} constructor - the node constructor function + * @function + * @memberof @node-red/registry + */ registerType: registry.registerNodeConstructor, + /** + * Get a node constructor function. + * + * @param {String} type - the node type + * @return {Function} the node constructor function + * @function + * @memberof @node-red/registry + */ get: registry.getNodeConstructor, + + /** + * Get a node's set information. + * + * @param {String} type - the node type or set identifier + * @return {Object} the node set information + * @function + * @memberof @node-red/registry + */ getNodeInfo: registry.getNodeInfo, + + + /** + * Get a list of all nodes in the registry. + * + * @return {Object} the node list + * @function + * @memberof @node-red/registry + */ getNodeList: registry.getNodeList, + /** + * Get a modules's information. + * + * @param {String} type - the module identifier + * @return {Object} the module information + * @function + * @memberof @node-red/registry + */ getModuleInfo: registry.getModuleInfo, + + /** + * Get a list of all moduless in the registry. + * + * @return {Object} the module list + * @function + * @memberof @node-red/registry + */ getModuleList: registry.getModuleList, + /** + * Get the HTML configs for all nodes in the registry. + * + * @param {String} lang - the language to return, default `en-US` + * @return {String} the node configs + * @function + * @memberof @node-red/registry + */ getNodeConfigs: registry.getAllNodeConfigs, + + /** + * Get the HTML config for a single node set. + * + * @param {String} id - the node identifier + * @param {String} lang - the language to return, default `en-US` + * @return {String} the node config + * @function + * @memberof @node-red/registry + */ getNodeConfig: registry.getNodeConfig, + + /** + * Get the local path to a node's icon file. + * + * @param {String} module - the module that provides the icon + * @param {String} icon - the name of the icon + * @return {String} the local path to the icon + * @function + * @memberof @node-red/registry + */ getNodeIconPath: registry.getNodeIconPath, + + + /** + * Get the full list of all icons available. + * + * @return {String} the icon list + * @function + * @memberof @node-red/registry + */ getNodeIcons: registry.getNodeIcons, + /** + * Enables a node set, making it available for use. + * + * @param {String} type - the node type or set identifier + * @return {Promise} A promise that resolves when the node set has been enabled + * @throws if the identifier is not recognised or runtime settings are unavailable + * @function + * @memberof @node-red/registry + */ enableNode: enableNodeSet, + + /** + * Disables a node set, making it unavailable for use. + * + * @param {String} type - the node type or set identifier + * @return {Promise} A promise that resolves when the node set has been disabled + * @throws if the identifier is not recognised or runtime settings are unavailable + * @function + * @memberof @node-red/registry + */ disableNode: registry.disableNodeSet, + + /** + * Loads a new module into the registry. + * + * This will rescan the node module paths looking for this module. + * + * @param {String} module - the name of the module to add + * @return {Promise} A promise that resolves with the module information once it has been added + * @throws if the module has already been added or the runtime settings are unavailable + * @function + * @memberof @node-red/registry + */ addModule: addModule, + + /** + * Removes a module from the registry. + * + * @param {String} module - the name of the module to remove + * @return {Promise} A promise that resolves with the list of removed node sets + * @throws if the module is not found or the runtime settings are unavailable + * @function + * @memberof @node-red/registry + */ removeModule: registry.removeModule, + /** + * Installs a new node module using npm and then add to the registry + * + * @param {String|Buffer} module - the name of the module to install, or a Buffer containing a module tar file + * @param {String} version - the version of the module to install, default: `latest` + * @param {String} url - (optional) a url to install the module from + * @return {Promise} A promise that resolves with the module information once it has been installed + * @function + * @memberof @node-red/registry + */ installModule: installer.installModule, + + + /** + * Uninstalls a module using npm + * + * @param {String} module - the name of the module to uninstall + * @return {Promise} A promise that resolves when the module has been removed + * @function + * @memberof @node-red/registry + */ uninstallModule: installer.uninstallModule, + /** + * Update to internal list of available modules based on what has been actually + * loaded. + * + * The `autoInstallModules` runtime option means the runtime may try to install + * missing modules after the initial load is complete. If that flag is not set + * this function is used to remove the modules from the registry's saved list. + * @function + * @memberof @node-red/registry + */ cleanModuleList: registry.cleanModuleList, - paletteEditorEnabled: installer.paletteEditorEnabled, + /** + * Check if the regisrty is able to install/remove modules. + * + * This is based on whether it has found `npm` on the command-line. + * @return {Boolean} whether the installer is enabled + * + * @function + * @memberof @node-red/registry + */ + installerEnabled: installer.installerEnabled, + /** + * Get a list of all example flows provided by nodes in the registry. + * @return {Object} an object, indexed by module, listing all example flows + * + * @function + * @memberof @node-red/registry + */ getNodeExampleFlows: library.getExampleFlows, + + + /** + * Gets the full path to a node example + * @param {String} module - the name of the module providing the example + * @param {String} path - the relative path of the example + * @return {String} the full path to the example + * + * @function + * @memberof @node-red/registry + */ getNodeExampleFlowPath: library.getExampleFlowPath, deprecated: require("./deprecated") diff --git a/packages/node_modules/@node-red/registry/lib/installer.js b/packages/node_modules/@node-red/registry/lib/installer.js index 03f9eb11c..0c3359382 100644 --- a/packages/node_modules/@node-red/registry/lib/installer.js +++ b/packages/node_modules/@node-red/registry/lib/installer.js @@ -22,14 +22,10 @@ var tar = require("tar"); var registry = require("./registry"); var library = require("./library"); -var log; -var exec; - -var events; - +const {exec,log,events} = require("@node-red/util"); var child_process = require('child_process'); var npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'; -var paletteEditorEnabled = false; +var installerEnabled = false; var settings; const moduleRe = /^(@[^/@]+?[/])?[^/@]+?$/; @@ -37,11 +33,8 @@ const slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/; const pkgurlRe = /^(https?|git(|\+https?|\+ssh|\+file)):\/\//; const localtgzRe = /^([a-zA-Z]:|\/).+tgz$/; -function init(runtime) { - events = runtime.events; - settings = runtime.settings; - log = runtime.log; - exec = runtime.exec; +function init(_settings) { + settings = _settings; } var activePromise = Promise.resolve(); @@ -349,20 +342,20 @@ function checkPrereq() { settings.editorTheme.palette.editable === false ) { log.info(log._("server.palette-editor.disabled")); - paletteEditorEnabled = false; + installerEnabled = false; return Promise.resolve(); } else { return new Promise(resolve => { child_process.execFile(npmCommand,['-v'],function(err,stdout) { if (err) { log.info(log._("server.palette-editor.npm-not-found")); - paletteEditorEnabled = false; + installerEnabled = false; } else { if (parseInt(stdout.split(".")[0]) < 3) { log.info(log._("server.palette-editor.npm-too-old")); - paletteEditorEnabled = false; + installerEnabled = false; } else { - paletteEditorEnabled = true; + installerEnabled = true; } } resolve(); @@ -376,7 +369,7 @@ module.exports = { checkPrereq: checkPrereq, installModule: installModule, uninstallModule: uninstallModule, - paletteEditorEnabled: function() { - return paletteEditorEnabled + installerEnabled: function() { + return installerEnabled } } diff --git a/packages/node_modules/@node-red/registry/lib/library.js b/packages/node_modules/@node-red/registry/lib/library.js index a8ca8a775..90b0fda82 100644 --- a/packages/node_modules/@node-red/registry/lib/library.js +++ b/packages/node_modules/@node-red/registry/lib/library.js @@ -14,7 +14,7 @@ * limitations under the License. **/ -var fs = require('fs'); +var fs = require('fs-extra'); var fspath = require('path'); var runtime; @@ -22,38 +22,34 @@ var runtime; var exampleRoots = {}; var exampleFlows = null; -function getFlowsFromPath(path) { - return new Promise(function(resolve,reject) { - var result = {}; - fs.readdir(path,function(err,files) { - var promises = []; - var validFiles = []; - files.forEach(function(file) { - var fullPath = fspath.join(path,file); - var stats = fs.lstatSync(fullPath); - if (stats.isDirectory()) { - validFiles.push(file); - promises.push(getFlowsFromPath(fullPath)); - } else if (/\.json$/.test(file)){ - validFiles.push(file); - promises.push(Promise.resolve(file.split(".")[0])) - } - }) - var i=0; - Promise.all(promises).then(function(results) { - results.forEach(function(r) { - if (typeof r === 'string') { - result.f = result.f||[]; - result.f.push(r); - } else { - result.d = result.d||{}; - result.d[validFiles[i]] = r; - } - i++; - }) - resolve(result); - }) - }); +async function getFlowsFromPath(path) { + var result = {}; + var validFiles = []; + return fs.readdir(path).then(files => { + var promises = []; + files.forEach(function(file) { + var fullPath = fspath.join(path,file); + var stats = fs.lstatSync(fullPath); + if (stats.isDirectory()) { + validFiles.push(file); + promises.push(getFlowsFromPath(fullPath)); + } else if (/\.json$/.test(file)){ + validFiles.push(file); + promises.push(Promise.resolve(file.split(".")[0])) + } + }) + return Promise.all(promises) + }).then(results => { + results.forEach(function(r,i) { + if (typeof r === 'string') { + result.f = result.f||[]; + result.f.push(r); + } else { + result.d = result.d||{}; + result.d[validFiles[i]] = r; + } + }) + return result; }) } diff --git a/packages/node_modules/@node-red/registry/lib/loader.js b/packages/node_modules/@node-red/registry/lib/loader.js index 14e2a0b7e..18d202420 100644 --- a/packages/node_modules/@node-red/registry/lib/loader.js +++ b/packages/node_modules/@node-red/registry/lib/loader.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var when = require("when"); var fs = require("fs-extra"); var path = require("path"); var semver = require("semver"); @@ -23,15 +22,14 @@ var localfilesystem = require("./localfilesystem"); var registry = require("./registry"); var registryUtil = require("./util") var i18n = require("@node-red/util").i18n; +var log = require("@node-red/util").log; var settings; -var runtime; function init(_runtime) { - runtime = _runtime; - settings = runtime.settings; - localfilesystem.init(runtime); - registryUtil.init(runtime); + settings = _runtime.settings; + localfilesystem.init(settings); + registryUtil.init(_runtime); } function load(disableNodePathScan) { @@ -39,7 +37,7 @@ function load(disableNodePathScan) { // We should expose that as an option at some point, although the // performance gains are minimal. //return loadNodeFiles(registry.getModuleList()); - runtime.log.info(runtime.log._("server.loading")); + log.info(log._("server.loading")); var nodeFiles = localfilesystem.getNodeFiles(disableNodePathScan); return loadNodeFiles(nodeFiles); @@ -52,9 +50,9 @@ function loadNodeFiles(nodeFiles) { /* istanbul ignore else */ if (nodeFiles.hasOwnProperty(module)) { if (nodeFiles[module].redVersion && - !semver.satisfies(runtime.version().replace(/(\-[1-9A-Za-z-][0-9A-Za-z-\.]*)?(\+[0-9A-Za-z-\.]+)?$/,""), nodeFiles[module].redVersion)) { + !semver.satisfies((settings.version||"0.0.0").replace(/(\-[1-9A-Za-z-][0-9A-Za-z-\.]*)?(\+[0-9A-Za-z-\.]+)?$/,""), nodeFiles[module].redVersion)) { //TODO: log it - runtime.log.warn("["+module+"] "+runtime.log._("server.node-version-mismatch",{version:nodeFiles[module].redVersion})); + log.warn("["+module+"] "+log._("server.node-version-mismatch",{version:nodeFiles[module].redVersion})); nodeFiles[module].err = "version_mismatch"; continue; } @@ -92,7 +90,7 @@ function loadNodeFiles(nodeFiles) { nodeFiles[m].nodes[n] = nodeSet; nodes.push(nodeSet); } - })())); + })()).catch(err => {})); } catch(err) { // } @@ -101,7 +99,7 @@ function loadNodeFiles(nodeFiles) { } } } - return when.settle(promises).then(function(results) { + return Promise.all(promises).then(function(results) { for (var module in nodeFiles) { if (nodeFiles.hasOwnProperty(module)) { if (!nodeFiles[module].err) { @@ -293,13 +291,13 @@ function loadNodeSetList(nodes) { var promises = []; nodes.forEach(function(node) { if (!node.err) { - promises.push(loadNodeSet(node)); + promises.push(loadNodeSet(node).catch(err => {})); } else { promises.push(node); } }); - return when.settle(promises).then(function() { + return Promise.all(promises).then(function() { if (settings.available()) { return registry.saveNodeList(); } else { diff --git a/packages/node_modules/@node-red/registry/lib/localfilesystem.js b/packages/node_modules/@node-red/registry/lib/localfilesystem.js index 7233d1da3..7aea3f57b 100644 --- a/packages/node_modules/@node-red/registry/lib/localfilesystem.js +++ b/packages/node_modules/@node-red/registry/lib/localfilesystem.js @@ -16,10 +16,6 @@ var fs = require("fs"); var path = require("path"); - -var events; -var log; - var log = require("@node-red/util").log; var i18n = require("@node-red/util").i18n; @@ -27,9 +23,8 @@ var settings; var disableNodePathScan = false; var iconFileExtensions = [".png", ".gif", ".svg"]; -function init(runtime) { - settings = runtime.settings; - events = runtime.events; +function init(_settings) { + settings = _settings; } function isIncluded(name) { @@ -75,7 +70,6 @@ function getLocalFile(file) { /** * Synchronously walks the directory looking for node files. - * Emits 'node-icon-dir' events for an icon dirs found * @param dir the directory to search * @return an array of fully-qualified paths to .js files */ @@ -229,7 +223,6 @@ function getModuleNodeFiles(module) { try { fs.statSync(examplesDir) result.examples = {path:examplesDir}; - // events.emit("node-examples-dir",{name:pkg.name,path:examplesDir}); } catch(err) { } return result; diff --git a/packages/node_modules/@node-red/registry/lib/registry.js b/packages/node_modules/@node-red/registry/lib/registry.js index 89f04eacc..a91735071 100644 --- a/packages/node_modules/@node-red/registry/lib/registry.js +++ b/packages/node_modules/@node-red/registry/lib/registry.js @@ -19,8 +19,7 @@ var path = require("path"); var fs = require("fs"); var library = require("./library"); - -var events; +const {events} = require("@node-red/util") var settings; var loader; @@ -31,10 +30,9 @@ var nodeConstructors = {}; var nodeTypeToId = {}; var moduleNodes = {}; -function init(_settings,_loader, _events) { +function init(_settings,_loader) { settings = _settings; loader = _loader; - events = _events; moduleNodes = {}; nodeTypeToId = {}; nodeConstructors = {}; diff --git a/packages/node_modules/@node-red/registry/lib/util.js b/packages/node_modules/@node-red/registry/lib/util.js index 5a6d3da38..dbb6c6fc7 100644 --- a/packages/node_modules/@node-red/registry/lib/util.js +++ b/packages/node_modules/@node-red/registry/lib/util.js @@ -14,9 +14,8 @@ * limitations under the License. **/ -var path = require("path"); -var i18n = require("@node-red/util").i18n; -var registry; +const path = require("path"); +const {events,i18n,log} = require("@node-red/util"); var runtime; function copyObjectProperties(src,dst,copyList,blockList) { @@ -40,7 +39,7 @@ function copyObjectProperties(src,dst,copyList,blockList) { } } function requireModule(name) { - var moduleInfo = registry.getModuleInfo(name); + var moduleInfo = require("./index").getModuleInfo(name); if (moduleInfo && moduleInfo.path) { var relPath = path.relative(__dirname, moduleInfo.path); return require(relPath); @@ -56,14 +55,14 @@ function createNodeApi(node) { nodes: {}, log: {}, settings: {}, - events: runtime.events, + events: events, hooks: runtime.hooks, util: runtime.util, version: runtime.version, require: requireModule, comms: { publish: function(topic,data,retain) { - runtime.events.emit("comms",{ + events.emit("comms",{ topic: topic, data: data, retain: retain @@ -83,7 +82,7 @@ function createNodeApi(node) { red.nodes.registerType = function(type,constructor,opts) { runtime.nodes.registerType(node.id,type,constructor,opts); } - copyObjectProperties(runtime.log,red.log,null,["init"]); + copyObjectProperties(log,red.log,null,["init"]); copyObjectProperties(runtime.settings,red.settings,null,["init","load","reset"]); if (runtime.adminApi) { red.auth = runtime.adminApi.auth; @@ -108,7 +107,6 @@ function createNodeApi(node) { module.exports = { init: function(_runtime) { runtime = _runtime; - registry = require("@node-red/registry/lib"); }, createNodeApi: createNodeApi } diff --git a/packages/node_modules/@node-red/registry/package.json b/packages/node_modules/@node-red/registry/package.json index 47472f38e..3d517421c 100644 --- a/packages/node_modules/@node-red/registry/package.json +++ b/packages/node_modules/@node-red/registry/package.json @@ -19,7 +19,6 @@ "@node-red/util": "1.3.0-beta.1", "semver": "6.3.0", "tar": "6.0.5", - "uglify-js": "3.11.6", - "when": "3.7.8" + "uglify-js": "3.11.6" } } diff --git a/packages/node_modules/@node-red/runtime/lib/api/comms.js b/packages/node_modules/@node-red/runtime/lib/api/comms.js index 55789b806..90f1603cd 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/comms.js +++ b/packages/node_modules/@node-red/runtime/lib/api/comms.js @@ -33,6 +33,7 @@ var runtime; var retained = {}; var connections = []; +const events = require("@node-red/util").events; function handleCommsEvent(event) { publish(event.topic,event.data,event.retain); @@ -88,14 +89,14 @@ var api = module.exports = { runtime = _runtime; connections = []; retained = {}; - runtime.events.removeListener("node-status",handleStatusEvent); - runtime.events.on("node-status",handleStatusEvent); - runtime.events.removeListener("runtime-event",handleRuntimeEvent); - runtime.events.on("runtime-event",handleRuntimeEvent); - runtime.events.removeListener("comms",handleCommsEvent); - runtime.events.on("comms",handleCommsEvent); - runtime.events.removeListener("event-log",handleEventLog); - runtime.events.on("event-log",handleEventLog); + events.removeListener("node-status",handleStatusEvent); + events.on("node-status",handleStatusEvent); + events.removeListener("runtime-event",handleRuntimeEvent); + events.on("runtime-event",handleRuntimeEvent); + events.removeListener("comms",handleCommsEvent); + events.on("comms",handleCommsEvent); + events.removeListener("event-log",handleEventLog); + events.on("event-log",handleEventLog); }, /** @@ -106,9 +107,8 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_comms */ - addConnection: function(opts) { + addConnection: async function(opts) { connections.push(opts.client); - return Promise.resolve(); }, /** @@ -119,14 +119,13 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_comms */ - removeConnection: function(opts) { + removeConnection: async function(opts) { for (var i=0;i} - resolves when complete * @memberof @node-red/runtime_comms */ - subscribe: function(opts) { + subscribe: async function(opts) { var re = new RegExp("^"+opts.topic.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); for (var t in retained) { if (re.test(t)) { opts.client.send(t,retained[t]); } } - return Promise.resolve(); }, /** @@ -159,5 +157,5 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_comms */ - unsubscribe: function(opts) {} + unsubscribe: async function(opts) {} }; diff --git a/packages/node_modules/@node-red/runtime/lib/api/context.js b/packages/node_modules/@node-red/runtime/lib/api/context.js index f69349a62..6716b6831 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/context.js +++ b/packages/node_modules/@node-red/runtime/lib/api/context.js @@ -71,7 +71,7 @@ var api = module.exports = { * @return {Promise} - the node information * @memberof @node-red/runtime_context */ - getValue: function(opts) { + getValue: async function(opts) { return new Promise(function(resolve,reject) { var scope = opts.scope; var id = opts.id; @@ -165,7 +165,7 @@ var api = module.exports = { * @return {Promise} - the node information * @memberof @node-red/runtime_context */ - delete: function(opts) { + delete: async function(opts) { return new Promise(function(resolve,reject) { var scope = opts.scope; var id = opts.id; diff --git a/packages/node_modules/@node-red/runtime/lib/api/index.js b/packages/node_modules/@node-red/runtime/lib/api/index.js index 8856ac3c2..b131470b0 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/index.js +++ b/packages/node_modules/@node-red/runtime/lib/api/index.js @@ -38,10 +38,10 @@ var api = module.exports = { projects: require("./projects"), context: require("./context"), - isStarted: function(opts) { - return Promise.resolve(runtime.isStarted()); + isStarted: async function(opts) { + return runtime.isStarted(); }, - version: function(opts) { - return Promise.resolve(runtime.version()); + version: async function(opts) { + return runtime.version(); } } diff --git a/packages/node_modules/@node-red/runtime/lib/api/library.js b/packages/node_modules/@node-red/runtime/lib/api/library.js index f252d3264..6b7ed6218 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/library.js +++ b/packages/node_modules/@node-red/runtime/lib/api/library.js @@ -36,32 +36,30 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_library */ - getEntry: function(opts) { - return new Promise(function(resolve,reject) { - 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}, opts.req); - return resolve(result); - }).catch(function(err) { - if (err) { - runtime.log.warn(runtime.log._("api.library.error-load-entry",{library:opts.library,type:opts.type,path:opts.path,message:err.toString()})); - if (err.code === 'forbidden') { - err.status = 403; - return reject(err); - } else if (err.code === "not_found") { - err.status = 404; - } else { - err.status = 400; - } - runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path,error:err.code}, opts.req); - return reject(err); + getEntry: async function(opts) { + return 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}, opts.req); + return result; + }).catch(function(err) { + if (err) { + runtime.log.warn(runtime.log._("api.library.error-load-entry",{library:opts.library,type:opts.type,path:opts.path,message:err.toString()})); + if (err.code === 'forbidden') { + err.status = 403; + throw err; + } else if (err.code === "not_found") { + err.status = 404; + } else { + err.status = 400; } - runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,error:"not_found"}, opts.req); - var error = new Error(); - error.code = "not_found"; - error.status = 404; - return reject(error); - }); - }) + runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,path:opts.path,error:err.code}, opts.req); + throw err; + } + runtime.log.audit({event: "library.get",library:opts.library,type:opts.type,error:"not_found"}, opts.req); + var error = new Error(); + error.code = "not_found"; + error.status = 404; + throw error; + }); }, /** @@ -77,23 +75,20 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_library */ - saveEntry: function(opts) { - return new Promise(function(resolve,reject) { - 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}, opts.req); - return resolve(); - }).catch(function(err) { - runtime.log.warn(runtime.log._("api.library.error-save-entry",{path:opts.path,message:err.toString()})); - if (err.code === '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()}, opts.req); - var error = new Error(); - error.status = 400; - return reject(error); - }); - }) + saveEntry: async function(opts) { + return 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}, opts.req); + }).catch(function(err) { + runtime.log.warn(runtime.log._("api.library.error-save-entry",{path:opts.path,message:err.toString()})); + if (err.code === 'forbidden') { + runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"forbidden"}, opts.req); + err.status = 403; + throw err; + } + runtime.log.audit({event: "library.set",type:opts.type,path:opts.path,error:"unexpected_error",message:err.toString()}, opts.req); + var error = new Error(); + error.status = 400; + throw error; + }); } } diff --git a/packages/node_modules/@node-red/runtime/lib/api/nodes.js b/packages/node_modules/@node-red/runtime/lib/api/nodes.js index a06cbed96..9ac83c814 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/nodes.js +++ b/packages/node_modules/@node-red/runtime/lib/api/nodes.js @@ -18,7 +18,7 @@ * @mixin @node-red/runtime_nodes */ -var fs = require("fs"); +var fs = require("fs-extra"); var runtime; @@ -52,22 +52,20 @@ var api = module.exports = { * @return {Promise} - the node information * @memberof @node-red/runtime_nodes */ - getNodeInfo: function(opts) { - return new Promise(function(resolve,reject) { - var id = opts.id; - var result = runtime.nodes.getNodeInfo(id); - if (result) { - 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"}, opts.req); - var err = new Error("Node not found"); - err.code = "not_found"; - err.status = 404; - return reject(err); - } - }) + getNodeInfo: async function(opts) { + var id = opts.id; + var result = runtime.nodes.getNodeInfo(id); + if (result) { + runtime.log.audit({event: "nodes.info.get",id:id}, opts.req); + delete result.loaded; + return result; + } else { + runtime.log.audit({event: "nodes.info.get",id:id,error:"not_found"}, opts.req); + var err = new Error("Node not found"); + err.code = "not_found"; + err.status = 404; + throw err; + } }, /** @@ -78,11 +76,9 @@ var api = module.exports = { * @return {Promise} - the list of node modules * @memberof @node-red/runtime_nodes */ - getNodeList: function(opts) { - return new Promise(function(resolve,reject) { - runtime.log.audit({event: "nodes.list.get"}, opts.req); - return resolve(runtime.nodes.getNodeList()); - }) + getNodeList: async function(opts) { + runtime.log.audit({event: "nodes.list.get"}, opts.req); + return runtime.nodes.getNodeList(); }, /** @@ -95,22 +91,20 @@ var api = module.exports = { * @return {Promise} - the node html content * @memberof @node-red/runtime_nodes */ - getNodeConfig: function(opts) { - return new Promise(function(resolve,reject) { - var id = opts.id; - var lang = opts.lang; - var result = runtime.nodes.getNodeConfig(id,lang); - if (result) { - 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"}, opts.req); - var err = new Error("Node not found"); - err.code = "not_found"; - err.status = 404; - return reject(err); - } - }); + getNodeConfig: async function(opts) { + var id = opts.id; + var lang = opts.lang; + var result = runtime.nodes.getNodeConfig(id,lang); + if (result) { + runtime.log.audit({event: "nodes.config.get",id:id}, opts.req); + return result; + } else { + runtime.log.audit({event: "nodes.config.get",id:id,error:"not_found"}, opts.req); + var err = new Error("Node not found"); + err.code = "not_found"; + err.status = 404; + throw err; + } }, /** * Gets all node html content @@ -121,11 +115,9 @@ var api = module.exports = { * @return {Promise} - the node html content * @memberof @node-red/runtime_nodes */ - getNodeConfigs: function(opts) { - return new Promise(function(resolve,reject) { - runtime.log.audit({event: "nodes.configs.get"}, opts.req); - return resolve(runtime.nodes.getNodeConfigs(opts.lang)); - }); + getNodeConfigs: async function(opts) { + runtime.log.audit({event: "nodes.configs.get"}, opts.req); + return runtime.nodes.getNodeConfigs(opts.lang); }, /** @@ -137,20 +129,18 @@ var api = module.exports = { * @return {Promise} - the node module info * @memberof @node-red/runtime_nodes */ - getModuleInfo: function(opts) { - return new Promise(function(resolve,reject) { - var result = runtime.nodes.getModuleInfo(opts.module); - if (result) { - 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"}, opts.req); - var err = new Error("Module not found"); - err.code = "not_found"; - err.status = 404; - return reject(err); - } - }) + getModuleInfo: async function(opts) { + var result = runtime.nodes.getModuleInfo(opts.module); + if (result) { + runtime.log.audit({event: "nodes.module.get",id:opts.module}, opts.req); + return result; + } else { + runtime.log.audit({event: "nodes.module.get",id:opts.module,error:"not_found"}, opts.req); + var err = new Error("Module not found"); + err.code = "not_found"; + err.status = 404; + throw err; + } }, /** @@ -165,83 +155,78 @@ var api = module.exports = { * @return {Promise} - the node module info * @memberof @node-red/runtime_nodes */ - addModule: function(opts) { - return new Promise(function(resolve,reject) { - if (!runtime.settings.available()) { - runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req); - var err = new Error("Settings unavailable"); - err.code = "settings_unavailable"; - err.status = 400; - return reject(err); - } - if (opts.tarball) { - if (runtime.settings.editorTheme && runtime.settings.editorTheme.palette && runtime.settings.editorTheme.palette.upload === false) { - runtime.log.audit({event: "nodes.install",tarball:opts.tarball.file,error:"invalid_request"}, opts.req); - var err = new Error("Invalid request"); - err.code = "invalid_request"; - err.status = 400; - return reject(err); - } - if (opts.module || opts.version || opts.url) { - runtime.log.audit({event: "nodes.install",tarball:opts.tarball.file,module:opts.module,error:"invalid_request"}, opts.req); - var err = new Error("Invalid request"); - err.code = "invalid_request"; - err.status = 400; - return reject(err); - } - runtime.nodes.installModule(opts.tarball.buffer).then(function(info) { - runtime.log.audit({event: "nodes.install",tarball:opts.tarball.file,module:info.id}, opts.req); - return resolve(info); - }).catch(function(err) { - - if (err.code) { - err.status = 400; - runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code}, opts.req); - } else { - err.status = 400; - runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code||"unexpected_error",message:err.toString()}, opts.req); - } - return reject(err); - }) - return; - } - if (opts.module) { - var existingModule = runtime.nodes.getModuleInfo(opts.module); - if (existingModule) { - if (!opts.version || existingModule.version === opts.version) { - 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"); - err.code = "module_already_loaded"; - err.status = 400; - return reject(err); - } - } - runtime.nodes.installModule(opts.module,opts.version,opts.url).then(function(info) { - runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url}, opts.req); - return resolve(info); - }).catch(function(err) { - if (err.code === 404) { - runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:"not_found"}, opts.req); - // TODO: code/status - err.status = 404; - } else if (err.code) { - err.status = 400; - runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code}, opts.req); - } else { - err.status = 400; - runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code||"unexpected_error",message:err.toString()}, opts.req); - } - return reject(err); - }) - } else { - runtime.log.audit({event: "nodes.install",module:opts.module,error:"invalid_request"}, opts.req); + addModule: async function(opts) { + if (!runtime.settings.available()) { + runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req); + var err = new Error("Settings unavailable"); + err.code = "settings_unavailable"; + err.status = 400; + throw err; + } + if (opts.tarball) { + if (runtime.settings.editorTheme && runtime.settings.editorTheme.palette && runtime.settings.editorTheme.palette.upload === false) { + runtime.log.audit({event: "nodes.install",tarball:opts.tarball.file,error:"invalid_request"}, opts.req); var err = new Error("Invalid request"); err.code = "invalid_request"; err.status = 400; - return reject(err); + throw err; } - - }); + if (opts.module || opts.version || opts.url) { + runtime.log.audit({event: "nodes.install",tarball:opts.tarball.file,module:opts.module,error:"invalid_request"}, opts.req); + var err = new Error("Invalid request"); + err.code = "invalid_request"; + err.status = 400; + throw err; + } + return runtime.nodes.installModule(opts.tarball.buffer).then(function(info) { + runtime.log.audit({event: "nodes.install",tarball:opts.tarball.file,module:info.id}, opts.req); + return info; + }).catch(function(err) { + if (err.code) { + err.status = 400; + runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code}, opts.req); + } else { + err.status = 400; + runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code||"unexpected_error",message:err.toString()}, opts.req); + } + throw err; + }) + } + if (opts.module) { + var existingModule = runtime.nodes.getModuleInfo(opts.module); + if (existingModule) { + if (!opts.version || existingModule.version === opts.version) { + 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"); + err.code = "module_already_loaded"; + err.status = 400; + throw err; + } + } + return runtime.nodes.installModule(opts.module,opts.version,opts.url).then(function(info) { + runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url}, opts.req); + return info; + }).catch(function(err) { + if (err.code === 404) { + runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:"not_found"}, opts.req); + // TODO: code/status + err.status = 404; + } else if (err.code) { + err.status = 400; + runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code}, opts.req); + } else { + err.status = 400; + runtime.log.audit({event: "nodes.install",module:opts.module,version:opts.version,url:opts.url,error:err.code||"unexpected_error",message:err.toString()}, opts.req); + } + throw err; + }) + } else { + runtime.log.audit({event: "nodes.install",module:opts.module,error:"invalid_request"}, opts.req); + var err = new Error("Invalid request"); + err.code = "invalid_request"; + err.status = 400; + throw err; + } }, /** * Removes a module from the runtime @@ -252,38 +237,35 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_nodes */ - removeModule: function(opts) { - return new Promise(function(resolve,reject) { - if (!runtime.settings.available()) { - runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req); - var err = new Error("Settings unavailable"); - err.code = "settings_unavailable"; + removeModule: async function(opts) { + if (!runtime.settings.available()) { + runtime.log.audit({event: "nodes.install",error:"settings_unavailable"}, opts.req); + var err = new Error("Settings unavailable"); + err.code = "settings_unavailable"; + err.status = 400; + throw err; + } + var module = runtime.nodes.getModuleInfo(opts.module); + if (!module) { + runtime.log.audit({event: "nodes.remove",module:opts.module,error:"not_found"}, opts.req); + var err = new Error("Module not found"); + err.code = "not_found"; + err.status = 404; + throw err; + } + try { + return runtime.nodes.uninstallModule(opts.module).then(function() { + runtime.log.audit({event: "nodes.remove",module:opts.module}, opts.req); + }).catch(function(err) { err.status = 400; - return reject(err); - } - var module = runtime.nodes.getModuleInfo(opts.module); - if (!module) { - runtime.log.audit({event: "nodes.remove",module:opts.module,error:"not_found"}, opts.req); - var err = new Error("Module not found"); - err.code = "not_found"; - err.status = 404; - return reject(err); - } - try { - runtime.nodes.uninstallModule(opts.module).then(function() { - 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()}, opts.req); - return reject(err); - }) - } catch(error) { - runtime.log.audit({event: "nodes.remove",module:opts.module,error:error.code||"unexpected_error",message:error.toString()}, opts.req); - error.status = 400; - return reject(error); - } - }); + runtime.log.audit({event: "nodes.remove",module:opts.module,error:err.code||"unexpected_error",message:err.toString()}, opts.req); + throw err; + }) + } catch(error) { + runtime.log.audit({event: "nodes.remove",module:opts.module,error:error.code||"unexpected_error",message:error.toString()}, opts.req); + error.status = 400; + throw err; + } }, /** @@ -296,43 +278,41 @@ var api = module.exports = { * @return {Promise} - the module info object * @memberof @node-red/runtime_nodes */ - setModuleState: function(opts) { + setModuleState: async function(opts) { var mod = opts.module; - return new Promise(function(resolve,reject) { - if (!runtime.settings.available()) { - runtime.log.audit({event: "nodes.module.set",error:"settings_unavailable"}, opts.req); - var err = new Error("Settings unavailable"); - err.code = "settings_unavailable"; - err.status = 400; - return reject(err); + if (!runtime.settings.available()) { + runtime.log.audit({event: "nodes.module.set",error:"settings_unavailable"}, opts.req); + var err = new Error("Settings unavailable"); + err.code = "settings_unavailable"; + err.status = 400; + throw err; + } + try { + var module = runtime.nodes.getModuleInfo(mod); + if (!module) { + runtime.log.audit({event: "nodes.module.set",module:mod,error:"not_found"}, opts.req); + var err = new Error("Module not found"); + err.code = "not_found"; + err.status = 404; + throw err; } - try { - var module = runtime.nodes.getModuleInfo(mod); - if (!module) { - runtime.log.audit({event: "nodes.module.set",module:mod,error:"not_found"}, opts.req); - var err = new Error("Module not found"); - err.code = "not_found"; - err.status = 404; - return reject(err); - } - var nodes = module.nodes; - var promises = []; - for (var i = 0; i < nodes.length; ++i) { - promises.push(putNode(nodes[i],opts.enabled)); - } - Promise.all(promises).then(function() { - return resolve(runtime.nodes.getModuleInfo(mod)); - }).catch(function(err) { - err.status = 400; - return reject(err); - }); - } catch(error) { - 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; - return reject(error); + var nodes = module.nodes; + var promises = []; + for (var i = 0; i < nodes.length; ++i) { + promises.push(putNode(nodes[i],opts.enabled)); } - }); + return Promise.all(promises).then(function() { + return runtime.nodes.getModuleInfo(mod); + }).catch(function(err) { + err.status = 400; + throw err; + }); + } catch(error) { + 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; + throw err; + } }, /** @@ -345,43 +325,41 @@ var api = module.exports = { * @return {Promise} - the module info object * @memberof @node-red/runtime_nodes */ - setNodeSetState: function(opts) { - return new Promise(function(resolve,reject) { - if (!runtime.settings.available()) { - runtime.log.audit({event: "nodes.info.set",error:"settings_unavailable"}, opts.req); - var err = new Error("Settings unavailable"); - err.code = "settings_unavailable"; - err.status = 400; - return reject(err); - } + setNodeSetState: async function(opts) { + if (!runtime.settings.available()) { + runtime.log.audit({event: "nodes.info.set",error:"settings_unavailable"}, opts.req); + var err = new Error("Settings unavailable"); + err.code = "settings_unavailable"; + err.status = 400; + throw err; + } - var id = opts.id; - var enabled = opts.enabled; - try { - var node = runtime.nodes.getNodeInfo(id); - if (!node) { - runtime.log.audit({event: "nodes.info.set",id:id,error:"not_found"}, opts.req); - var err = new Error("Node not found"); - err.code = "not_found"; - err.status = 404; - return reject(err); - } else { - delete node.loaded; - putNode(node,enabled).then(function(result) { - 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()}, opts.req); - err.status = 400; - return reject(err); - }); - } - } catch(error) { - runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:error.code||"unexpected_error",message:error.toString()}, opts.req); - error.status = 400; - return reject(error); + var id = opts.id; + var enabled = opts.enabled; + try { + var node = runtime.nodes.getNodeInfo(id); + if (!node) { + runtime.log.audit({event: "nodes.info.set",id:id,error:"not_found"}, opts.req); + var err = new Error("Node not found"); + err.code = "not_found"; + err.status = 404; + throw err; + } else { + delete node.loaded; + return putNode(node,enabled).then(function(result) { + runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled}, opts.req); + return result; + }).catch(function(err) { + runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:err.code||"unexpected_error",message:err.toString()}, opts.req); + err.status = 400; + throw err; + }); } - }); + } catch(error) { + runtime.log.audit({event: "nodes.info.set",id:id,enabled:enabled,error:error.code||"unexpected_error",message:error.toString()}, opts.req); + error.status = 400; + throw err; + } }, /** @@ -393,12 +371,12 @@ var api = module.exports = { * @return {Promise} - the message catalogs * @memberof @node-red/runtime_nodes */ - getModuleCatalogs: function(opts) { - return new Promise(function(resolve,reject) { - var namespace = opts.module; - var lang = opts.lang; - var prevLang = runtime.i18n.i.language; - // Trigger a load from disk of the language if it is not the default + getModuleCatalogs: async function(opts) { + var namespace = opts.module; + var lang = opts.lang; + var prevLang = runtime.i18n.i.language; + // Trigger a load from disk of the language if it is not the default + return new Promise( (resolve,reject) => { runtime.i18n.i.changeLanguage(lang, function(){ var nodeList = runtime.nodes.getNodeList(); var result = {}; @@ -407,9 +385,9 @@ var api = module.exports = { result[n.id] = runtime.i18n.i.getResourceBundle(lang, n.id)||{}; } }); + runtime.i18n.i.changeLanguage(prevLang); resolve(result); }); - runtime.i18n.i.changeLanguage(prevLang); }); }, @@ -423,17 +401,15 @@ var api = module.exports = { * @return {Promise} - the message catalog * @memberof @node-red/runtime_nodes */ - getModuleCatalog: function(opts) { - return new Promise(function(resolve,reject) { - var namespace = opts.module; - var lang = opts.lang; - var prevLang = runtime.i18n.i.language; - // Trigger a load from disk of the language if it is not the default - runtime.i18n.i.changeLanguage(lang, function(){ - var catalog = runtime.i18n.i.getResourceBundle(lang, namespace); - resolve(catalog||{}); - }); + getModuleCatalog: async function(opts) { + var namespace = opts.module; + var lang = opts.lang; + var prevLang = runtime.i18n.i.language; + // Trigger a load from disk of the language if it is not the default + return runtime.i18n.i.changeLanguage(lang, function(){ + var catalog = runtime.i18n.i.getResourceBundle(lang, namespace); runtime.i18n.i.changeLanguage(prevLang); + return catalog||{}; }); }, @@ -445,12 +421,9 @@ var api = module.exports = { * @return {Promise} - the list of all icons * @memberof @node-red/runtime_nodes */ - getIconList: function(opts) { - return new Promise(function(resolve,reject) { - runtime.log.audit({event: "nodes.icons.get"}, opts.req); - return resolve(runtime.nodes.getNodeIcons()); - }); - + getIconList: async function(opts) { + runtime.log.audit({event: "nodes.icons.get"}, opts.req); + return runtime.nodes.getNodeIcons(); }, /** * Gets a node icon @@ -462,20 +435,15 @@ var api = module.exports = { * @return {Promise} - the icon file as a Buffer or null if no icon available * @memberof @node-red/runtime_nodes */ - getIcon: function(opts) { - return new Promise(function(resolve,reject) { - var iconPath = runtime.nodes.getNodeIconPath(opts.module,opts.icon); - if (iconPath) { - fs.readFile(iconPath,function(err,data) { - if (err) { - err.status = 400; - return reject(err); - } - return resolve(data) - }); - } else { - resolve(null); - } - }); + getIcon: async function(opts) { + var iconPath = runtime.nodes.getNodeIconPath(opts.module,opts.icon); + if (iconPath) { + return fs.readFile(iconPath).catch(err => { + err.status = 400; + throw err; + }); + } else { + return null + } } } diff --git a/packages/node_modules/@node-red/runtime/lib/api/projects.js b/packages/node_modules/@node-red/runtime/lib/api/projects.js index d792f3765..14d1d0ec1 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/projects.js +++ b/packages/node_modules/@node-red/runtime/lib/api/projects.js @@ -24,8 +24,8 @@ var api = module.exports = { init: function(_runtime) { runtime = _runtime; }, - available: function(opts) { - return Promise.resolve(!!runtime.storage.projects); + available: async function(opts) { + return !!runtime.storage.projects; }, /** * List projects known to the runtime @@ -36,7 +36,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - listProjects: function(opts) { + listProjects: async function(opts) { return runtime.storage.projects.listProjects(opts.user).then(function(list) { var active = runtime.storage.projects.getActiveProject(opts.user); var response = { @@ -61,7 +61,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - createProject: function(opts) { + createProject: async 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,7 +76,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - initialiseProject: function(opts) { + initialiseProject: async function(opts) { // 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,8 +90,8 @@ var api = module.exports = { * @return {Promise} - the active project * @memberof @node-red/runtime_projects */ - getActiveProject: function(opts) { - return Promise.resolve(runtime.storage.projects.getActiveProject(opts.user)); + getActiveProject: async function(opts) { + return runtime.storage.projects.getActiveProject(opts.user); }, /** @@ -103,13 +103,11 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - setActiveProject: function(opts) { + setActiveProject: async function(opts) { 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) { return runtime.storage.projects.setActiveProject(opts.user, opts.id); - } else { - return Promise.resolve(); } }, @@ -122,7 +120,7 @@ var api = module.exports = { * @return {Promise} - the project metadata * @memberof @node-red/runtime_projects */ - getProject: function(opts) { + getProject: async function(opts) { return runtime.storage.projects.getProject(opts.user, opts.id) }, @@ -136,7 +134,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - updateProject: function(opts) { + updateProject: async 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,7 +148,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - deleteProject: function(opts) { + deleteProject: async function(opts) { runtime.log.audit({event: "projects.delete",id:opts.id}, opts.req); return runtime.storage.projects.deleteProject(opts.user, opts.id); }, @@ -165,7 +163,7 @@ var api = module.exports = { * @return {Promise} - the project status * @memberof @node-red/runtime_projects */ - getStatus: function(opts) { + getStatus: async function(opts) { return runtime.storage.projects.getStatus(opts.user, opts.id, opts.remote) }, @@ -179,7 +177,7 @@ var api = module.exports = { * @return {Promise} - a list of the local branches * @memberof @node-red/runtime_projects */ - getBranches: function(opts) { + getBranches: async function(opts) { return runtime.storage.projects.getBranches(opts.user, opts.id, opts.remote); }, @@ -193,7 +191,7 @@ var api = module.exports = { * @return {Promise} - the status of the branch * @memberof @node-red/runtime_projects */ - getBranchStatus: function(opts) { + getBranchStatus: async function(opts) { return runtime.storage.projects.getBranchStatus(opts.user, opts.id, opts.branch); }, @@ -208,7 +206,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - setBranch: function(opts) { + setBranch: async 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,7 +222,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - deleteBranch: function(opts) { + deleteBranch: async 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,7 +237,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - commit: function(opts) { + commit: async 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,7 +252,7 @@ var api = module.exports = { * @return {Promise} - the commit details * @memberof @node-red/runtime_projects */ - getCommit: function(opts) { + getCommit: async function(opts) { return runtime.storage.projects.getCommit(opts.user, opts.id, opts.sha); }, @@ -269,7 +267,7 @@ var api = module.exports = { * @return {Promise} - an array of commits * @memberof @node-red/runtime_projects */ - getCommits: function(opts) { + getCommits: async function(opts) { return runtime.storage.projects.getCommits(opts.user, opts.id, { limit: opts.limit || 20, before: opts.before @@ -285,7 +283,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - abortMerge: function(opts) { + abortMerge: async function(opts) { runtime.log.audit({event: "projects.merge.abort",id:opts.id}, opts.req); return runtime.storage.projects.abortMerge(opts.user, opts.id); }, @@ -301,7 +299,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - resolveMerge: function(opts) { + resolveMerge: async 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,7 +313,7 @@ var api = module.exports = { * @return {Promise} - the file listing * @memberof @node-red/runtime_projects */ - getFiles: function(opts) { + getFiles: async function(opts) { return runtime.storage.projects.getFiles(opts.user, opts.id); }, @@ -330,7 +328,7 @@ var api = module.exports = { * @return {Promise} - the content of the file * @memberof @node-red/runtime_projects */ - getFile: function(opts) { + getFile: async function(opts) { return runtime.storage.projects.getFile(opts.user, opts.id,opts.path,opts.tree); }, @@ -344,7 +342,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - stageFile: function(opts) { + stageFile: async 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,7 +357,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - unstageFile: function(opts) { + unstageFile: async 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,7 +372,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - revertFile: function(opts) { + revertFile: async 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,7 +388,7 @@ var api = module.exports = { * @return {Promise} - the requested diff * @memberof @node-red/runtime_projects */ - getFileDiff: function(opts) { + getFileDiff: async function(opts) { return runtime.storage.projects.getFileDiff(opts.user, opts.id, opts.path, opts.type); }, @@ -403,7 +401,7 @@ var api = module.exports = { * @return {Promise} - a list of project remotes * @memberof @node-red/runtime_projects */ - getRemotes: function(opts) { + getRemotes: async function(opts) { return runtime.storage.projects.getRemotes(opts.user, opts.id); }, @@ -420,7 +418,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - addRemote: function(opts) { + addRemote: async 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,7 +433,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - removeRemote: function(opts) { + removeRemote: async 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,7 +449,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - updateRemote: function(opts) { + updateRemote: async 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) }, @@ -467,7 +465,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - pull: function(opts) { + pull: async 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); }, @@ -483,7 +481,7 @@ var api = module.exports = { * @return {Promise} - resolves when complete * @memberof @node-red/runtime_projects */ - push: function(opts) { + push: async 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); } diff --git a/packages/node_modules/@node-red/runtime/lib/api/settings.js b/packages/node_modules/@node-red/runtime/lib/api/settings.js index 6ebeeccfb..067a8e83a 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/settings.js +++ b/packages/node_modules/@node-red/runtime/lib/api/settings.js @@ -64,64 +64,57 @@ var api = module.exports = { * @return {Promise} - the runtime settings * @memberof @node-red/runtime_settings */ - getRuntimeSettings: function(opts) { - return new Promise(function(resolve,reject) { - try { - var safeSettings = { - httpNodeRoot: runtime.settings.httpNodeRoot||"/", - version: runtime.settings.version - } - if (opts.user) { - safeSettings.user = {} - var props = ["anonymous","username","image","permissions"]; - props.forEach(prop => { - if (opts.user.hasOwnProperty(prop)) { - safeSettings.user[prop] = opts.user[prop]; - } - }) + getRuntimeSettings: async function(opts) { + var safeSettings = { + httpNodeRoot: runtime.settings.httpNodeRoot||"/", + version: runtime.settings.version + } + if (opts.user) { + safeSettings.user = {} + var props = ["anonymous","username","image","permissions"]; + props.forEach(prop => { + if (opts.user.hasOwnProperty(prop)) { + safeSettings.user[prop] = opts.user[prop]; } + }) + } - if (!runtime.settings.disableEditor) { - safeSettings.context = runtime.nodes.listContextStores(); + if (!runtime.settings.disableEditor) { + safeSettings.context = runtime.nodes.listContextStores(); - if (util.isArray(runtime.settings.paletteCategories)) { - safeSettings.paletteCategories = runtime.settings.paletteCategories; - } - - if (runtime.settings.flowFilePretty) { - safeSettings.flowFilePretty = runtime.settings.flowFilePretty; - } - - if (!runtime.nodes.paletteEditorEnabled()) { - safeSettings.editorTheme = safeSettings.editorTheme || {}; - safeSettings.editorTheme.palette = safeSettings.editorTheme.palette || {}; - safeSettings.editorTheme.palette.editable = false; - } - if (runtime.storage.projects) { - var activeProject = runtime.storage.projects.getActiveProject(); - if (activeProject) { - safeSettings.project = activeProject; - } else if (runtime.storage.projects.flowFileExists()) { - safeSettings.files = { - flow: runtime.storage.projects.getFlowFilename(), - credentials: runtime.storage.projects.getCredentialsFilename() - } - } - safeSettings.git = { - globalUser: runtime.storage.projects.getGlobalGitUser() - } - } - - safeSettings.flowEncryptionType = runtime.nodes.getCredentialKeyType(); - runtime.settings.exportNodeSettings(safeSettings); - } - - - resolve(safeSettings); - }catch(err) { - console.log(err); + if (util.isArray(runtime.settings.paletteCategories)) { + safeSettings.paletteCategories = runtime.settings.paletteCategories; } - }); + + if (runtime.settings.flowFilePretty) { + safeSettings.flowFilePretty = runtime.settings.flowFilePretty; + } + + if (!runtime.nodes.installerEnabled()) { + safeSettings.editorTheme = safeSettings.editorTheme || {}; + safeSettings.editorTheme.palette = safeSettings.editorTheme.palette || {}; + safeSettings.editorTheme.palette.editable = false; + } + if (runtime.storage.projects) { + var activeProject = runtime.storage.projects.getActiveProject(); + if (activeProject) { + safeSettings.project = activeProject; + } else if (runtime.storage.projects.flowFileExists()) { + safeSettings.files = { + flow: runtime.storage.projects.getFlowFilename(), + credentials: runtime.storage.projects.getCredentialsFilename() + } + } + safeSettings.git = { + globalUser: runtime.storage.projects.getGlobalGitUser() + } + } + + safeSettings.flowEncryptionType = runtime.nodes.getCredentialKeyType(); + runtime.settings.exportNodeSettings(safeSettings); + } + + return safeSettings; }, /** @@ -132,14 +125,14 @@ var api = module.exports = { * @return {Promise} - the user settings * @memberof @node-red/runtime_settings */ - getUserSettings: function(opts) { + getUserSettings: async function(opts) { var username; if (!opts.user || opts.user.anonymous) { username = '_'; } else { username = opts.user.username; } - return Promise.resolve(runtime.settings.getUserSettings(username)||{}); + return runtime.settings.getUserSettings(username)||{}; }, /** @@ -151,32 +144,30 @@ var api = module.exports = { * @return {Promise} - the user settings * @memberof @node-red/runtime_settings */ - updateUserSettings: function(opts) { + updateUserSettings: async function(opts) { var username; if (!opts.user || opts.user.anonymous) { username = '_'; } else { username = opts.user.username; } - return new Promise(function(resolve,reject) { - var currentSettings = runtime.settings.getUserSettings(username)||{}; - currentSettings = extend(currentSettings, opts.settings); - try { - runtime.settings.setUserSettings(username, currentSettings).then(function() { - 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()}, opts.req); - err.status = 400; - return reject(err); - }); - } catch(err) { - runtime.log.warn(runtime.log._("settings.user-not-available",{message:runtime.log._("settings.not-available")})); + var currentSettings = runtime.settings.getUserSettings(username)||{}; + currentSettings = extend(currentSettings, opts.settings); + try { + return runtime.settings.setUserSettings(username, currentSettings).then(function() { + runtime.log.audit({event: "settings.update",username:username}, opts.req); + return; + }).catch(function(err) { runtime.log.audit({event: "settings.update",username:username,error:err.code||"unexpected_error",message:err.toString()}, opts.req); err.status = 400; - return reject(err); - } - }); + throw err; + }); + } catch(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()}, opts.req); + err.status = 400; + throw err; + } }, /** @@ -187,15 +178,12 @@ var api = module.exports = { * @return {Promise} - the user's ssh keys * @memberof @node-red/runtime_settings */ - getUserKeys: function(opts) { - return new Promise(function(resolve,reject) { - var username = getSSHKeyUsername(opts.user); - runtime.storage.projects.ssh.listSSHKeys(username).then(function(list) { - return resolve(list); - }).catch(function(err) { - err.status = 400; - return reject(err); - }); + getUserKeys: async function(opts) { + var username = getSSHKeyUsername(opts.user); + return runtime.storage.projects.ssh.listSSHKeys(username).catch(function(err) { + err.status = 400; + throw err; + return reject(err); }); }, @@ -208,23 +196,23 @@ var api = module.exports = { * @return {Promise} - the user's ssh public key * @memberof @node-red/runtime_settings */ - getUserKey: function(opts) { - return new Promise(function(resolve,reject) { - var username = getSSHKeyUsername(opts.user); - // console.log('username:', username); - runtime.storage.projects.ssh.getSSHKey(username, opts.id).then(function(data) { - if (data) { - return resolve(data); - } else { - var err = new Error("Key not found"); - err.code = "not_found"; - err.status = 404; - return reject(err); - } - }).catch(function(err) { + getUserKey: async function(opts) { + var username = getSSHKeyUsername(opts.user); + // console.log('username:', username); + return runtime.storage.projects.ssh.getSSHKey(username, opts.id).then(function(data) { + if (data) { + return data; + } else { + var err = new Error("Key not found"); + err.code = "not_found"; + err.status = 404; + throw err; + } + }).catch(function(err) { + if (!err.status) { err.status = 400; - return reject(err); - }); + } + throw err; }); }, @@ -240,15 +228,11 @@ var api = module.exports = { * @return {Promise} - the id of the generated key * @memberof @node-red/runtime_settings */ - generateUserKey: function(opts) { - return new Promise(function(resolve,reject) { - var username = getSSHKeyUsername(opts.user); - runtime.storage.projects.ssh.generateSSHKey(username, opts).then(function(name) { - return resolve(name); - }).catch(function(err) { - err.status = 400; - return reject(err); - }); + generateUserKey: async function(opts) { + var username = getSSHKeyUsername(opts.user); + return runtime.storage.projects.ssh.generateSSHKey(username, opts).catch(function(err) { + err.status = 400; + throw err; }); }, @@ -261,16 +245,11 @@ var api = module.exports = { * @return {Promise} - resolves when deleted * @memberof @node-red/runtime_settings */ - removeUserKey: function(opts) { - return new Promise(function(resolve,reject) { - var username = getSSHKeyUsername(opts.user); - runtime.storage.projects.ssh.deleteSSHKey(username, opts.id).then(function() { - return resolve(); - }).catch(function(err) { - err.status = 400; - return reject(err); - }); + removeUserKey: async function(opts) { + var username = getSSHKeyUsername(opts.user); + return runtime.storage.projects.ssh.deleteSSHKey(username, opts.id).catch(function(err) { + err.status = 400; + throw err; }); - } } diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js index a7e00bfbc..a4791e084 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js @@ -16,8 +16,8 @@ var clone = require("clone"); var redUtil = require("@node-red/util").util; +const events = require("@node-red/util").events; var flowUtil = require("./util"); -var events = require("../events"); const context = require('../nodes/context'); const hooks = require("../hooks"); @@ -679,7 +679,6 @@ module.exports = { asyncMessageDelivery = !runtime.settings.runtimeSyncDelivery Log = runtime.log; Subflow = require("./Subflow"); - Subflow.init(runtime); }, create: function(parent,global,conf) { return new Flow(parent,global,conf); diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js index 78ec9ee75..da15ecfe4 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Subflow.js @@ -18,16 +18,11 @@ const clone = require("clone"); const Flow = require('./Flow').Flow; const context = require('../nodes/context'); const util = require("util"); -const events = require("../events"); - const redUtil = require("@node-red/util").util; +const events = require("@node-red/util").events; const flowUtil = require("./util"); - - const credentials = require("../nodes/credentials"); -var Log; - /** * Create deep copy of object */ @@ -509,8 +504,6 @@ function createSubflow(parent,globalFlow,subflowDef,subflowInstance) { } module.exports = { - init: function(runtime) { - Log = runtime.log; - }, + init: function(runtime) {}, create: createSubflow } diff --git a/packages/node_modules/@node-red/runtime/lib/flows/index.js b/packages/node_modules/@node-red/runtime/lib/flows/index.js index a207b8f05..350115f81 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/index.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/index.js @@ -25,9 +25,8 @@ var context = require("../nodes/context") var credentials = require("../nodes/credentials"); var flowUtil = require("./util"); var log; -var events = require("../events"); +const events = require("@node-red/util").events; var redUtil = require("@node-red/util").util; -const hooks = require("../hooks"); var storage = null; var settings = null; @@ -712,7 +711,7 @@ module.exports = { */ load: load, loadFlows: load, - + get:getNode, eachNode: eachNode, diff --git a/packages/node_modules/@node-red/runtime/lib/index.js b/packages/node_modules/@node-red/runtime/lib/index.js index f9a772ea3..dd1594467 100644 --- a/packages/node_modules/@node-red/runtime/lib/index.js +++ b/packages/node_modules/@node-red/runtime/lib/index.js @@ -14,27 +14,21 @@ * limitations under the License. **/ -var when = require('when'); - var externalAPI = require("./api"); var redNodes = require("./nodes"); var flows = require("./flows"); var storage = require("./storage"); var library = require("./library"); -var events = require("./events"); var hooks = require("./hooks"); var settings = require("./settings"); -var exec = require("./exec"); var express = require("express"); var path = require('path'); var fs = require("fs"); var os = require("os"); -var redUtil = require("@node-red/util"); -var log = redUtil.log; -var i18n = redUtil.i18n; +const {log,i18n,events,exec,util} = require("@node-red/util"); var runtimeMetricInterval = null; @@ -67,7 +61,7 @@ var server; * better abstracted. * @memberof @node-red/runtime */ -function init(userSettings,httpServer,_adminApi,__util) { +function init(userSettings,httpServer,_adminApi) { server = httpServer; userSettings.version = getVersion(); settings.init(userSettings); @@ -81,14 +75,6 @@ function init(userSettings,httpServer,_adminApi,__util) { redNodes.init(runtime); library.init(runtime); externalAPI.init(runtime); - exec.init(runtime); - if (__util) { - log = __util.log; - i18n = __util.i18n; - } else { - log = redUtil.log; - i18n = redUtil.i18n; - } } var version; @@ -197,25 +183,24 @@ function start() { }); } -var reinstallAttempts; +var reinstallAttempts = 0; var reinstallTimeout; function reinstallModules(moduleList) { var promises = []; - var failedModules = []; + var reinstallList = []; + for (var i=0;i { + events.emit("runtime-event",{id:"node/added",retain:false,payload:m.nodes}); + }).catch(err => { + reinstallList.push(mod); + })); + })(moduleList[i]) } } - when.settle(promises).then(function(results) { - var reinstallList = []; - for (var i=0;i 0) { reinstallAttempts++; // First 5 at 1x timeout, next 5 at 2x, next 5 at 4x, then 8x @@ -249,6 +234,10 @@ function reportMetrics() { /** * Stops the runtime. + * + * Once called, Node-RED should not be restarted until the Node.JS process is + * restarted. + * * @return {Promise} - resolves when the runtime is stopped. * @memberof @node-red/runtime */ @@ -269,17 +258,17 @@ function stop() { // This is the internal api var runtime = { version: getVersion, - get log() { return log }, - get i18n() { return i18n }, + log: log, + i18n: i18n, + events: events, settings: settings, storage: storage, - events: events, hooks: hooks, nodes: redNodes, flows: flows, library: library, exec: exec, - util: require("@node-red/util").util, + util: util, get adminApi() { return adminApi }, get adminApp() { return adminApp }, get nodeApp() { return nodeApp }, diff --git a/packages/node_modules/@node-red/runtime/lib/nodes/credentials.js b/packages/node_modules/@node-red/runtime/lib/nodes/credentials.js index 153ef4b06..86ea1d3a1 100644 --- a/packages/node_modules/@node-red/runtime/lib/nodes/credentials.js +++ b/packages/node_modules/@node-red/runtime/lib/nodes/credentials.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var when = require("when"); var crypto = require('crypto'); var runtime; var settings; @@ -60,7 +59,7 @@ var api = module.exports = { /** * Sets the credentials from storage. */ - load: function (credentials) { + load: async function (credentials) { dirty = false; var credentialsEncrypted = credentials.hasOwnProperty("$") && Object.keys(credentials).length === 1; @@ -77,7 +76,7 @@ var api = module.exports = { // Case 4: credentialSecret set // - use it - var setupEncryptionPromise = when.resolve(); + var setupEncryptionPromise = Promise.resolve(); var projectKey = false; var activeProject; @@ -134,7 +133,7 @@ var api = module.exports = { log.warn(log._("nodes.credentials.error",{message:err.toString()})) var error = new Error("Failed to decrypt credentials"); error.code = "credentials_load_failed"; - return when.reject(error); + throw error; } } dirty = true; @@ -163,7 +162,7 @@ var api = module.exports = { log.warn(log._("nodes.credentials.error",{message:err.toString()})) var error = new Error("Failed to decrypt credentials"); error.code = "credentials_load_failed"; - return when.reject(error); + throw error; } } dirty = true; @@ -217,9 +216,9 @@ var api = module.exports = { // This is a project with a bad key. Mark it as invalid // TODO: this delves too deep into Project structure activeProject.credentialSecretInvalid = true; - return when.reject(error); + throw error; } - return when.reject(error); + throw error; } // These are encrypted credentials try { @@ -235,9 +234,9 @@ var api = module.exports = { // This is a project with a bad key. Mark it as invalid // TODO: this delves too deep into Project structure activeProject.credentialSecretInvalid = true; - return when.reject(error); + throw error; } - return when.reject(error); + throw error; } } else { credentialCache = credentials; @@ -257,12 +256,11 @@ var api = module.exports = { * @param creds an object of credential key/value pairs * @return a promise for backwards compatibility TODO: can this be removed? */ - add: function (id, creds) { + add: async function (id, creds) { if (!credentialCache.hasOwnProperty(id) || JSON.stringify(creds) !== JSON.stringify(credentialCache[id])) { credentialCache[id] = creds; dirty = true; } - return when.resolve(); }, /** @@ -293,7 +291,7 @@ var api = module.exports = { * @param config a flow config * @return a promise for the saving of credentials to storage */ - clean: function (config) { + clean: async function (config) { var existingIds = {}; config.forEach(function(n) { existingIds[n.id] = true; @@ -313,7 +311,6 @@ var api = module.exports = { if (deletedCredentials) { dirty = true; } - return when.resolve(); }, /** @@ -432,7 +429,7 @@ var api = module.exports = { getKeyType: function() { return encryptionKeyType; }, - export: function() { + export: async function() { var result = credentialCache; if (encryptionEnabled) { @@ -455,7 +452,7 @@ var api = module.exports = { return result; }) } else { - return when.resolve(result); + return result; } } } diff --git a/packages/node_modules/@node-red/runtime/lib/nodes/index.js b/packages/node_modules/@node-red/runtime/lib/nodes/index.js index 42fcd72f6..7c6b6085e 100644 --- a/packages/node_modules/@node-red/runtime/lib/nodes/index.js +++ b/packages/node_modules/@node-red/runtime/lib/nodes/index.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var when = require("when"); var path = require("path"); var fs = require("fs"); var clone = require("clone"); @@ -29,7 +28,7 @@ var context = require("./context"); var Node = require("./Node"); var log; -var events = require("../events"); +const events = require("@node-red/util").events; var settings; @@ -188,7 +187,7 @@ module.exports = { getContext: context.get, - paletteEditorEnabled: registry.paletteEditorEnabled, + installerEnabled: registry.installerEnabled, installModule: installModule, uninstallModule: uninstallModule, diff --git a/packages/node_modules/@node-red/runtime/lib/settings.js b/packages/node_modules/@node-red/runtime/lib/settings.js index 16667d177..989b83d9b 100644 --- a/packages/node_modules/@node-red/runtime/lib/settings.js +++ b/packages/node_modules/@node-red/runtime/lib/settings.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var when = require("when"); var clone = require("clone"); var assert = require("assert"); var log = require("@node-red/util").log; // TODO: separate module @@ -90,10 +89,10 @@ var persistentSettings = { globalSettings[prop] = clone(value); try { assert.deepEqual(current,value); - return when.resolve(); } catch(err) { return storage.saveSettings(clone(globalSettings)); } + return Promise.resolve(); }, delete: function(prop) { if (localSettings.hasOwnProperty(prop)) { @@ -106,7 +105,7 @@ var persistentSettings = { delete globalSettings[prop]; return storage.saveSettings(clone(globalSettings)); } - return when.resolve(); + return Promise.resolve(); }, available: function() { @@ -180,7 +179,7 @@ var persistentSettings = { userSettings[username] = settings; try { assert.deepEqual(current,settings); - return when.resolve(); + return Promise.resolve(); } catch(err) { globalSettings.users = userSettings; return storage.saveSettings(clone(globalSettings)); diff --git a/packages/node_modules/@node-red/runtime/lib/storage/index.js b/packages/node_modules/@node-red/runtime/lib/storage/index.js index d3350a95e..f5e07e254 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/index.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/index.js @@ -14,11 +14,10 @@ * limitations under the License. **/ -var when = require('when'); var Path = require('path'); var crypto = require('crypto'); -var log = require("@node-red/util").log; // TODO: separate module +var log = require("@node-red/util").log; var runtime; var storageModule; @@ -50,15 +49,13 @@ function is_malicious(path) { } var storageModuleInterface = { - init: function(_runtime) { + init: async function(_runtime) { runtime = _runtime; - try { - storageModule = moduleSelector(runtime.settings); - settingsAvailable = storageModule.hasOwnProperty("getSettings") && storageModule.hasOwnProperty("saveSettings"); - sessionsAvailable = storageModule.hasOwnProperty("getSessions") && storageModule.hasOwnProperty("saveSessions"); - } catch (e) { - return when.reject(e); - } + // Any errors thrown by the module will get passed up to the called + // as a rejected promise + storageModule = moduleSelector(runtime.settings); + settingsAvailable = storageModule.hasOwnProperty("getSettings") && storageModule.hasOwnProperty("saveSettings"); + sessionsAvailable = storageModule.hasOwnProperty("getSessions") && storageModule.hasOwnProperty("saveSessions"); if (!!storageModule.projects) { var projectsEnabled = false; if (runtime.settings.hasOwnProperty("editorTheme") && runtime.settings.editorTheme.hasOwnProperty("projects")) { @@ -73,7 +70,7 @@ var storageModuleInterface = { } return storageModule.init(runtime.settings,runtime); }, - getFlows: function() { + getFlows: async function() { return storageModule.getFlows().then(function(flows) { return storageModule.getCredentials().then(function(creds) { var result = { @@ -85,14 +82,14 @@ var storageModuleInterface = { }) }); }, - saveFlows: function(config, user) { + saveFlows: async function(config, user) { var flows = config.flows; var credentials = config.credentials; var credentialSavePromise; if (config.credentialsDirty) { credentialSavePromise = storageModule.saveCredentials(credentials); } else { - credentialSavePromise = when.resolve(); + credentialSavePromise = Promise.resolve(); } delete config.credentialsDirty; @@ -105,64 +102,60 @@ var storageModuleInterface = { // getCredentials: function() { // return storageModule.getCredentials(); // }, - saveCredentials: function(credentials) { + saveCredentials: async function(credentials) { return storageModule.saveCredentials(credentials); }, - getSettings: function() { + getSettings: async function() { if (settingsAvailable) { return storageModule.getSettings(); } else { - return when.resolve(null); + return null } }, - saveSettings: function(settings) { + saveSettings: async function(settings) { if (settingsAvailable) { return settingsSaveMutex.runExclusive(() => storageModule.saveSettings(settings)) - } else { - return when.resolve(); } }, - getSessions: function() { + getSessions: async function() { if (sessionsAvailable) { return storageModule.getSessions(); } else { - return when.resolve(null); + return null } }, - saveSessions: function(sessions) { + saveSessions: async function(sessions) { if (sessionsAvailable) { return storageModule.saveSessions(sessions); - } else { - return when.resolve(); } }, /* Library Functions */ - getLibraryEntry: function(type, path) { + getLibraryEntry: async function(type, path) { if (is_malicious(path)) { var err = new Error(); err.code = "forbidden"; - return when.reject(err); + throw err; } return storageModule.getLibraryEntry(type, path); }, - saveLibraryEntry: function(type, path, meta, body) { + saveLibraryEntry: async function(type, path, meta, body) { if (is_malicious(path)) { var err = new Error(); err.code = "forbidden"; - return when.reject(err); + throw err; } return storageModule.saveLibraryEntry(type, path, meta, body); }, /* Deprecated functions */ - getAllFlows: function() { + getAllFlows: async function() { if (storageModule.hasOwnProperty("getAllFlows")) { return storageModule.getAllFlows(); } else { if (libraryFlowsCachedResult) { - return Promise.resolve(libraryFlowsCachedResult); + return libraryFlowsCachedResult; } else { return listFlows("/").then(function(result) { libraryFlowsCachedResult = result; @@ -175,7 +168,7 @@ var storageModuleInterface = { if (is_malicious(fn)) { var err = new Error(); err.code = "forbidden"; - return when.reject(err); + throw err; } if (storageModule.hasOwnProperty("getFlow")) { return storageModule.getFlow(fn); @@ -188,7 +181,7 @@ var storageModuleInterface = { if (is_malicious(fn)) { var err = new Error(); err.code = "forbidden"; - return when.reject(err); + throw err; } libraryFlowsCachedResult = null; if (storageModule.hasOwnProperty("saveFlow")) { @@ -204,40 +197,36 @@ var storageModuleInterface = { 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.join(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.replace(/\.json$/, ""); - } - result.f = result.f || []; - result.f.push(name); - } else { - result.d = result.d || {}; - result.d[res[i]] = r.value; - //console.log(">",r.value); + const promises = []; + res.forEach(function(r) { + if (typeof r === "string") { + promises.push(listFlows(Path.join(path,r))); + } else { + promises.push(Promise.resolve(r)); + } + }); + return Promise.all(promises).then(res2 => { + let i = 0; + const result = {}; + res2.forEach(function(r) { + // TODO: name||fn + if (r.fn) { + var name = r.name; + if (!name) { + name = r.fn.replace(/\.json$/, ""); } - i++; - }); - resolve(result); + result.f = result.f || []; + result.f.push(name); + } else { + result.d = result.d || {}; + result.d[res[i]] = r; + //console.log(">",r.value); + } + i++; }); + return result; }); }); } - - module.exports = storageModuleInterface; diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/library.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/library.js index 22f01c978..fbcb44e2f 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/library.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/library.js @@ -15,9 +15,7 @@ **/ var fs = require('fs-extra'); -var when = require('when'); var fspath = require("path"); -var nodeFn = require('when/node/function'); var util = require("./util"); @@ -90,14 +88,14 @@ function getLibraryEntry(type,path) { var rootPath = fspath.join(libDir,type,path); // don't create the folder if it does not exist - we are only reading.... - return nodeFn.call(fs.lstat, rootPath).then(function(stats) { + return fs.lstat(rootPath).then(function(stats) { if (stats.isFile()) { return getFileBody(root,path); } if (path.substr(-1) == '/') { path = path.substr(0,path.length-1); } - return nodeFn.call(fs.readdir, rootPath).then(function(fns) { + return fs.readdir(rootPath).then(function(fns) { var dirs = []; var files = []; fns.sort().filter(function(fn) { @@ -143,21 +141,19 @@ function getLibraryEntry(type,path) { } module.exports = { - init: function(_settings) { + init: async function(_settings) { settings = _settings; libDir = fspath.join(settings.userDir,"lib"); libFlowsDir = fspath.join(libDir,"flows"); if (!settings.readOnly) { return fs.ensureDir(libFlowsDir); - } else { - return when.resolve(); } }, getLibraryEntry: getLibraryEntry, - saveLibraryEntry: function(type,path,meta,body) { + saveLibraryEntry: async function(type,path,meta,body) { if (settings.readOnly) { - return when.resolve(); + return; } if (type === "flows" && !path.endsWith(".json")) { path += ".json"; diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/Project.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/Project.js index 0fbf89de4..d87001f1f 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/Project.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/Project.js @@ -16,7 +16,6 @@ var fs = require('fs-extra'); -var when = require('when'); var fspath = require("path"); var os = require('os'); @@ -27,6 +26,7 @@ var sshKeys = require("./ssh"); var settings; var runtime; var log = require("@node-red/util").log; +const events = require("@node-red/util").events; var projectsDir; @@ -108,12 +108,12 @@ Project.prototype.load = function () { // package.json isn't valid JSON... is a merge underway? project.package = {}; } - })); + }).catch(err => {})); // if (missingFiles.indexOf('README.md') === -1) { project.paths['README.md'] = fspath.join(project.paths.root,"README.md"); promises.push(fs.readFile(fspath.join(project.path,project.paths['README.md']),"utf8").then(function(content) { project.description = content; - })); + }).catch(err => {})); } else { project.description = ""; } @@ -133,9 +133,9 @@ Project.prototype.load = function () { // project.paths.credentialsFile = fspath.join(project.path,"flow_cred.json"); // } - promises.push(project.loadRemotes()); + promises.push(project.loadRemotes().catch(err => {})); - return when.settle(promises).then(function(results) { + return Promise.all(promises).then(function(results) { return project; }) }); @@ -239,7 +239,7 @@ Project.prototype.isMerging = function() { return this.merging; } -Project.prototype.update = function (user, data) { +Project.prototype.update = async function (user, data) { var username; if (!user) { username = "_"; @@ -279,7 +279,7 @@ Project.prototype.update = function (user, data) { this.credentialSecret !== existingSecret) { // key doesn't match provided existing key var e = new Error("Cannot change credentialSecret without current key"); e.code = "missing_current_credential_key"; - return when.reject(e); + throw e; } this.credentialSecret = secret; @@ -292,7 +292,7 @@ Project.prototype.update = function (user, data) { if (this.missingFiles.indexOf('package.json') !== -1) { if (!data.files || !data.files.package) { // Cannot update a project that doesn't have a known package.json - return Promise.reject("Cannot update project with missing package.json"); + throw new Error("Cannot update project with missing package.json"); } } @@ -302,7 +302,7 @@ Project.prototype.update = function (user, data) { // We have a package file. It could be one that doesn't exist yet, // or it does exist and we need to load it. if (!/package\.json$/.test(data.files.package)) { - return Promise.reject("Invalid package file: "+data.files.package) + return new Error("Invalid package file: "+data.files.package) } var root = data.files.package.substring(0,data.files.package.length-12); this.paths.root = root; @@ -391,20 +391,20 @@ Project.prototype.update = function (user, data) { modifyRemotesPromise = modifyRemotesPromise.then(function() { return project.loadRemotes(); }); - promises.push(modifyRemotesPromise); + promises.push(modifyRemotesPromise.catch(err => {})); } } } if (saveSettings) { - promises.push(settings.set("projects",globalProjectSettings)); + promises.push(settings.set("projects",globalProjectSettings).catch(err => {})); } var modifiedFiles = []; if (saveREADME) { - promises.push(util.writeFile(fspath.join(this.path,this.paths['README.md']), this.description)); + promises.push(util.writeFile(fspath.join(this.path,this.paths['README.md']), this.description).catch(err => {})); modifiedFiles.push('README.md'); } if (savePackage) { @@ -416,10 +416,10 @@ Project.prototype.update = function (user, data) { } this.package = Object.assign(currentPackage,this.package); return util.writeFile(fspath.join(project.path,this.paths['package.json']), JSON.stringify(this.package,"",4)); - })); + }).catch(err => {})); modifiedFiles.push('package.json'); } - return when.settle(promises).then(function(res) { + return Promise.all(promises).then(function(res) { var gitSettings = getUserGitSettings(user) || {}; var workflowMode = (gitSettings.workflow||{}).mode || "manual"; if (workflowMode === 'auto') { @@ -533,7 +533,7 @@ Project.prototype.status = function(user, includeRemote) { result.merging = true; if (!self.merging) { self.merging = true; - runtime.events.emit("runtime-event",{ + events.emit("runtime-event",{ id:"runtime-state", payload:{ type:"warning", @@ -557,7 +557,7 @@ Project.prototype.status = function(user, includeRemote) { } if (result.commits.total === 0 && Object.keys(result.files).length === 0) { if (!self.empty) { - runtime.events.emit("runtime-event",{ + events.emit("runtime-event",{ id:"runtime-state", payload:{ type:"warning", @@ -571,9 +571,9 @@ Project.prototype.status = function(user, includeRemote) { } else { if (self.empty) { if (self.paths.flowFile) { - runtime.events.emit("runtime-event",{id:"runtime-state",retain:true}); + events.emit("runtime-event",{id:"runtime-state",retain:true}); } else { - runtime.events.emit("runtime-event",{ + events.emit("runtime-event",{ id:"runtime-state", payload:{ type:"warning", @@ -944,32 +944,17 @@ function createDefaultProject(user, project) { } function checkProjectFiles(project) { var promises = []; - var paths = []; + var missing = []; for (var file in defaultFileSet) { if (defaultFileSet.hasOwnProperty(file)) { - paths.push(file); - promises.push(fs.stat(fspath.join(project.path,project.paths.root,file))); + (function(f) { + promises.push(fs.stat(fspath.join(project.path,project.paths.root,f)).catch(err => { + missing.push(f); + })); + })(file); } } - return when.settle(promises).then(function(results) { - var missing = []; - results.forEach(function(result,i) { - if (result.state === 'rejected') { - missing.push(paths[i]); - } - }); - return missing; - }).then(function(missing) { - // if (createMissing) { - // var promises = []; - // missing.forEach(function(file) { - // promises.push(util.writeFile(fspath.join(projectPath,file),defaultFileSet[file](project))); - // }); - // return promises; - // } else { - return missing; - // } - }); + return Promise.all(promises).then(() => missing); } function createProject(user, metadata) { var username; diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/index.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/index.js index dbcb5fb61..e1ded4337 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/index.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/index.js @@ -14,8 +14,6 @@ * limitations under the License. **/ -var exec = require("../../../../exec"); - var authResponseServer = require('./authServer').ResponseServer; var sshResponseServer = require('./authServer').ResponseSSHServer; var clone = require('clone'); @@ -23,7 +21,7 @@ var path = require("path"); var gitCommand = "git"; var gitVersion; -var log = require("@node-red/util").log; +const {log,exec} = require("@node-red/util"); function runGitCommand(args,cwd,env,emit) { log.trace(gitCommand + JSON.stringify(args)); diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js index 5e1d4f15b..3bbeb823b 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/index.js @@ -15,9 +15,7 @@ **/ var fs = require('fs-extra'); -var when = require('when'); var fspath = require("path"); -var nodeFn = require('when/node/function'); var crypto = require('crypto'); var storageSettings = require("../settings"); @@ -30,6 +28,7 @@ var Projects = require("./Project"); var settings; var runtime; var log = require("@node-red/util").log; +const events = require("@node-red/util").events; var projectsEnabled = false; var projectLogMessages = []; @@ -223,7 +222,6 @@ function loadProject(name) { function getProject(user, name) { checkActiveProject(name); - //return when.resolve(activeProject.info); return Promise.resolve(activeProject.export()); } @@ -358,11 +356,11 @@ function getActiveProject(user) { function reloadActiveProject(action) { return runtime.nodes.stopFlows().then(function() { return runtime.nodes.loadFlows(true).then(function() { - runtime.events.emit("runtime-event",{id:"project-update", payload:{ project: activeProject.name, action:action}}); + events.emit("runtime-event",{id:"project-update", payload:{ project: activeProject.name, action:action}}); }).catch(function(err) { // We're committed to the project change now, so notify editors // that it has changed. - runtime.events.emit("runtime-event",{id:"project-update", payload:{ project: activeProject.name, action:action}}); + events.emit("runtime-event",{id:"project-update", payload:{ project: activeProject.name, action:action}}); throw err; }); }); @@ -495,7 +493,7 @@ var flowsFileBackup; var credentialsFile; var credentialsFileBackup; -function getFlows() { +async function getFlows() { if (!initialFlowLoadComplete) { initialFlowLoadComplete = true; log.info(log._("storage.localfilesystem.user-dir",{path:settings.userDir})); @@ -522,25 +520,25 @@ function getFlows() { log.warn("Project repository is empty"); error = new Error("Project repository is empty"); error.code = "project_empty"; - return when.reject(error); + throw error; } if (activeProject.missingFiles && activeProject.missingFiles.indexOf('package.json') !== -1) { log.warn("Project missing package.json"); error = new Error("Project missing package.json"); error.code = "missing_package_file"; - return when.reject(error); + throw error; } if (!activeProject.getFlowFile()) { log.warn("Project has no flow file"); error = new Error("Project has no flow file"); error.code = "missing_flow_file"; - return when.reject(error); + throw error; } if (activeProject.isMerging()) { log.warn("Project has unmerged changes"); error = new Error("Project has unmerged changes. Cannot load flows"); error.code = "git_merge_conflict"; - return when.reject(error); + throw error; } } @@ -554,14 +552,14 @@ function getFlows() { }); } -function saveFlows(flows, user) { +async function saveFlows(flows, user) { if (settings.readOnly) { - return when.resolve(); + return } if (activeProject && activeProject.isMerging()) { var error = new Error("Project has unmerged changes. Cannot deploy new flows"); error.code = "git_merge_conflict"; - return when.reject(error); + throw error; } flowsFileExists = true; @@ -589,9 +587,9 @@ function getCredentials() { return util.readFile(credentialsFile,credentialsFileBackup,{},'credentials'); } -function saveCredentials(credentials) { +async function saveCredentials(credentials) { if (settings.readOnly) { - return when.resolve(); + return; } var credentialData; diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index.js index 25dacd3b1..cafe9bcb7 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index.js @@ -15,7 +15,6 @@ **/ var fs = require('fs-extra'); -var when = require('when'); var fspath = require("path"); var keygen = require("./keygen"); diff --git a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/sessions.js b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/sessions.js index 6b4deaa5a..575b0c056 100644 --- a/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/sessions.js +++ b/packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/sessions.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var when = require('when'); var fs = require('fs-extra'); var fspath = require("path"); @@ -30,8 +29,8 @@ module.exports = { settings = _settings; sessionsFile = fspath.join(settings.userDir,".sessions.json"); }, - getSessions: function() { - return when.promise(function(resolve,reject) { + getSessions: async function() { + return new Promise(function(resolve,reject) { fs.readFile(sessionsFile,'utf8',function(err,data){ if (!err) { try { @@ -44,9 +43,9 @@ module.exports = { }) }); }, - saveSessions: function(sessions) { + saveSessions: async function(sessions) { if (settings.readOnly) { - return when.resolve(); + return; } return util.writeFile(sessionsFile,JSON.stringify(sessions)); } diff --git a/packages/node_modules/@node-red/runtime/package.json b/packages/node_modules/@node-red/runtime/package.json index 17622c6b4..1a549e0c6 100644 --- a/packages/node_modules/@node-red/runtime/package.json +++ b/packages/node_modules/@node-red/runtime/package.json @@ -22,7 +22,6 @@ "clone": "2.1.2", "express": "4.17.1", "fs-extra": "8.1.0", - "json-stringify-safe": "5.0.1", - "when": "3.7.8" + "json-stringify-safe": "5.0.1" } } diff --git a/packages/node_modules/@node-red/util/index.js b/packages/node_modules/@node-red/util/index.js index 66ac91bd3..29e1a480c 100644 --- a/packages/node_modules/@node-red/util/index.js +++ b/packages/node_modules/@node-red/util/index.js @@ -17,6 +17,8 @@ const log = require("./lib/log"); const i18n = require("./lib/i18n"); const util = require("./lib/util"); +const events = require("./lib/events"); +const exec = require("./lib/exec"); /** * This module provides common utilities for the Node-RED runtime and editor @@ -54,4 +56,18 @@ module.exports = { * @memberof @node-red/util */ util: util, + + /** + * Runtime events + * @mixes @node-red/util_event + * @memberof @node-red/util + */ + events: events, + + /** + * Run system commands with event-log integration + * @mixes @node-red/util_exec + * @memberof @node-red/util + */ + exec: exec } diff --git a/packages/node_modules/@node-red/runtime/lib/events.js b/packages/node_modules/@node-red/util/lib/events.js similarity index 92% rename from packages/node_modules/@node-red/runtime/lib/events.js rename to packages/node_modules/@node-red/util/lib/events.js index 8e6935222..df45b4d16 100644 --- a/packages/node_modules/@node-red/runtime/lib/events.js +++ b/packages/node_modules/@node-red/util/lib/events.js @@ -14,6 +14,11 @@ * limitations under the License. **/ + /** + * Runtime events + * @mixin @node-red/util_events + */ + const events = new (require("events")).EventEmitter(); @@ -45,14 +50,14 @@ module.exports = events; /** * Runtime events emitter - * @mixin @node-red/runtime_events + * @mixin @node-red/util_events */ /** * Register an event listener for a runtime event * @name on * @function - * @memberof @node-red/runtime_events + * @memberof @node-red/util_events * @param {String} eventName - the name of the event to listen to * @param {Function} listener - the callback function for the event */ @@ -61,7 +66,7 @@ module.exports = events; * Emit an event to all of its registered listeners * @name emit * @function - * @memberof @node-red/runtime_events + * @memberof @node-red/util_events * @param {String} eventName - the name of the event to emit * @param {any} ...args - the arguments to pass in the event * @return {Boolean} - whether the event had listeners or not diff --git a/packages/node_modules/@node-red/runtime/lib/exec.js b/packages/node_modules/@node-red/util/lib/exec.js similarity index 67% rename from packages/node_modules/@node-red/runtime/lib/exec.js rename to packages/node_modules/@node-red/util/lib/exec.js index 0ef3c069c..c7197ef65 100644 --- a/packages/node_modules/@node-red/runtime/lib/exec.js +++ b/packages/node_modules/@node-red/util/lib/exec.js @@ -1,4 +1,4 @@ -/** +/*! * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,19 +14,41 @@ * limitations under the License. **/ -const child_process = require('child_process'); -const { util } = require('@node-red/util'); +/** + * Run system commands with event-log integration + * @mixin @node-red/util_exec + */ -var events; +const child_process = require('child_process'); +const events = require("./events"); +const util = require('./util'); function logLines(id,type,data) { events.emit("event-log", {id:id,payload:{ts: Date.now(),data:data,type:type}}); } module.exports = { - init: function(_runtime) { - events = _runtime.events; - }, + /** + * Run a system command with stdout/err being emitted as 'event-log' events + * on the @node-red/util/events handler. + * + * The main arguments to this function are the same as passed to `child_process.spawn` + * + * @param {String} command - the command to run + * @param {Array} args - arguments for the command + * @param {Object} options - options to pass child_process.spawn + * @param {Boolean} emit - whether to emit events to the event-log for each line of stdout/err + * @return {Promise} A promise that resolves (rc=0) or rejects (rc!=0) when the command completes. The value + * of the promise is an object of the form: + * + * { + * code: , + * stdout: , + * stderr: + * } + + * @memberof @node-red/util_exec + */ run: function(command,args,options,emit) { var invocationId = util.generateId(); diff --git a/packages/node_modules/@node-red/util/lib/i18n.js b/packages/node_modules/@node-red/util/lib/i18n.js index d95f4bec6..cce2e8149 100644 --- a/packages/node_modules/@node-red/util/lib/i18n.js +++ b/packages/node_modules/@node-red/util/lib/i18n.js @@ -22,7 +22,6 @@ var i18n = require("i18next"); -var when = require("when"); var path = require("path"); var fs = require("fs"); @@ -38,16 +37,16 @@ var initPromise; */ function registerMessageCatalogs(catalogs) { var promises = catalogs.map(function(catalog) { - return registerMessageCatalog(catalog.namespace,catalog.dir,catalog.file); + return registerMessageCatalog(catalog.namespace,catalog.dir,catalog.file).catch(err => {}); }); - return when.settle(promises); + return Promise.all(promises); } /** * Register a message catalog with i18n. * @memberof @node-red/util_i18n */ -function registerMessageCatalog(namespace,dir,file) { +async function registerMessageCatalog(namespace,dir,file) { return initPromise.then(function() { return new Promise((resolve,reject) => { resourceMap[namespace] = { basedir:dir, file:file, lngs: []}; @@ -147,7 +146,7 @@ function init() { if (!initPromise) { // Keep this as a 'when' promise as top-level red.js uses 'otherwise' // and embedded users of NR may have copied that. - initPromise = when.promise((resolve,reject) => { + initPromise = new Promise((resolve,reject) => { i18n.use(MessageFileLoader); var opt = { // debug: true, diff --git a/packages/node_modules/@node-red/util/lib/log.js b/packages/node_modules/@node-red/util/lib/log.js index 8d7b84966..341019080 100644 --- a/packages/node_modules/@node-red/util/lib/log.js +++ b/packages/node_modules/@node-red/util/lib/log.js @@ -1,4 +1,4 @@ -/** +/*! * Copyright JS Foundation and other contributors, http://js.foundation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,7 +12,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * @ignore **/ /** @@ -91,7 +90,7 @@ var consoleLogger = function(msg) { } catch(e){ message = 'Exception trying to log: '+util.inspect(message); } - + util.log("["+levelNames[msg.level]+"] "+(msg.type?"["+msg.type+":"+(msg.name||msg.id)+"] ":"")+message); } } diff --git a/packages/node_modules/@node-red/util/package.json b/packages/node_modules/@node-red/util/package.json index 9d447a280..41e858c7a 100644 --- a/packages/node_modules/@node-red/util/package.json +++ b/packages/node_modules/@node-red/util/package.json @@ -20,7 +20,6 @@ "json-stringify-safe": "5.0.1", "jsonata": "1.8.4", "lodash.clonedeep": "^4.5.0", - "moment-timezone": "0.5.32", - "when": "3.7.8" + "moment-timezone": "0.5.32" } } diff --git a/packages/node_modules/node-red/lib/red.js b/packages/node_modules/node-red/lib/red.js index 684ff6d8a..e46e40e26 100644 --- a/packages/node_modules/node-red/lib/red.js +++ b/packages/node_modules/node-red/lib/red.js @@ -92,14 +92,39 @@ module.exports = { * @memberof node-red */ start: function() { - return runtime.start().then(function() { + // The top level red.js has always used 'otherwise' on the promise returned + // here. This is a non-standard promise function coming from our early use + // of the when.js library. + // We want to remove all dependency on when.js as native Promises now exist. + // But we have the issue that some embedders of Node-RED may have copied our + // top-level red.js a bit too much. + // + let startPromise = runtime.start().then(function() { if (apiEnabled) { return api.start(); } }); + startPromise._then = startPromise.then; + startPromise.then = function(resolve,reject) { + var inner = startPromise._then(resolve,reject); + inner.otherwise = function(cb) { + redUtil.log.error("**********************************************"); + redUtil.log.error("* Deprecated call to RED.start().otherwise() *"); + redUtil.log.error("* This will be removed in Node-RED 2.x *"); + redUtil.log.error("* Use RED.start().catch() instead *") + redUtil.log.error("**********************************************"); + return inner.catch(cb); + } + return inner; + } + return startPromise; }, /** * Stop the Node-RED application. + * + * Once called, Node-RED should not be restarted until the Node.JS process is + * restarted. + * * @return {Promise} - resolves when complete * @memberof node-red */ @@ -140,10 +165,10 @@ module.exports = { /** * Runtime events emitter - * @see @node-red/runtime_events + * @see @node-red/util_events * @memberof node-red */ - events: runtime.events, + events: redUtil.events, /** * Runtime hooks engine diff --git a/packages/node_modules/node-red/red.js b/packages/node_modules/node-red/red.js index 32639ea3c..55e355a7c 100755 --- a/packages/node_modules/node-red/red.js +++ b/packages/node_modules/node-red/red.js @@ -429,7 +429,7 @@ httpsPromise.then(function(startupHttps) { } else { RED.log.info(RED.log._("server.headless-mode")); } - }).otherwise(function(err) { + }).catch(function(err) { RED.log.error(RED.log._("server.failed-to-start")); if (err.stack) { RED.log.error(err.stack); @@ -468,4 +468,5 @@ httpsPromise.then(function(startupHttps) { }).catch(function(err) { console.log("Failed to get https settings: " + err); + console.log(err.stack) }); diff --git a/test/nodes/core/network/21-httprequest_spec.js b/test/nodes/core/network/21-httprequest_spec.js index ab9020a64..e9792dd54 100644 --- a/test/nodes/core/network/21-httprequest_spec.js +++ b/test/nodes/core/network/21-httprequest_spec.js @@ -14,7 +14,6 @@ * limitations under the License. **/ -var when = require("when"); var http = require("http"); var https = require("https"); var should = require("should"); diff --git a/test/nodes/core/network/22-websocket_spec.js b/test/nodes/core/network/22-websocket_spec.js index e13b513c8..995248279 100644 --- a/test/nodes/core/network/22-websocket_spec.js +++ b/test/nodes/core/network/22-websocket_spec.js @@ -15,7 +15,6 @@ **/ var ws = require("ws"); -var when = require("when"); var should = require("should"); var helper = require("node-red-node-test-helper"); var websocketNode = require("nr-test-utils").require("@node-red/nodes/core/network/22-websocket.js"); @@ -27,7 +26,7 @@ function getWsUrl(path) { } function createClient(listenerid) { - return when.promise(function(resolve, reject) { + return new Promise(function(resolve, reject) { var node = helper.getNode(listenerid); var url = getWsUrl(node.path); var sock = new ws(url); @@ -300,23 +299,33 @@ describe('websocket Node', function() { { id: "n2", type: "websocket out", server: "n1" }, { id: "n3", type: "helper", wires: [["n2"]] }]; helper.load(websocketNode, flow, function() { - var def1 = when.defer(), - def2 = when.defer(); - when.all([createClient("n1"), createClient("n1")]).then(function(socks) { - socks[0].on("message", function(msg, flags) { - msg.should.equal("hello"); - def1.resolve(); - }); - socks[1].on("message", function(msg, flags) { - msg.should.equal("hello"); - def2.resolve(); - }); + Promise.all([createClient("n1"), createClient("n1")]).then(function(socks) { + var promises = [ + new Promise((resolve,reject) => { + socks[0].on("message", function(msg, flags) { + try { + msg.should.equal("hello"); + resolve(); + } catch(err) { + reject(err); + } + }); + }), + new Promise((resolve,reject) => { + socks[1].on("message", function(msg, flags) { + try { + msg.should.equal("hello"); + resolve(); + } catch(err) { + reject(err); + } + }); + }) + ]; helper.getNode("n3").send({ payload: "hello" }); - return when.all([def1.promise, def2.promise]).then(function() { - done(); - }); + return Promise.all(promises).then(() => {done()}); }).catch(function(err) { done(err); }); diff --git a/test/unit/@node-red/editor-api/lib/admin/flow_spec.js b/test/unit/@node-red/editor-api/lib/admin/flow_spec.js index 278c6a3f3..807fc8fb9 100644 --- a/test/unit/@node-red/editor-api/lib/admin/flow_spec.js +++ b/test/unit/@node-red/editor-api/lib/admin/flow_spec.js @@ -19,7 +19,6 @@ var request = require('supertest'); var express = require('express'); var bodyParser = require('body-parser'); var sinon = require('sinon'); -var when = require('when'); var NR_TEST_UTILS = require("nr-test-utils"); diff --git a/test/unit/@node-red/editor-api/lib/admin/nodes_spec.js b/test/unit/@node-red/editor-api/lib/admin/nodes_spec.js index f921d907d..872f76e23 100644 --- a/test/unit/@node-red/editor-api/lib/admin/nodes_spec.js +++ b/test/unit/@node-red/editor-api/lib/admin/nodes_spec.js @@ -19,7 +19,6 @@ var request = require('supertest'); var express = require('express'); var bodyParser = require('body-parser'); var sinon = require('sinon'); -var when = require('when'); var NR_TEST_UTILS = require("nr-test-utils"); diff --git a/test/unit/@node-red/editor-api/lib/auth/index_spec.js b/test/unit/@node-red/editor-api/lib/auth/index_spec.js index 3cf0111d6..def2335a7 100644 --- a/test/unit/@node-red/editor-api/lib/auth/index_spec.js +++ b/test/unit/@node-red/editor-api/lib/auth/index_spec.js @@ -15,7 +15,6 @@ **/ var should = require("should"); -var when = require("when"); var sinon = require("sinon"); var passport = require("passport"); @@ -60,7 +59,7 @@ describe("api/auth/index",function() { describe("revoke", function() { it("revokes a token", function(done) { var revokeToken = sinon.stub(Tokens,"revoke",function() { - return when.resolve(); + return Promise.resolve(); }); var req = { body: { token: "abcdef" } }; diff --git a/test/unit/@node-red/editor-api/lib/auth/strategies_spec.js b/test/unit/@node-red/editor-api/lib/auth/strategies_spec.js index 848aaf99d..d95d78db2 100644 --- a/test/unit/@node-red/editor-api/lib/auth/strategies_spec.js +++ b/test/unit/@node-red/editor-api/lib/auth/strategies_spec.js @@ -15,7 +15,6 @@ **/ var should = require("should"); -var when = require('when'); var sinon = require('sinon'); var NR_TEST_UTILS = require("nr-test-utils"); @@ -37,7 +36,7 @@ describe("api/auth/strategies", function() { it('Handles authentication failure',function(done) { userAuthentication = sinon.stub(Users,"authenticate",function(username,password) { - return when.resolve(null); + return Promise.resolve(null); }); strategies.passwordTokenExchange({},"user","password","scope",function(err,token) { @@ -53,7 +52,7 @@ describe("api/auth/strategies", function() { it('Handles scope overreach',function(done) { userAuthentication = sinon.stub(Users,"authenticate",function(username,password) { - return when.resolve({username:"user",permissions:"read"}); + return Promise.resolve({username:"user",permissions:"read"}); }); strategies.passwordTokenExchange({},"user","password","*",function(err,token) { @@ -69,14 +68,14 @@ describe("api/auth/strategies", function() { it('Creates new token on authentication success',function(done) { userAuthentication = sinon.stub(Users,"authenticate",function(username,password) { - return when.resolve({username:"user",permissions:"*"}); + return Promise.resolve({username:"user",permissions:"*"}); }); var tokenDetails = {}; var tokenCreate = sinon.stub(Tokens,"create",function(username,client,scope) { tokenDetails.username = username; tokenDetails.client = client; tokenDetails.scope = scope; - return when.resolve({accessToken: "123456"}); + return Promise.resolve({accessToken: "123456"}); }); strategies.passwordTokenExchange({id:"myclient"},"user","password","read",function(err,token) { @@ -100,7 +99,7 @@ describe("api/auth/strategies", function() { describe("Anonymous Strategy", function() { it('Succeeds if anon user enabled',function(done) { var userDefault = sinon.stub(Users,"default",function() { - return when.resolve("anon"); + return Promise.resolve("anon"); }); strategies.anonymousStrategy._success = strategies.anonymousStrategy.success; strategies.anonymousStrategy.success = function(user) { @@ -113,7 +112,7 @@ describe("api/auth/strategies", function() { }); it('Fails if anon user not enabled',function(done) { var userDefault = sinon.stub(Users,"default",function() { - return when.resolve(null); + return Promise.resolve(null); }); strategies.anonymousStrategy._fail = strategies.anonymousStrategy.fail; strategies.anonymousStrategy.fail = function(err) { @@ -132,7 +131,7 @@ describe("api/auth/strategies", function() { describe("Tokens Strategy", function() { it('Succeeds if tokens user enabled custom header',function(done) { var userTokens = sinon.stub(Users,"tokens",function(token) { - return when.resolve("tokens-"+token); + return Promise.resolve("tokens-"+token); }); var userTokenHeader = sinon.stub(Users,"tokenHeader",function(token) { return "x-test-token"; @@ -148,7 +147,7 @@ describe("api/auth/strategies", function() { }); it('Succeeds if tokens user enabled default header',function(done) { var userTokens = sinon.stub(Users,"tokens",function(token) { - return when.resolve("tokens-"+token); + return Promise.resolve("tokens-"+token); }); var userTokenHeader = sinon.stub(Users,"tokenHeader",function(token) { return "authorization"; @@ -164,7 +163,7 @@ describe("api/auth/strategies", function() { }); it('Fails if tokens user not enabled',function(done) { var userTokens = sinon.stub(Users,"tokens",function() { - return when.resolve(null); + return Promise.resolve(null); }); var userTokenHeader = sinon.stub(Users,"tokenHeader",function(token) { return "authorization"; @@ -187,7 +186,7 @@ describe("api/auth/strategies", function() { describe("Bearer Strategy", function() { it('Rejects invalid token',function(done) { var getToken = sinon.stub(Tokens,"get",function(token) { - return when.resolve(null); + return Promise.resolve(null); }); strategies.bearerStrategy("1234",function(err,user) { @@ -204,10 +203,10 @@ describe("api/auth/strategies", function() { }); it('Accepts valid token',function(done) { var getToken = sinon.stub(Tokens,"get",function(token) { - return when.resolve({user:"user",scope:"scope"}); + return Promise.resolve({user:"user",scope:"scope"}); }); var getUser = sinon.stub(Users,"get",function(username) { - return when.resolve("aUser"); + return Promise.resolve("aUser"); }); strategies.bearerStrategy("1234",function(err,user,opts) { @@ -226,10 +225,10 @@ describe("api/auth/strategies", function() { }); it('Fail if no user for token',function(done) { var getToken = sinon.stub(Tokens,"get",function(token) { - return when.resolve({user:"user",scope:"scope"}); + return Promise.resolve({user:"user",scope:"scope"}); }); var getUser = sinon.stub(Users,"get",function(username) { - return when.resolve(null); + return Promise.resolve(null); }); strategies.bearerStrategy("1234",function(err,user,opts) { @@ -252,7 +251,7 @@ describe("api/auth/strategies", function() { it('Accepts valid client',function(done) { var testClient = {id:"node-red-editor",secret:"not_available"}; var getClient = sinon.stub(Clients,"get",function(client) { - return when.resolve(testClient); + return Promise.resolve(testClient); }); strategies.clientPasswordStrategy(testClient.id,testClient.secret,function(err,client) { @@ -270,7 +269,7 @@ describe("api/auth/strategies", function() { it('Rejects invalid client secret',function(done) { var testClient = {id:"node-red-editor",secret:"not_available"}; var getClient = sinon.stub(Clients,"get",function(client) { - return when.resolve(testClient); + return Promise.resolve(testClient); }); strategies.clientPasswordStrategy(testClient.id,"invalid_secret",function(err,client) { @@ -287,7 +286,7 @@ describe("api/auth/strategies", function() { }); it('Rejects invalid client id',function(done) { var getClient = sinon.stub(Clients,"get",function(client) { - return when.resolve(null); + return Promise.resolve(null); }); strategies.clientPasswordStrategy("invalid_id","invalid_secret",function(err,client) { try { @@ -305,7 +304,7 @@ describe("api/auth/strategies", function() { var userAuthentication; it('Blocks after 5 failures',function(done) { userAuthentication = sinon.stub(Users,"authenticate",function(username,password) { - return when.resolve(null); + return Promise.resolve(null); }); for (var z=0; z<5; z++) { strategies.passwordTokenExchange({},"user","badpassword","scope",function(err,token) { diff --git a/test/unit/@node-red/editor-api/lib/auth/tokens_spec.js b/test/unit/@node-red/editor-api/lib/auth/tokens_spec.js index 2b06932c7..9bb231eb5 100644 --- a/test/unit/@node-red/editor-api/lib/auth/tokens_spec.js +++ b/test/unit/@node-red/editor-api/lib/auth/tokens_spec.js @@ -15,7 +15,6 @@ **/ var should = require("should"); -var when = require("when"); var sinon = require("sinon"); var NR_TEST_UTILS = require("nr-test-utils"); @@ -35,7 +34,7 @@ describe("api/auth/tokens", function() { it('returns a valid token', function(done) { Tokens.init({},{ getSessions:function() { - return when.resolve({"1234":{"user":"fred","expires":Date.now()+1000}}); + return Promise.resolve({"1234":{"user":"fred","expires":Date.now()+1000}}); } }).then(function() { Tokens.get("1234").then(function(token) { @@ -52,7 +51,7 @@ describe("api/auth/tokens", function() { it('returns null for an invalid token', function(done) { Tokens.init({},{ getSessions:function() { - return when.resolve({}); + return Promise.resolve({}); } }).then(function() { Tokens.get("1234").then(function(token) { @@ -66,11 +65,11 @@ describe("api/auth/tokens", function() { }); }); it('returns null for an expired token', function(done) { - var saveSessions = sinon.stub().returns(when.resolve()); + var saveSessions = sinon.stub().returns(Promise.resolve()); var expiryTime = Date.now()+50; Tokens.init({},{ getSessions:function() { - return when.resolve({"1234":{"user":"fred","expires":expiryTime}}); + return Promise.resolve({"1234":{"user":"fred","expires":expiryTime}}); }, saveSessions: saveSessions }).then(function() { @@ -100,10 +99,10 @@ describe("api/auth/tokens", function() { tokens: [{ token: "1234", user: "fred", - }] + }] },{ getSessions:function() { - return when.resolve({}); + return Promise.resolve({}); } }).then(function() { Tokens.get("1234").then(function(token) { @@ -124,11 +123,11 @@ describe("api/auth/tokens", function() { var savedSession; Tokens.init({sessionExpiryTime: 10},{ getSessions:function() { - return when.resolve({}); + return Promise.resolve({}); }, saveSessions:function(sess) { savedSession = sess; - return when.resolve(); + return Promise.resolve(); } }); var expectedExpiryTime = Date.now()+10000; @@ -159,11 +158,11 @@ describe("api/auth/tokens", function() { var savedSession; Tokens.init({},{ getSessions:function() { - return when.resolve({"1234":{"user":"fred","expires":Date.now()+1000}}); + return Promise.resolve({"1234":{"user":"fred","expires":Date.now()+1000}}); }, saveSessions:function(sess) { savedSession = sess; - return when.resolve(); + return Promise.resolve(); } }).then(function() { Tokens.revoke("1234").then(function() { diff --git a/test/unit/@node-red/editor-api/lib/auth/users_spec.js b/test/unit/@node-red/editor-api/lib/auth/users_spec.js index 18a179ac7..e07a35a03 100644 --- a/test/unit/@node-red/editor-api/lib/auth/users_spec.js +++ b/test/unit/@node-red/editor-api/lib/auth/users_spec.js @@ -15,7 +15,6 @@ **/ var should = require("should"); -var when = require('when'); var sinon = require('sinon'); var NR_TEST_UTILS = require("nr-test-utils"); @@ -144,12 +143,12 @@ describe("api/auth/users", function() { Users.init({ type:"credentials", users:function(username) { - return when.resolve({'username':'dave','permissions':'read'}); + return Promise.resolve({'username':'dave','permissions':'read'}); }, authenticate: function(username,password) { authUsername = username; authPassword = password; - return when.resolve({'username':'pete','permissions':'write'}); + return Promise.resolve({'username':'pete','permissions':'write'}); } }); }); diff --git a/test/unit/@node-red/editor-api/lib/editor/comms_spec.js b/test/unit/@node-red/editor-api/lib/editor/comms_spec.js index 8f6f78315..06743e87e 100644 --- a/test/unit/@node-red/editor-api/lib/editor/comms_spec.js +++ b/test/unit/@node-red/editor-api/lib/editor/comms_spec.js @@ -18,7 +18,6 @@ var should = require("should"); var sinon = require("sinon"); const stoppable = require('stoppable'); -var when = require("when"); var http = require('http'); var express = require('express'); var app = express(); @@ -59,7 +58,7 @@ describe("api/editor/comms", function() { var url; var port; before(function(done) { - sinon.stub(Users,"default",function() { return when.resolve(null);}); + sinon.stub(Users,"default",function() { return Promise.resolve(null);}); server = stoppable(http.createServer(function(req,res){app(req,res)})); comms.init(server, {}, {comms: mockComms}); server.listen(listenPort, address); @@ -165,7 +164,7 @@ describe("api/editor/comms", function() { var url; var port; before(function(done) { - sinon.stub(Users,"default",function() { return when.resolve(null);}); + sinon.stub(Users,"default",function() { return Promise.resolve(null);}); server = stoppable(http.createServer(function(req,res){app(req,res)})); comms.init(server, {httpAdminRoot:"/adminPath"}, {comms: mockComms}); server.listen(listenPort, address); @@ -203,7 +202,7 @@ describe("api/editor/comms", function() { var url; var port; before(function(done) { - sinon.stub(Users,"default",function() { return when.resolve(null);}); + sinon.stub(Users,"default",function() { return Promise.resolve(null);}); server = stoppable(http.createServer(function(req,res){app(req,res)})); comms.init(server, {httpAdminRoot:"/adminPath/"}, {comms: mockComms}); server.listen(listenPort, address); @@ -241,7 +240,7 @@ describe("api/editor/comms", function() { var url; var port; before(function(done) { - sinon.stub(Users,"default",function() { return when.resolve(null);}); + sinon.stub(Users,"default",function() { return Promise.resolve(null);}); server = stoppable(http.createServer(function(req,res){app(req,res)})); comms.init(server, {httpAdminRoot:"adminPath"}, {comms: mockComms}); server.listen(listenPort, address); @@ -279,7 +278,7 @@ describe("api/editor/comms", function() { var url; var port; before(function(done) { - sinon.stub(Users,"default",function() { return when.resolve(null);}); + sinon.stub(Users,"default",function() { return Promise.resolve(null);}); server = stoppable(http.createServer(function(req,res){app(req,res)})); comms.init(server, {webSocketKeepAliveTime: 100}, {comms: mockComms}); server.listen(listenPort, address); @@ -345,28 +344,28 @@ describe("api/editor/comms", function() { var getToken; var getUserToken; before(function(done) { - getDefaultUser = sinon.stub(Users,"default",function() { return when.resolve(null);}); + getDefaultUser = sinon.stub(Users,"default",function() { return Promise.resolve(null);}); getUser = sinon.stub(Users,"get", function(username) { if (username == "fred") { - return when.resolve({permissions:"read"}); + return Promise.resolve({permissions:"read"}); } else { - return when.resolve(null); + return Promise.resolve(null); } }); getUserToken = sinon.stub(Users,"tokens", function(token) { if (token == "abcde") { - return when.resolve({user:"wilma", permissions:"*"}) + return Promise.resolve({user:"wilma", permissions:"*"}) } else { - return when.resolve(null); + return Promise.resolve(null); } }); getToken = sinon.stub(Tokens,"get",function(token) { if (token == "1234") { - return when.resolve({user:"fred",scope:["*"]}); + return Promise.resolve({user:"fred",scope:["*"]}); } else if (token == "5678") { - return when.resolve({user:"barney",scope:["*"]}); + return Promise.resolve({user:"barney",scope:["*"]}); } else { - return when.resolve(null); + return Promise.resolve(null); } }); @@ -484,7 +483,7 @@ describe("api/editor/comms", function() { var port; var getDefaultUser; before(function(done) { - getDefaultUser = sinon.stub(Users,"default",function() { return when.resolve({permissions:"read"});}); + getDefaultUser = sinon.stub(Users,"default",function() { return Promise.resolve({permissions:"read"});}); server = stoppable(http.createServer(function(req,res){app(req,res)})); comms.init(server, {adminAuth:{}}, {comms: mockComms}); server.listen(listenPort, address); diff --git a/test/unit/@node-red/editor-api/lib/editor/credentials_spec.js b/test/unit/@node-red/editor-api/lib/editor/credentials_spec.js index 2fc1ea5a3..c5a6c74f8 100644 --- a/test/unit/@node-red/editor-api/lib/editor/credentials_spec.js +++ b/test/unit/@node-red/editor-api/lib/editor/credentials_spec.js @@ -18,7 +18,6 @@ var should = require("should"); var request = require('supertest'); var express = require('express'); var sinon = require('sinon'); -var when = require('when'); var NR_TEST_UTILS = require("nr-test-utils"); diff --git a/test/unit/@node-red/editor-api/lib/editor/index_spec.js b/test/unit/@node-red/editor-api/lib/editor/index_spec.js index e45fcbdba..e142f8984 100644 --- a/test/unit/@node-red/editor-api/lib/editor/index_spec.js +++ b/test/unit/@node-red/editor-api/lib/editor/index_spec.js @@ -28,10 +28,6 @@ var auth = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth"); var log = NR_TEST_UTILS.require("@node-red/util").log; - -var when = require("when"); - - describe("api/editor/index", function() { var app; describe("disabled the editor", function() { diff --git a/test/unit/@node-red/editor-api/lib/editor/theme_spec.js b/test/unit/@node-red/editor-api/lib/editor/theme_spec.js index 67e305f71..55006f71b 100644 --- a/test/unit/@node-red/editor-api/lib/editor/theme_spec.js +++ b/test/unit/@node-red/editor-api/lib/editor/theme_spec.js @@ -17,7 +17,6 @@ var should = require("should"); var express = require('express'); var sinon = require('sinon'); -var when = require('when'); var fs = require("fs"); var app = express(); diff --git a/test/unit/@node-red/editor-api/lib/index_spec.js b/test/unit/@node-red/editor-api/lib/index_spec.js index 1d5e9380b..ec846cf65 100644 --- a/test/unit/@node-red/editor-api/lib/index_spec.js +++ b/test/unit/@node-red/editor-api/lib/index_spec.js @@ -18,7 +18,6 @@ var should = require("should"); var sinon = require("sinon"); var request = require("supertest"); var express = require("express"); -var when = require("when"); var fs = require("fs"); var path = require("path"); diff --git a/test/unit/@node-red/registry/lib/index_spec.js b/test/unit/@node-red/registry/lib/index_spec.js index 753486e9f..75a057730 100644 --- a/test/unit/@node-red/registry/lib/index_spec.js +++ b/test/unit/@node-red/registry/lib/index_spec.js @@ -17,7 +17,6 @@ var should = require("should"); var sinon = require("sinon"); var path = require("path"); -var when = require("when"); var fs = require("fs"); var NR_TEST_UTILS = require("nr-test-utils"); @@ -51,7 +50,7 @@ describe('red/registry/index', function() { describe('#addModule', function() { it('loads the module and returns its info', function(done) { stubs.push(sinon.stub(loader,"addModule",function(module) { - return when.resolve(); + return Promise.resolve(); })); stubs.push(sinon.stub(typeRegistry,"getModuleInfo", function(module) { return "info"; @@ -63,7 +62,7 @@ describe('red/registry/index', function() { }); it('rejects if loader rejects', function(done) { stubs.push(sinon.stub(loader,"addModule",function(module) { - return when.reject("error"); + return Promise.reject("error"); })); stubs.push(sinon.stub(typeRegistry,"getModuleInfo", function(module) { return "info"; @@ -80,7 +79,7 @@ describe('red/registry/index', function() { describe('#enableNode',function() { it('enables a node set',function(done) { stubs.push(sinon.stub(typeRegistry,"enableNodeSet",function() { - return when.resolve(); + return Promise.resolve(); })); stubs.push(sinon.stub(typeRegistry,"getNodeInfo", function() { return {id:"node-set",loaded:true}; @@ -104,14 +103,14 @@ describe('red/registry/index', function() { it('triggers a node load',function(done) { stubs.push(sinon.stub(typeRegistry,"enableNodeSet",function() { - return when.resolve(); + return Promise.resolve(); })); var calls = 0; stubs.push(sinon.stub(typeRegistry,"getNodeInfo", function() { // loaded=false on first call, true on subsequent return {id:"node-set",loaded:(calls++>0)}; })); - stubs.push(sinon.stub(loader,"loadNodeSet",function(){return when.resolve();})); + stubs.push(sinon.stub(loader,"loadNodeSet",function(){return Promise.resolve();})); stubs.push(sinon.stub(typeRegistry,"getFullNodeInfo")); registry.enableNode("node-set").then(function(ns) { diff --git a/test/unit/@node-red/registry/lib/installer_spec.js b/test/unit/@node-red/registry/lib/installer_spec.js index ad658fd16..e0e7380f6 100644 --- a/test/unit/@node-red/registry/lib/installer_spec.js +++ b/test/unit/@node-red/registry/lib/installer_spec.js @@ -16,7 +16,6 @@ var should = require("should"); var sinon = require("sinon"); -var when = require("when"); var path = require("path"); var fs = require('fs-extra'); var EventEmitter = require('events'); @@ -26,6 +25,7 @@ var NR_TEST_UTILS = require("nr-test-utils"); var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer"); var registry = NR_TEST_UTILS.require("@node-red/registry/lib/index"); var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry"); +const { events, exec, log } = NR_TEST_UTILS.require("@node-red/util"); describe('nodes/registry/installer', function() { @@ -39,21 +39,15 @@ describe('nodes/registry/installer', function() { _: function(msg) { return msg } } + var execResponse; + beforeEach(function() { - installer.init({log:mockLog, settings:{}, events: new EventEmitter(), exec: { - run: function() { - return Promise.resolve(""); - } - }}); + sinon.stub(exec,"run", () => execResponse || Promise.resolve("")) + installer.init({}) }); - function initInstaller(execResult) { - installer.init({log:mockLog, settings:{}, events: new EventEmitter(), exec: { - run: function() { - return execResult; - } - }}); - } + afterEach(function() { + execResponse = null; if (registry.addModule.restore) { registry.addModule.restore(); } @@ -73,7 +67,7 @@ describe('nodes/registry/installer', function() { if (fs.statSync.restore) { fs.statSync.restore(); } - + exec.run.restore(); }); describe("installs module", function() { @@ -109,7 +103,7 @@ describe('nodes/registry/installer', function() { } var p = Promise.reject(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; installer.installModule("this_wont_exist").catch(function(err) { err.should.have.property("code",404); done(); @@ -123,7 +117,7 @@ describe('nodes/registry/installer', function() { } var p = Promise.reject(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; sinon.stub(typeRegistry,"getModuleInfo", function() { return { version: "0.1.1" @@ -164,7 +158,7 @@ describe('nodes/registry/installer', function() { } var p = Promise.reject(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; installer.installModule("this_wont_exist").then(function() { done(new Error("Unexpected success")); }).catch(err => { @@ -182,10 +176,10 @@ describe('nodes/registry/installer', function() { } var p = Promise.resolve(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; var addModule = sinon.stub(registry,"addModule",function(md) { - return when.resolve(nodeInfo); + return Promise.resolve(nodeInfo); }); installer.installModule("this_wont_exist").then(function(info) { @@ -216,7 +210,7 @@ describe('nodes/registry/installer', function() { it("succeeds when path is valid node-red module", function(done) { var nodeInfo = {nodes:{module:"foo",types:["a"]}}; var addModule = sinon.stub(registry,"addModule",function(md) { - return when.resolve(nodeInfo); + return Promise.resolve(nodeInfo); }); var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule")); @@ -227,7 +221,7 @@ describe('nodes/registry/installer', function() { } var p = Promise.resolve(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; installer.installModule(resourcesDir).then(function(info) { info.should.eql(nodeInfo); done(); @@ -243,10 +237,10 @@ describe('nodes/registry/installer', function() { } var p = Promise.resolve(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; var addModule = sinon.stub(registry,"addModule",function(md) { - return when.resolve(nodeInfo); + return Promise.resolve(nodeInfo); }); installer.installModule("this_wont_exist",null,"https://example/foo-0.1.1.tgz").then(function(info) { @@ -259,19 +253,20 @@ describe('nodes/registry/installer', function() { describe("uninstalls module", function() { it("rejects invalid module names", function(done) { var promises = []; - promises.push(installer.uninstallModule("this_wont_exist ")); - promises.push(installer.uninstallModule("this_wont_exist;no_it_really_wont")); - when.settle(promises).then(function(results) { - results[0].state.should.be.eql("rejected"); - results[1].state.should.be.eql("rejected"); + var rejectedCount = 0; + + promises.push(installer.uninstallModule("this_wont_exist ").catch(() => {rejectedCount++})); + promises.push(installer.uninstallModule("this_wont_exist;no_it_really_wont").catch(() => {rejectedCount++})); + Promise.all(promises).then(function() { + rejectedCount.should.eql(2); done(); - }); + }).catch(done); }); it("rejects with generic error", function(done) { var nodeInfo = [{module:"foo",types:["a"]}]; var removeModule = sinon.stub(registry,"removeModule",function(md) { - return when.resolve(nodeInfo); + return Promise.resolve(nodeInfo); }); var res = { code: 1, @@ -280,7 +275,7 @@ describe('nodes/registry/installer', function() { } var p = Promise.reject(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; installer.uninstallModule("this_wont_exist").then(function() { done(new Error("Unexpected success")); @@ -304,7 +299,7 @@ describe('nodes/registry/installer', function() { } var p = Promise.resolve(res); p.catch((err)=>{}); - initInstaller(p) + execResponse = p; sinon.stub(fs,"statSync", function(fn) { return {}; }); diff --git a/test/unit/@node-red/registry/lib/loader_spec.js b/test/unit/@node-red/registry/lib/loader_spec.js index 6dc9daa55..d62a8a9b4 100644 --- a/test/unit/@node-red/registry/lib/loader_spec.js +++ b/test/unit/@node-red/registry/lib/loader_spec.js @@ -15,7 +15,6 @@ **/ var should = require("should"); -var when = require("when"); var sinon = require("sinon"); var path = require("path"); var fs = require("fs-extra"); diff --git a/test/unit/@node-red/registry/lib/localfilesystem_spec.js b/test/unit/@node-red/registry/lib/localfilesystem_spec.js index 82e4d1b2d..5cb3c180d 100644 --- a/test/unit/@node-red/registry/lib/localfilesystem_spec.js +++ b/test/unit/@node-red/registry/lib/localfilesystem_spec.js @@ -15,7 +15,6 @@ **/ var should = require("should"); -var when = require("when"); var sinon = require("sinon"); var path = require("path"); @@ -54,7 +53,7 @@ describe("red/nodes/registry/localfilesystem",function() { } describe("#getNodeFiles",function() { it("Finds all the node files in the resources tree",function(done) { - localfilesystem.init({settings:{coreNodesDir:resourcesDir}}); + localfilesystem.init({coreNodesDir:resourcesDir}); var nodeList = localfilesystem.getNodeFiles(true); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -69,7 +68,7 @@ describe("red/nodes/registry/localfilesystem",function() { done(); }); it("Includes node files from settings",function(done) { - localfilesystem.init({settings:{nodesIncludes:['TestNode1.js'],coreNodesDir:resourcesDir}}); + localfilesystem.init({nodesIncludes:['TestNode1.js'],coreNodesDir:resourcesDir}); var nodeList = localfilesystem.getNodeFiles(true); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -79,7 +78,7 @@ describe("red/nodes/registry/localfilesystem",function() { done(); }); it("Excludes node files from settings",function(done) { - localfilesystem.init({settings:{nodesExcludes:['TestNode1.js'],coreNodesDir:resourcesDir}}); + localfilesystem.init({nodesExcludes:['TestNode1.js'],coreNodesDir:resourcesDir}); var nodeList = localfilesystem.getNodeFiles(true); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -89,7 +88,7 @@ describe("red/nodes/registry/localfilesystem",function() { done(); }); it("Finds nodes in userDir/nodes",function(done) { - localfilesystem.init({settings:{userDir:userDir}}); + localfilesystem.init({userDir:userDir}); var nodeList = localfilesystem.getNodeFiles(true); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -100,7 +99,7 @@ describe("red/nodes/registry/localfilesystem",function() { }); it("Finds nodes in settings.nodesDir (string)",function(done) { - localfilesystem.init({settings:{nodesDir:userDir}}); + localfilesystem.init({nodesDir:userDir}); var nodeList = localfilesystem.getNodeFiles(true); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -111,7 +110,7 @@ describe("red/nodes/registry/localfilesystem",function() { }); it("Finds nodes in settings.nodesDir (string,relative path)",function(done) { var relativeUserDir = path.join("test","unit","@node-red","registry","lib","resources","userDir"); - localfilesystem.init({settings:{nodesDir:relativeUserDir}}); + localfilesystem.init({nodesDir:relativeUserDir}); var nodeList = localfilesystem.getNodeFiles(true); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -121,7 +120,7 @@ describe("red/nodes/registry/localfilesystem",function() { done(); }); it("Finds nodes in settings.nodesDir (array)",function(done) { - localfilesystem.init({settings:{nodesDir:[userDir]}}); + localfilesystem.init({nodesDir:[userDir]}); var nodeList = localfilesystem.getNodeFiles(true); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -140,7 +139,7 @@ describe("red/nodes/registry/localfilesystem",function() { } return _join.apply(null,arguments); })); - localfilesystem.init({settings:{coreNodesDir:moduleDir}}); + localfilesystem.init({coreNodesDir:moduleDir}); var nodeList = localfilesystem.getNodeFiles(); nodeList.should.have.a.property("node-red"); var nm = nodeList['node-red']; @@ -176,18 +175,7 @@ describe("red/nodes/registry/localfilesystem",function() { it("scans icon files in the resources tree",function(done) { var count = 0; localfilesystem.init({ - - // events:{emit:function(eventName,dir){ - // if (count === 0) { - // eventName.should.equal("node-icon-dir"); - // dir.name.should.equal("node-red"); - // dir.icons.should.be.an.Array(); - // count = 1; - // } else if (count === 1) { - // done(); - // } - // }}, - settings:{coreNodesDir:resourcesDir} + coreNodesDir: resourcesDir }); var list = localfilesystem.getNodeFiles(true); list.should.have.property("node-red"); @@ -202,22 +190,7 @@ describe("red/nodes/registry/localfilesystem",function() { it("scans icons dir in library",function(done) { var count = 0; localfilesystem.init({ - // - // events:{emit:function(eventName,dir){ - // eventName.should.equal("node-icon-dir"); - // if (count === 0) { - // dir.name.should.equal("node-red"); - // dir.icons.should.be.an.Array(); - // count = 1; - // } else if (count === 1) { - // dir.name.should.equal("Library"); - // dir.icons.should.be.an.Array(); - // dir.icons.length.should.equal(1); - // dir.icons[0].should.be.equal("test_icon.png"); - // done(); - // } - // }}, - settings:{userDir:userDir} + userDir: userDir }); var list = localfilesystem.getNodeFiles(true); list.should.have.property("node-red"); @@ -241,7 +214,7 @@ describe("red/nodes/registry/localfilesystem",function() { } return _join.apply(null,arguments); })); - localfilesystem.init({settings:{coreNodesDir:moduleDir}}); + localfilesystem.init({coreNodesDir:moduleDir}); var nodeModule = localfilesystem.getModuleFiles('TestNodeModule'); nodeModule.should.have.a.property('TestNodeModule'); nodeModule['TestNodeModule'].should.have.a.property('name','TestNodeModule'); @@ -267,7 +240,7 @@ describe("red/nodes/registry/localfilesystem",function() { } return _join.apply(null,arguments); })); - localfilesystem.init({settings:{coreNodesDir:moduleDir}}); + localfilesystem.init({coreNodesDir:moduleDir}); /*jshint immed: false */ (function(){ localfilesystem.getModuleFiles('WontExistModule'); @@ -287,14 +260,7 @@ describe("red/nodes/registry/localfilesystem",function() { return _join.apply(null,arguments); })); localfilesystem.init({ - - // events:{emit:function(eventName,dir){ - // eventName.should.equal("node-icon-dir"); - // dir.name.should.equal("TestNodeModule"); - // dir.icons.should.be.an.Array(); - // done(); - // }}, - settings:{coreNodesDir:moduleDir} + coreNodesDir: moduleDir }); var nodeModule = localfilesystem.getModuleFiles('TestNodeModule'); nodeModule.should.have.property("TestNodeModule"); diff --git a/test/unit/@node-red/registry/lib/registry_spec.js b/test/unit/@node-red/registry/lib/registry_spec.js index c7ad930c4..60b48938d 100644 --- a/test/unit/@node-red/registry/lib/registry_spec.js +++ b/test/unit/@node-red/registry/lib/registry_spec.js @@ -15,16 +15,13 @@ **/ var should = require("should"); -var when = require("when"); var sinon = require("sinon"); var path = require("path"); var NR_TEST_UTILS = require("nr-test-utils"); var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry"); -var EventEmitter = require('events'); - -var events = new EventEmitter(); +const { events } = NR_TEST_UTILS.require("@node-red/util"); describe("red/nodes/registry/registry",function() { @@ -34,7 +31,7 @@ describe("red/nodes/registry/registry",function() { function stubSettings(s,available,initialConfig) { s.available = function() {return available;}; - s.set = sinon.spy(function(s,v) { return when.resolve();}); + s.set = sinon.spy(function(s,v) { return Promise.resolve();}); s.get = function(s) { return initialConfig;}; return s; } @@ -85,7 +82,7 @@ describe("red/nodes/registry/registry",function() { describe('#init/load', function() { it('loads initial config', function(done) { - typeRegistry.init(settingsWithStorageAndInitialConfig,null,events); + typeRegistry.init(settingsWithStorageAndInitialConfig,null); typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.load(); typeRegistry.getNodeList().should.have.lengthOf(1); @@ -95,7 +92,7 @@ describe("red/nodes/registry/registry",function() { it('migrates legacy format', function(done) { var legacySettings = { available: function() { return true; }, - set: sinon.stub().returns(when.resolve()), + set: sinon.stub().returns(Promise.resolve()), get: function() { return { "123": { "name": "72-sentiment.js", @@ -122,7 +119,7 @@ describe("red/nodes/registry/registry",function() { }} }; var expected = JSON.parse('{"node-red":{"name":"node-red","nodes":{"sentiment":{"name":"sentiment","types":["sentiment"],"enabled":true,"module":"node-red"},"inject":{"name":"inject","types":["inject"],"enabled":true,"module":"node-red"}}},"testModule":{"name":"testModule","nodes":{"a-module.js":{"name":"a-module.js","types":["example"],"enabled":true,"module":"testModule"}}}}'); - typeRegistry.init(legacySettings,null,events); + typeRegistry.init(legacySettings,null); typeRegistry.load(); legacySettings.set.calledOnce.should.be.true(); legacySettings.set.args[0][1].should.eql(expected); @@ -134,7 +131,7 @@ describe("red/nodes/registry/registry",function() { describe.skip('#addNodeSet', function() { it('adds a node set for an unknown module', function() { - typeRegistry.init(settings,null,events); + typeRegistry.init(settings,null); typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getModuleList().should.eql({}); @@ -163,7 +160,7 @@ describe("red/nodes/registry/registry",function() { it('adds a node set to an existing module', function() { - typeRegistry.init(settings,null,events); + typeRegistry.init(settings,null); typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getModuleList().should.eql({}); @@ -192,7 +189,7 @@ describe("red/nodes/registry/registry",function() { }); it('doesnt add node set types if node set has an error', function() { - typeRegistry.init(settings,null,events); + typeRegistry.init(settings,null); typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getModuleList().should.eql({}); @@ -208,7 +205,7 @@ describe("red/nodes/registry/registry",function() { }); it('doesnt add node set if type already exists', function() { - typeRegistry.init(settings,null,events); + typeRegistry.init(settings,null); typeRegistry.getNodeList().should.have.lengthOf(0); typeRegistry.getModuleList().should.eql({}); @@ -242,7 +239,7 @@ describe("red/nodes/registry/registry",function() { describe("#enableNodeSet", function() { it('throws error if settings unavailable', function() { - typeRegistry.init(settings,null,events); + typeRegistry.init(settings,null); /*jshint immed: false */ (function(){ typeRegistry.enableNodeSet("test-module/test-name"); @@ -250,7 +247,7 @@ describe("red/nodes/registry/registry",function() { }); it('throws error if module unknown', function() { - typeRegistry.init(settingsWithStorageAndInitialConfig,null,events); + typeRegistry.init(settingsWithStorageAndInitialConfig,null); /*jshint immed: false */ (function(){ typeRegistry.enableNodeSet("test-module/unknown"); @@ -261,7 +258,7 @@ describe("red/nodes/registry/registry",function() { }); describe("#disableNodeSet", function() { it('throws error if settings unavailable', function() { - typeRegistry.init(settings,null,events); + typeRegistry.init(settings,null); /*jshint immed: false */ (function(){ typeRegistry.disableNodeSet("test-module/test-name"); @@ -269,7 +266,7 @@ describe("red/nodes/registry/registry",function() { }); it('throws error if module unknown', function() { - typeRegistry.init(settingsWithStorageAndInitialConfig,null,events); + typeRegistry.init(settingsWithStorageAndInitialConfig,null); /*jshint immed: false */ (function(){ typeRegistry.disableNodeSet("test-module/unknown"); @@ -280,7 +277,7 @@ describe("red/nodes/registry/registry",function() { describe('#getNodeConfig', function() { it('returns nothing for an unregistered type config', function(done) { - typeRegistry.init(settings,null,events); + typeRegistry.init(settings,null); var config = typeRegistry.getNodeConfig("imaginary-shark"); (config === null).should.be.true(); done(); @@ -289,7 +286,7 @@ describe("red/nodes/registry/registry",function() { describe('#saveNodeList',function() { it('rejects when settings unavailable',function(done) { - typeRegistry.init(stubSettings({},false,{}),null,events); + typeRegistry.init(stubSettings({},false,{}),null); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {"test-name":{module:"test-module",name:"test-name",types:[]}}}); typeRegistry.saveNodeList().catch(function(err) { done(); @@ -297,7 +294,7 @@ describe("red/nodes/registry/registry",function() { }); it('saves the list',function(done) { var s = stubSettings({},true,{}); - typeRegistry.init(s,null,events); + typeRegistry.init(s,null); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":testNodeSet1, @@ -326,7 +323,7 @@ describe("red/nodes/registry/registry",function() { describe('#removeModule',function() { it('throws error for unknown module', function() { var s = stubSettings({},true,{}); - typeRegistry.init(s,null,events); + typeRegistry.init(s,null); /*jshint immed: false */ (function(){ typeRegistry.removeModule("test-module/unknown"); @@ -334,7 +331,7 @@ describe("red/nodes/registry/registry",function() { }); it('throws error for unavaiable settings', function() { var s = stubSettings({},false,{}); - typeRegistry.init(s,null,events); + typeRegistry.init(s,null); /*jshint immed: false */ (function(){ typeRegistry.removeModule("test-module/unknown"); @@ -342,7 +339,7 @@ describe("red/nodes/registry/registry",function() { }); it('removes a known module', function() { var s = stubSettings({},true,{}); - typeRegistry.init(s,null,events); + typeRegistry.init(s,null); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":testNodeSet1 }}); @@ -361,7 +358,7 @@ describe("red/nodes/registry/registry",function() { it('returns node config', function() { typeRegistry.init(settings,{ getNodeHelp: function(config) { return "HE"+config.name+"LP" } - },events); + }); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":{ @@ -390,7 +387,7 @@ describe("red/nodes/registry/registry",function() { }); describe('#getModuleInfo', function() { it('returns module info', function() { - typeRegistry.init(settings,{},events); + typeRegistry.init(settings,{}); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":{ id: "test-module/test-name", @@ -414,7 +411,7 @@ describe("red/nodes/registry/registry",function() { }); describe('#getNodeInfo', function() { it('returns node info', function() { - typeRegistry.init(settings,{},events); + typeRegistry.init(settings,{}); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":{ id: "test-module/test-name", @@ -435,7 +432,7 @@ describe("red/nodes/registry/registry",function() { }); describe('#getFullNodeInfo', function() { it('returns node info', function() { - typeRegistry.init(settings,{},events); + typeRegistry.init(settings,{}); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":{ id: "test-module/test-name", @@ -460,7 +457,7 @@ describe("red/nodes/registry/registry",function() { }); describe('#getNodeList', function() { it("returns a filtered list", function() { - typeRegistry.init(settings,{},events); + typeRegistry.init(settings,{}); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":{ id: "test-module/test-name", @@ -527,7 +524,7 @@ describe("red/nodes/registry/registry",function() { it('returns a registered icon' , function() { var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/'); - typeRegistry.init(settings,{},events); + typeRegistry.init(settings,{}); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":{ id: "test-module/test-name", @@ -559,7 +556,7 @@ describe("red/nodes/registry/registry",function() { it('returns an icon list of registered node module', function() { var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/'); - typeRegistry.init(settings,{},events); + typeRegistry.init(settings,{}); typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: { "test-name":{ id: "test-module/test-name", diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js b/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js index faf61a8f3..1bf2fa6c9 100644 --- a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js +++ b/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js @@ -1,8 +1,7 @@ // A test node that exports a function which returns a resolving promise -var when = require("when"); module.exports = function(RED) { - return when.promise(function(resolve,reject) { + return new Promise(function(resolve,reject) { function TestNode(n) {} RED.nodes.registerType("test-node-2",TestNode); resolve(); diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js b/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js index 756dc1398..b9ee6a624 100644 --- a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js +++ b/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js @@ -1,8 +1,7 @@ // A test node that exports a function which returns a rejecting promise -var when = require("when"); module.exports = function(RED) { - return when.promise(function(resolve,reject) { + return new Promise(function(resolve,reject) { reject("fail"); }); } diff --git a/test/unit/@node-red/runtime/lib/api/comms_spec.js b/test/unit/@node-red/runtime/lib/api/comms_spec.js index e1359cb7d..2f2e35a54 100644 --- a/test/unit/@node-red/runtime/lib/api/comms_spec.js +++ b/test/unit/@node-red/runtime/lib/api/comms_spec.js @@ -19,6 +19,7 @@ var sinon = require("sinon"); var NR_TEST_UTILS = require("nr-test-utils"); var comms = NR_TEST_UTILS.require("@node-red/runtime/lib/api/comms"); +var events = NR_TEST_UTILS.require("@node-red/util/lib/events"); describe("runtime-api/comms", function() { describe("listens for events", function() { @@ -30,21 +31,19 @@ describe("runtime-api/comms", function() { } var eventHandlers = {}; before(function(done) { + sinon.stub(events,"removeListener", function() {}) + sinon.stub(events,"on", function(evt,handler) { eventHandlers[evt] = handler }) comms.init({ log: { trace: function(){} - }, - events: { - removeListener: function() {}, - on: function(evt,handler) { - eventHandlers[evt] = handler; - } } }) comms.addConnection({client: clientConnection}).then(done); }) after(function(done) { comms.removeConnection({client: clientConnection}).then(done); + events.removeListener.restore(); + events.on.restore(); }) afterEach(function() { messages = []; @@ -98,18 +97,18 @@ describe("runtime-api/comms", function() { } } before(function() { + sinon.stub(events,"removeListener", function() {}) + sinon.stub(events,"on", function(evt,handler) { eventHandlers[evt] = handler }) comms.init({ log: { trace: function(){} - }, - events: { - removeListener: function() {}, - on: function(evt,handler) { - eventHandlers[evt] = handler; - } } }) }) + after(function() { + events.removeListener.restore(); + events.on.restore(); + }) afterEach(function(done) { comms.removeConnection({client: clientConnection1}).then(function() { comms.removeConnection({client: clientConnection2}).then(done); @@ -178,18 +177,18 @@ describe("runtime-api/comms", function() { } var eventHandlers = {}; before(function() { + sinon.stub(events,"removeListener", function() {}) + sinon.stub(events,"on", function(evt,handler) { eventHandlers[evt] = handler }) comms.init({ log: { trace: function(){} - }, - events: { - removeListener: function() {}, - on: function(evt,handler) { - eventHandlers[evt] = handler; - } } }) }) + after(function() { + events.removeListener.restore(); + events.on.restore(); + }) afterEach(function(done) { messages = []; comms.removeConnection({client: clientConnection}).then(done); diff --git a/test/unit/@node-red/runtime/lib/api/nodes_spec.js b/test/unit/@node-red/runtime/lib/api/nodes_spec.js index 6481c653d..327df15e0 100644 --- a/test/unit/@node-red/runtime/lib/api/nodes_spec.js +++ b/test/unit/@node-red/runtime/lib/api/nodes_spec.js @@ -185,7 +185,6 @@ var request = require('supertest'); var express = require('express'); var bodyParser = require('body-parser'); var sinon = require('sinon'); -var when = require('when'); var nodes = require("../../../../red/api/admin/nodes"); var apiUtil = require("../../../../red/api/util"); @@ -418,7 +417,7 @@ describe("api/admin/nodes", function() { nodes:{ getModuleInfo: function(id) { return null; }, installModule: function() { - return when.resolve({ + return Promise.resolve({ name:"foo", nodes:[{id:"123"}] }); @@ -446,7 +445,7 @@ describe("api/admin/nodes", function() { nodes:{ getModuleInfo: function(id) { return {nodes:{id:"123"}}; }, installModule: function() { - return when.resolve({id:"123"}); + return Promise.resolve({id:"123"}); } } }); @@ -468,7 +467,7 @@ describe("api/admin/nodes", function() { nodes:{ getModuleInfo: function(id) { return null }, installModule: function() { - return when.reject(new Error("test error")); + return Promise.reject(new Error("test error")); } } }); @@ -492,7 +491,7 @@ describe("api/admin/nodes", function() { installModule: function() { var err = new Error("test error"); err.code = 404; - return when.reject(err); + return Promise.reject(err); } } }); @@ -533,7 +532,7 @@ describe("api/admin/nodes", function() { nodes:{ getModuleInfo: function(id) { return {nodes:[{id:"123"}]} }, getNodeInfo: function() { return null }, - uninstallModule: function() { return when.resolve({id:"123"});} + uninstallModule: function() { return Promise.resolve({id:"123"});} } }); request(app) @@ -572,7 +571,7 @@ describe("api/admin/nodes", function() { nodes:{ getModuleInfo: function(id) { return {nodes:[{id:"123"}]} }, getNodeInfo: function() { return null }, - uninstallModule: function() { return when.reject(new Error("test error"));} + uninstallModule: function() { return Promise.reject(new Error("test error"));} } }); request(app) @@ -686,7 +685,7 @@ describe("api/admin/nodes", function() { settings:{available:function(){return true}}, nodes:{ getNodeInfo: function() { return {id:"123",enabled: false} }, - enableNode: function() { return when.resolve({id:"123",enabled: true,types:['a']}); } + enableNode: function() { return Promise.resolve({id:"123",enabled: true,types:['a']}); } } }); request(app) @@ -709,7 +708,7 @@ describe("api/admin/nodes", function() { settings:{available:function(){return true}}, nodes:{ getNodeInfo: function() { return {id:"123",enabled: true} }, - disableNode: function() { return when.resolve({id:"123",enabled: false,types:['a']}); } + disableNode: function() { return Promise.resolve({id:"123",enabled: false,types:['a']}); } } }); request(app) @@ -729,8 +728,8 @@ describe("api/admin/nodes", function() { describe('no-ops if already in the right state', function() { function run(state,done) { - var enableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: true,types:['a']}) }); - var disableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: false,types:['a']}) }); + var enableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: true,types:['a']}) }); + var disableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: false,types:['a']}) }); initNodes({ settings:{available:function(){return true}}, @@ -768,8 +767,8 @@ describe("api/admin/nodes", function() { describe('does not no-op if err on node', function() { function run(state,done) { - var enableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: true,types:['a']}) }); - var disableNode = sinon.spy(function() { return when.resolve({id:"123",enabled: false,types:['a']}) }); + var enableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: true,types:['a']}) }); + var disableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: false,types:['a']}) }); initNodes({ settings:{available:function(){return true}}, @@ -811,11 +810,11 @@ describe("api/admin/nodes", function() { var enableNode = sinon.stub(); enableNode.onFirstCall().returns((function() { n1.enabled = true; - return when.resolve(n1); + return Promise.resolve(n1); })()); enableNode.onSecondCall().returns((function() { n2.enabled = true; - return when.resolve(n2); + return Promise.resolve(n2); })()); enableNode.returns(null); initNodes({ @@ -849,11 +848,11 @@ describe("api/admin/nodes", function() { var disableNode = sinon.stub(); disableNode.onFirstCall().returns((function() { n1.enabled = false; - return when.resolve(n1); + return Promise.resolve(n1); })()); disableNode.onSecondCall().returns((function() { n2.enabled = false; - return when.resolve(n2); + return Promise.resolve(n2); })()); disableNode.returns(null); initNodes({ @@ -886,11 +885,11 @@ describe("api/admin/nodes", function() { var node = {id:"123",enabled:state,types:['a']}; var enableNode = sinon.spy(function(id) { node.enabled = true; - return when.resolve(node); + return Promise.resolve(node); }); var disableNode = sinon.spy(function(id) { node.enabled = false; - return when.resolve(node); + return Promise.resolve(node); }); initNodes({ @@ -933,11 +932,11 @@ describe("api/admin/nodes", function() { var node = {id:"123",enabled:state,types:['a'],err:"foo"}; var enableNode = sinon.spy(function(id) { node.enabled = true; - return when.resolve(node); + return Promise.resolve(node); }); var disableNode = sinon.spy(function(id) { node.enabled = false; - return when.resolve(node); + return Promise.resolve(node); }); initNodes({ diff --git a/test/unit/@node-red/runtime/lib/api/settings_spec.js b/test/unit/@node-red/runtime/lib/api/settings_spec.js index 3830e9ab2..d01235604 100644 --- a/test/unit/@node-red/runtime/lib/api/settings_spec.js +++ b/test/unit/@node-red/runtime/lib/api/settings_spec.js @@ -48,7 +48,7 @@ describe("runtime-api/settings", function() { }, nodes: { listContextStores: () => { return {stores:["file","memory"], default: "file"} }, - paletteEditorEnabled: () => false, + installerEnabled: () => false, getCredentialKeyType: () => "test-key-type" }, storage: {} @@ -79,7 +79,7 @@ describe("runtime-api/settings", function() { }, nodes: { listContextStores: () => { return {stores:["file","memory"], default: "file"} }, - paletteEditorEnabled: () => false, + installerEnabled: () => false, getCredentialKeyType: () => "test-key-type" }, storage: {} @@ -115,7 +115,7 @@ describe("runtime-api/settings", function() { }, nodes: { listContextStores: () => { return {stores:["file","memory"], default: "file"} }, - paletteEditorEnabled: () => false, + installerEnabled: () => false, getCredentialKeyType: () => "test-key-type" }, storage: { @@ -166,7 +166,7 @@ describe("runtime-api/settings", function() { }, nodes: { listContextStores: () => { return {stores:["file","memory"], default: "file"} }, - paletteEditorEnabled: () => false, + installerEnabled: () => false, getCredentialKeyType: () => "test-key-type" }, storage: { @@ -207,7 +207,7 @@ describe("runtime-api/settings", function() { }, nodes: { listContextStores: () => { return {stores:["file","memory"], default: "file"} }, - paletteEditorEnabled: () => false, + installerEnabled: () => false, getCredentialKeyType: () => "test-key-type" }, storage: { @@ -252,7 +252,7 @@ describe("runtime-api/settings", function() { }, nodes: { listContextStores: () => { return {stores:["file","memory"], default: "file"} }, - paletteEditorEnabled: () => false, + installerEnabled: () => false, getCredentialKeyType: () => "test-key-type" }, storage: { @@ -588,7 +588,6 @@ var comms = require("../../../../red/api/editor/comms"); var info = require("../../../../red/api/editor/settings"); var auth = require("../../../../red/api/auth"); var sshkeys = require("../../../../red/api/editor/sshkeys"); -var when = require("when"); var bodyParser = require("body-parser"); var fs = require("fs-extra"); var fspath = require("path"); @@ -611,11 +610,11 @@ describe("api/editor/sshkeys", function() { exportNodeSettings:function(){}, storage: { getSessions: function(){ - return when.resolve(session_data); + return Promise.resolve(session_data); }, setSessions: function(_session) { session_data = _session; - return when.resolve(); + return Promise.resolve(); } } }, @@ -633,7 +632,7 @@ describe("api/editor/sshkeys", function() { }, events:{on:function(){},removeListener:function(){}}, isStarted: function() { return isStarted; }, - nodes: {paletteEditorEnabled: function() { return false }} + nodes: {installerEnabled: function() { return false }} }; before(function() { diff --git a/test/unit/@node-red/runtime/lib/flows/index_spec.js b/test/unit/@node-red/runtime/lib/flows/index_spec.js index df5012844..e230d2407 100644 --- a/test/unit/@node-red/runtime/lib/flows/index_spec.js +++ b/test/unit/@node-red/runtime/lib/flows/index_spec.js @@ -16,14 +16,13 @@ var should = require("should"); var sinon = require("sinon"); -var when = require("when"); var clone = require("clone"); var NR_TEST_UTILS = require("nr-test-utils"); var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows"); var RedNode = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node"); var RED = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes"); -var events = NR_TEST_UTILS.require("@node-red/runtime/lib/events"); +var events = NR_TEST_UTILS.require("@node-red/util/lib/events"); var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials"); var typeRegistry = NR_TEST_UTILS.require("@node-red/registry") var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow"); @@ -65,13 +64,13 @@ describe('flows/index', function() { conf.forEach(function(n) { delete n.credentials; }); - return when.resolve(); + return Promise.resolve(); }); credentialsLoad = sinon.stub(credentials,"load",function(creds) { if (creds && creds.hasOwnProperty("$") && creds['$'] === "fail") { - return when.reject("creds error"); + return Promise.reject("creds error"); } - return when.resolve(); + return Promise.resolve(); }); flowCreate = sinon.stub(Flow,"create",function(parent, global, flow) { var id; @@ -101,7 +100,7 @@ describe('flows/index', function() { storage = { saveFlows: function(conf) { storage.conf = conf; - return when.resolve(); + return Promise.resolve(); } } }); @@ -145,10 +144,10 @@ describe('flows/index', function() { var loadStorage = { saveFlows: function(conf) { loadStorage.conf = conf; - return when.resolve(456); + return Promise.resolve(456); }, getFlows: function() { - return when.resolve({flows:originalConfig,rev:123}) + return Promise.resolve({flows:originalConfig,rev:123}) } } flows.init({log:mockLog, settings:{},storage:loadStorage}); @@ -207,7 +206,7 @@ describe('flows/index', function() { newConfig.push({id:"t2",type:"tab"}); newConfig.push({id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]}); storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } events.once('flows:started',function() { flows.setFlows(newConfig,"nodes").then(function() { @@ -235,7 +234,7 @@ describe('flows/index', function() { newConfig.push({id:"t2",type:"tab"}); newConfig.push({id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]}); storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } events.once('flows:started',function() { @@ -277,7 +276,7 @@ describe('flows/index', function() { {id:"t1",type:"tab"} ]; storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } flows.init({log:mockLog, settings:{},storage:storage}); flows.load().then(function() { @@ -297,7 +296,7 @@ describe('flows/index', function() { {id:"t1",type:"tab"} ]; storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } events.once('flows:started',function() { @@ -317,7 +316,7 @@ describe('flows/index', function() { {id:"t1",type:"tab"} ]; storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } flows.init({log:mockLog, settings:{},storage:storage}); @@ -336,7 +335,7 @@ describe('flows/index', function() { {id:"t1",type:"tab"} ]; storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } flows.init({log:mockLog, settings:{},storage:storage}); flows.load().then(function() { @@ -370,7 +369,7 @@ describe('flows/index', function() { {id:"t1",type:"tab"} ]; storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } flows.init({log:mockLog, settings:{},storage:storage}); flows.load().then(function() { @@ -394,7 +393,7 @@ describe('flows/index', function() { // {id:"t1",type:"tab"} // ]; // storage.getFlows = function() { - // return when.resolve({flows:originalConfig}); + // return Promise.resolve({flows:originalConfig}); // } // // events.once('flows:started',function() { @@ -419,7 +418,7 @@ describe('flows/index', function() { // {id:"t3-1",x:10,y:10,z:"t3",type:"test",config:"configNode",wires:[]} // ]; // storage.getFlows = function() { - // return when.resolve({flows:originalConfig}); + // return Promise.resolve({flows:originalConfig}); // } // // events.once('flows:started',function() { @@ -447,7 +446,7 @@ describe('flows/index', function() { // {id:"t1",type:"tab"} // ]; // storage.getFlows = function() { - // return when.resolve({flows:originalConfig}); + // return Promise.resolve({flows:originalConfig}); // } // // events.once('flows:started',function() { @@ -473,7 +472,7 @@ describe('flows/index', function() { // {id:"t3-1",x:10,y:10,z:"t3",type:"test",config:"configNode",wires:[]} // ]; // storage.getFlows = function() { - // return when.resolve({flows:originalConfig}); + // return Promise.resolve({flows:originalConfig}); // } // // events.once('flows:started',function() { @@ -548,7 +547,7 @@ describe('flows/index', function() { {id:"t1",type:"tab"} ]; storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } flows.init({log:mockLog, settings:{},storage:storage}); flows.load().then(function() { @@ -572,10 +571,10 @@ describe('flows/index', function() { {id:"t1",type:"tab"} ]; storage.getFlows = function() { - return when.resolve({flows:originalConfig}); + return Promise.resolve({flows:originalConfig}); } storage.setFlows = function() { - return when.resolve(); + return Promise.resolve(); } flows.init({log:mockLog, settings:{},storage:storage}); flows.load().then(function() { diff --git a/test/unit/@node-red/runtime/lib/flows/util_spec.js b/test/unit/@node-red/runtime/lib/flows/util_spec.js index 8e1f15754..59169376e 100644 --- a/test/unit/@node-red/runtime/lib/flows/util_spec.js +++ b/test/unit/@node-red/runtime/lib/flows/util_spec.js @@ -16,7 +16,6 @@ var should = require("should"); var sinon = require("sinon"); -var when = require("when"); var clone = require("clone"); var NR_TEST_UTILS = require("nr-test-utils"); var flowUtil = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util"); diff --git a/test/unit/@node-red/runtime/lib/index_spec.js b/test/unit/@node-red/runtime/lib/index_spec.js index f6a506de1..60bdc286b 100644 --- a/test/unit/@node-red/runtime/lib/index_spec.js +++ b/test/unit/@node-red/runtime/lib/index_spec.js @@ -28,6 +28,7 @@ var settings = NR_TEST_UTILS.require("@node-red/runtime/lib/settings"); var util = NR_TEST_UTILS.require("@node-red/util"); var log = NR_TEST_UTILS.require("@node-red/util").log; +var i18n = NR_TEST_UTILS.require("@node-red/util").i18n; describe("runtime", function() { afterEach(function() { @@ -43,43 +44,45 @@ describe("runtime", function() { delete process.env.NODE_RED_HOME; }); function mockUtil(metrics) { - - return { - log:{ - log: sinon.stub(), - warn: sinon.stub(), - info: sinon.stub(), - trace: sinon.stub(), - metric: sinon.stub().returns(!!metrics), - _: function() { return "abc"} - }, - i18n: { - registerMessageCatalog: function(){ - return Promise.resolve(); - } - } - } + sinon.stub(log,"log",function(){}) + sinon.stub(log,"warn",function(){}) + sinon.stub(log,"info",function(){}) + sinon.stub(log,"trace",function(){}) + sinon.stub(log,"metric",function(){ return !!metrics }) + sinon.stub(log,"_",function(){ return "abc"}) + sinon.stub(i18n,"registerMessageCatalog",function(){ return Promise.resolve()}) + } + function unmockUtil() { + log.log.restore && log.log.restore(); + log.warn.restore && log.warn.restore(); + log.info.restore && log.info.restore(); + log.trace.restore && log.trace.restore(); + log.metric.restore && log.metric.restore(); + log._.restore && log._.restore(); + i18n.registerMessageCatalog.restore && i18n.registerMessageCatalog.restore(); } describe("init", function() { beforeEach(function() { sinon.stub(log,"init",function() {}); sinon.stub(settings,"init",function() {}); sinon.stub(redNodes,"init",function() {}) + mockUtil(); }); afterEach(function() { log.init.restore(); settings.init.restore(); redNodes.init.restore(); + unmockUtil(); }) it("initialises components", function() { - runtime.init({testSettings: true, httpAdminRoot:"/"},mockUtil()); + runtime.init({testSettings: true, httpAdminRoot:"/"}); settings.init.called.should.be.true(); redNodes.init.called.should.be.true(); }); it("returns version", function() { - runtime.init({testSettings: true, httpAdminRoot:"/"},mockUtil()); + runtime.init({testSettings: true, httpAdminRoot:"/"}); return runtime.version().then(version => { /^\d+\.\d+\.\d+(-.*)?$/.test(version).should.be.true(); }); @@ -98,7 +101,6 @@ describe("runtime", function() { var redNodesLoadFlows; var redNodesStartFlows; var redNodesLoadContextsPlugin; - var i18nRegisterMessageCatalog; beforeEach(function() { storageInit = sinon.stub(storage,"init",function(settings) {return Promise.resolve();}); @@ -108,7 +110,7 @@ describe("runtime", function() { redNodesLoadFlows = sinon.stub(redNodes,"loadFlows",function() {return Promise.resolve()}); redNodesStartFlows = sinon.stub(redNodes,"startFlows",function() {}); redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin",function() {return Promise.resolve()}); - i18nRegisterMessageCatalog = sinon.stub(util.i18n,"registerMessageCatalog",function() {return Promise.resolve()}); + mockUtil(); }); afterEach(function() { storageInit.restore(); @@ -119,7 +121,7 @@ describe("runtime", function() { redNodesLoadFlows.restore(); redNodesStartFlows.restore(); redNodesLoadContextsPlugin.restore(); - i18nRegisterMessageCatalog.restore(); + unmockUtil(); }); it("reports errored/missing modules",function(done) { redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) { @@ -128,8 +130,7 @@ describe("runtime", function() { { module:"module",enabled:true,loaded:false,types:["typeA","typeB"]} // missing ].filter(cb); }); - var util = mockUtil(); - runtime.init({testSettings: true, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util); + runtime.init({testSettings: true, httpAdminRoot:"/", load:function() { return Promise.resolve();}}); // sinon.stub(console,"log"); runtime.start().then(function() { // console.log.restore(); @@ -139,9 +140,9 @@ describe("runtime", function() { redNodesLoad.calledOnce.should.be.true(); redNodesLoadFlows.calledOnce.should.be.true(); - util.log.warn.calledWithMatch("Failed to register 1 node type"); - util.log.warn.calledWithMatch("Missing node modules"); - util.log.warn.calledWithMatch(" - module: typeA, typeB"); + log.warn.calledWithMatch("Failed to register 1 node type"); + log.warn.calledWithMatch("Missing node modules"); + log.warn.calledWithMatch(" - module: typeA, typeB"); redNodesCleanModuleList.calledOnce.should.be.true(); done(); } catch(err) { @@ -159,16 +160,15 @@ describe("runtime", function() { ].filter(cb); }); var serverInstallModule = sinon.stub(redNodes,"installModule",function(name) { return Promise.resolve({nodes:[]});}); - var util = mockUtil(); - runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util); + runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}}); sinon.stub(console,"log"); runtime.start().then(function() { console.log.restore(); try { - util.log.warn.calledWithMatch("Failed to register 2 node types"); - util.log.warn.calledWithMatch("Missing node modules"); - util.log.warn.calledWithMatch(" - module: typeA, typeB"); - util.log.warn.calledWithMatch(" - node-red: typeC, typeD"); + log.warn.calledWithMatch("Failed to register 2 node types"); + log.warn.calledWithMatch("Missing node modules"); + log.warn.calledWithMatch(" - module: typeA, typeB"); + log.warn.calledWithMatch(" - node-red: typeC, typeD"); redNodesCleanModuleList.calledOnce.should.be.false(); serverInstallModule.calledOnce.should.be.true(); serverInstallModule.calledWithMatch("module"); @@ -186,14 +186,13 @@ describe("runtime", function() { { err:"errored",name:"errName" } // error ].filter(cb); }); - var util = mockUtil(); - runtime.init({testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util); + runtime.init({testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}}); sinon.stub(console,"log"); runtime.start().then(function() { console.log.restore(); try { - util.log.warn.neverCalledWithMatch("Failed to register 1 node type"); - util.log.warn.calledWithMatch("[errName] errored"); + log.warn.neverCalledWithMatch("Failed to register 1 node type"); + log.warn.calledWithMatch("[errName] errored"); done(); } catch(err) { done(err); @@ -204,21 +203,21 @@ describe("runtime", function() { it("reports runtime metrics",function(done) { var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return Promise.resolve();} ); redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []}); - var util = mockUtil(true); + unmockUtil(); + mockUtil(true); runtime.init( {testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return Promise.resolve();}}, {}, - undefined, - util); + undefined); // sinon.stub(console,"log"); runtime.start().then(function() { // console.log.restore(); setTimeout(function() { try { - util.log.log.args.should.have.lengthOf(3); - util.log.log.args[0][0].should.have.property("event","runtime.memory.rss"); - util.log.log.args[1][0].should.have.property("event","runtime.memory.heapTotal"); - util.log.log.args[2][0].should.have.property("event","runtime.memory.heapUsed"); + log.log.args.should.have.lengthOf(3); + log.log.args[0][0].should.have.property("event","runtime.memory.rss"); + log.log.args[1][0].should.have.property("event","runtime.memory.heapTotal"); + log.log.args[2][0].should.have.property("event","runtime.memory.heapUsed"); done(); } catch(err) { done(err); diff --git a/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js b/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js index 63050a8b9..5e4bc8094 100644 --- a/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js +++ b/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js @@ -16,7 +16,6 @@ var should = require("should"); var sinon = require("sinon"); -var when = require("when"); var util = require("util"); var NR_TEST_UTILS = require("nr-test-utils"); @@ -228,11 +227,11 @@ describe('red/runtime/nodes/credentials', function() { }, set: function(key,value) { settings[key] = value; - return when.resolve(); + return Promise.resolve(); }, delete: function(key) { delete settings[key]; - return when.resolve(); + return Promise.resolve(); } } } diff --git a/test/unit/@node-red/runtime/lib/nodes/index_spec.js b/test/unit/@node-red/runtime/lib/nodes/index_spec.js index 7a4992624..a73e0a246 100644 --- a/test/unit/@node-red/runtime/lib/nodes/index_spec.js +++ b/test/unit/@node-red/runtime/lib/nodes/index_spec.js @@ -17,7 +17,6 @@ var should = require("should"); var fs = require('fs-extra'); var path = require('path'); -var when = require("when"); var sinon = require('sinon'); var inherits = require("util").inherits; @@ -47,11 +46,11 @@ describe("red/nodes/index", function() { var testCredentials = {"tab1":{"b":1, "c":"2", "d":"$(foo)"}}; var storage = { getFlows: function() { - return when({red:123,flows:testFlows,credentials:testCredentials}); + return Promise.resolve({red:123,flows:testFlows,credentials:testCredentials}); }, saveFlows: function(conf) { should.deepEqual(testFlows, conf.flows); - return when.resolve(123); + return Promise.resolve(123); } }; @@ -182,12 +181,12 @@ describe("red/nodes/index", function() { fs.remove(userDir,function(err) { fs.mkdir(userDir,function() { sinon.stub(index, 'load', function() { - return when.promise(function(resolve,reject){ + return new Promise(function(resolve,reject){ resolve([]); }); }); sinon.stub(localfilesystem, 'getCredentials', function() { - return when.promise(function(resolve,reject) { + return new Promise(function(resolve,reject) { resolve({"tab1":{"b":1,"c":2}}); }); }) ; @@ -282,7 +281,7 @@ describe("red/nodes/index", function() { } }); sinon.stub(registry,"disableNode",function(id) { - return when.resolve(randomNodeInfo); + return Promise.resolve(randomNodeInfo); }); }); afterEach(function() { diff --git a/test/unit/@node-red/runtime/lib/storage/index_spec.js b/test/unit/@node-red/runtime/lib/storage/index_spec.js index 3ede68c86..dd9fa6e9b 100644 --- a/test/unit/@node-red/runtime/lib/storage/index_spec.js +++ b/test/unit/@node-red/runtime/lib/storage/index_spec.js @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var when = require("when"); var should = require("should"); var paff = require('path'); @@ -79,16 +78,16 @@ describe("red/storage/index", function() { }, getFlows : function() { calledFlagGetFlows = true; - return when.resolve([]); + return Promise.resolve([]); }, saveFlows : function (flows) { flows.should.be.an.Array(); flows.should.have.lengthOf(0); - return when.resolve(""); + return Promise.resolve(""); }, getCredentials : function() { calledFlagGetCredentials = true; - return when.resolve({}); + return Promise.resolve({}); }, saveCredentials : function(credentials) { credentials.should.be.true(); @@ -147,7 +146,7 @@ describe("red/storage/index", function() { storage.getLibraryEntry(true, "name"); storage.saveLibraryEntry(true, "name", true, true); - when.settle(promises).then(function() { + Promise.all(promises).then(function() { try { calledInit.should.be.true(); calledFlagGetFlows.should.be.true(); @@ -174,11 +173,11 @@ describe("red/storage/index", function() { getLibraryEntry : function(type, path) { if (type === "flows") { if (path === "/" || path === "\\") { - return when.resolve(["a",{fn:"test.json"}]); + return Promise.resolve(["a",{fn:"test.json"}]); } else if (path == "/a" || path == "\\a") { - return when.resolve([{fn:"test2.json"}]); + return Promise.resolve([{fn:"test2.json"}]); } else if (path == paff.join("","a","test2.json")) { - return when.resolve("test content"); + return Promise.resolve("test content"); } } }, @@ -187,7 +186,7 @@ describe("red/storage/index", function() { savePath = path; saveContent = body; saveMeta = meta; - return when.resolve(); + return Promise.resolve(); } }; diff --git a/test/unit/@node-red/runtime/lib/events_spec.js b/test/unit/@node-red/util/lib/events_spec.js similarity index 88% rename from test/unit/@node-red/runtime/lib/events_spec.js rename to test/unit/@node-red/util/lib/events_spec.js index 09b47693d..09f5d2ae0 100644 --- a/test/unit/@node-red/runtime/lib/events_spec.js +++ b/test/unit/@node-red/util/lib/events_spec.js @@ -17,9 +17,9 @@ var should = require("should"); var NR_TEST_UTILS = require("nr-test-utils"); -describe("runtime/events", function() { +describe("@node-red/util/events", function() { it('can be required without errors', function() { - NR_TEST_UTILS.require("@node-red/runtime/lib/events"); + NR_TEST_UTILS.require("@node-red/util/lib/events"); }); it.skip('more tests needed', function(){}) }); diff --git a/test/unit/@node-red/runtime/lib/exec_spec.js b/test/unit/@node-red/util/lib/exec_spec.js similarity index 90% rename from test/unit/@node-red/runtime/lib/exec_spec.js rename to test/unit/@node-red/util/lib/exec_spec.js index 1e37b7cc1..887938d16 100644 --- a/test/unit/@node-red/runtime/lib/exec_spec.js +++ b/test/unit/@node-red/util/lib/exec_spec.js @@ -16,30 +16,31 @@ var should = require("should"); var sinon = require("sinon"); var path = require("path"); -var events = require("events"); +var EventEmitter = require("events").EventEmitter; var child_process = require('child_process'); var NR_TEST_UTILS = require("nr-test-utils"); -var exec = NR_TEST_UTILS.require("@node-red/runtime/lib/exec"); +var events = NR_TEST_UTILS.require("@node-red/util/lib/events"); +var exec = NR_TEST_UTILS.require("@node-red/util/lib/exec"); describe("runtime/exec", function() { var logEvents; var mockProcess; + const eventLogHandler = function(ev) { + logEvents.push(ev); + } beforeEach(function() { - var logEventHandler = new events.EventEmitter(); - logEvents = []; - logEventHandler.on('event-log', function(ev) { - logEvents.push(ev); - }); - exec.init({events:logEventHandler}); - mockProcess = new events.EventEmitter(); - mockProcess.stdout = new events.EventEmitter(); - mockProcess.stderr = new events.EventEmitter(); + logEvents = []; + events.on("event-log", eventLogHandler); + + mockProcess = new EventEmitter(); + mockProcess.stdout = new EventEmitter(); + mockProcess.stderr = new EventEmitter(); sinon.stub(child_process,'spawn',function(command,args,options) { mockProcess._args = {command,args,options}; return mockProcess; @@ -47,6 +48,7 @@ describe("runtime/exec", function() { }); afterEach(function() { + events.removeListener("event-log", eventLogHandler); if (child_process.spawn.restore) { child_process.spawn.restore(); }