mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge branch 'dev' into debug-node-with-jsonata
This commit is contained in:
		
							
								
								
									
										94
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,3 +1,97 @@ | ||||
| #### 0.20.0-beta.2: Beta Release | ||||
|  | ||||
|  - Split Node-RED internals into multiple sub-modules | ||||
|  | ||||
| Editor | ||||
|  | ||||
|  - Allow the editor to use a custom admin api url root | ||||
|  - Improve performance of Flow Diff dialog - @TothiViseo #1989 | ||||
|  - Add 'open project' option to Projects Welcome dialog | ||||
|  - Add 'type already registered' check in palette editor | ||||
|  - Handle missing tab.disabled property | ||||
|  - Handle missing wires prop and string x/y props on import | ||||
|  - Add RED.notifications.hide flag - for UI testing | ||||
|  - Improve alignment of node label edit inputs | ||||
|  - Show arrow-in node when invalid font-awesome icon name was specified for default icon | ||||
|  - Add ability to delete context values from sidebar | ||||
|  - Allow copy-to-clipboard copy whole tabs | ||||
|  - Make disabled flows more obvious in editor | ||||
|  - Allow import/export from file in editor | ||||
|  - Allow config nodes to be selected in sidebar and deleted | ||||
|  - Show port label of subflow with input port | ||||
|  - Support ctrl-click selection of flow tabs | ||||
|  - Allow left-hand node button to act as toggle | ||||
|  - Support dbl-click in tab bar to add new flow in position | ||||
|  - Fix duplicate subflow detection on import | ||||
|  - Add import notification with info on what has been imported Closes #1862 | ||||
|  - Show error details when trying to import invalid json | ||||
|  - Show default icon when non-existent font-awesome icon was specified | ||||
|  - Add configurable option for showing node label | ||||
|  - Avoid http redirects as Safari doesn't reuse Auth header Fixes #1903 | ||||
|  - Tidy up ace tooltip styling | ||||
|  - Add event log to editor | ||||
|  - Add tooltips to multiple editor elements | ||||
|  - Allow palette to be hidden | ||||
|  - Add node module into to sidebar and palette popover | ||||
|  - Mark all newly imported nodes as changed | ||||
|  - Allow a node label to be hidden | ||||
|  - Add markdown formatting toolbar | ||||
|  - Add markdown toolbar to various editors | ||||
|  - Fix i18n handling for ja-JP locale on Safari/MacOS | ||||
|  - Add node body tooltip | ||||
|  - Decrease opacity of flow-navigator | ||||
|  - Update tooltip style | ||||
|  - Update ACE to 1.4.1-src-min-noconflict | ||||
|  - Cache node locales by language | ||||
|  - Show icon element with either icon image or fa-icon | ||||
|  - Added font-awesome icons to user defined icon | ||||
|  - Update info side bar with node description section | ||||
|  - One-click search of config node users | ||||
|  - Redesign node edit dialog to tabbed style | ||||
|  - Add 'restart flows' option to deploy menu | ||||
|  - Add node description property UI | ||||
|  | ||||
|  | ||||
| Runtime | ||||
|  | ||||
|  - Allow a project to be loaded from cmdline | ||||
|  - Handle lookup of undefined property in Global context Fixes #1978 | ||||
|  - Refuse to enable Manage Palette if npm too old | ||||
|  - Remove restriction on upgrading non-local modules | ||||
|  - Remove deprecated Buffer constructor usage Fixes #1709 | ||||
|  - Update httpServerOptions doc in settings.js | ||||
|  - Exclude non-testable .js files from the unit tests | ||||
|  - Add --safe mode flag to allow starting without flows running | ||||
|  - Add setting-defined accessToken for automated access to the adminAPI - #1789 | ||||
|  | ||||
| Nodes | ||||
|  | ||||
|  - Move all core node EN help to their own locale files - #1990 | ||||
|  - CSV: better regex for number detection | ||||
|  - Debug: hide button if not configured to send to sidebar | ||||
|  - Delay: report queue activity when in by-topic mode | ||||
|  - Delay: add msg.flush mode | ||||
|  - Exec: Preserve existing properties on msg object | ||||
|  - File: remove CR/LF from incoming filename | ||||
|  - Function: create custom ace javascript mode to handle ES6 Fixes #1911 | ||||
|  - Function: add env.get | ||||
|  - HTTP Request: Add http-proxy config #1913 | ||||
|  - HTTP Request: add msg.redirectList to output | ||||
|  - HTTP Request: add msg.requestTimeout option for per-message setting - @natcl #1959 | ||||
|  - MQTT: add auto-detect and base64 output to mqtt node Fixes #1912 - @DurandA | ||||
|  - MQTT: only unsubscribe node that is being removed | ||||
|  - Sentiment: move to node-red-node-sentiment | ||||
|  - Switch: add missing edit dialog icon | ||||
|  - Tail: move to node-red-node-tail | ||||
|  - TCPGet: clear status if user changes target per message | ||||
|  - Template: tidy up edit dialog | ||||
|  - UDP: more resilient binding to correct port for udp, give input side priority | ||||
|  - Split/Join: add msg.reset to info panel | ||||
|  - Split/Join: reset join without sending part array | ||||
|  - Watch: add msg.filename so can feed direct to file in node | ||||
|  - WebSocket: preserve \_session on msg but don't send as part of wholemsg | ||||
|  | ||||
|  | ||||
| #### 0.19.5: Maintenance Release | ||||
|  | ||||
|  - Recognize pip installs of RPi.GPIO (#1934) | ||||
|   | ||||
							
								
								
									
										35
									
								
								Gruntfile.js
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								Gruntfile.js
									
									
									
									
									
								
							| @@ -373,6 +373,10 @@ module.exports = function(grunt) { | ||||
|                         src: 'CHANGELOG.md', | ||||
|                         dest: 'packages/node_modules/@node-red/editor-client/public/red/about' | ||||
|                     }, | ||||
|                     { | ||||
|                         src: 'CHANGELOG.md', | ||||
|                         dest: 'packages/node_modules/node-red/' | ||||
|                     }, | ||||
|                     { | ||||
|                         cwd: 'packages/node_modules/@node-red/editor-client/src/ace/bin/', | ||||
|                         src: '**', | ||||
| @@ -429,23 +433,18 @@ module.exports = function(grunt) { | ||||
|             } | ||||
|         }, | ||||
|         jsdoc : { | ||||
|             runtimeAPI: { | ||||
|             modules: { | ||||
|                 src: [ | ||||
|                     'packages/node_modules/node-red/lib/red.js', | ||||
|                     'packages/node_modules/@node-red/runtime/lib/index.js', | ||||
|                     'packages/node_modules/@node-red/runtime/lib/api/*.js', | ||||
|                     'packages/node_modules/@node-red/runtime/lib/events.js', | ||||
|                     'packages/node_modules/@node-red/util/**/*.js', | ||||
|                     ], | ||||
|                 options: { | ||||
|                     destination: 'docs', | ||||
|                     configure: './jsdoc.json' | ||||
|                 } | ||||
|             }, | ||||
|             nodeREDUtil: { | ||||
|                 src: 'packages/node_modules/@node-red/util/**/*.js', | ||||
|                 options: { | ||||
|                     destination: 'packages/node_modules/@node-red/util/docs', | ||||
|                     configure: './jsdoc.json' | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         jsdoc2md: { | ||||
| @@ -453,8 +452,11 @@ module.exports = function(grunt) { | ||||
|                 options: { | ||||
|                     separators: true | ||||
|                 }, | ||||
|                 src: ['packages/node_modules/@node-red/runtime/lib/index.js', | ||||
|                       'packages/node_modules/@node-red/runtime/lib/api/*.js'], | ||||
|                 src: [ | ||||
|                     'packages/node_modules/@node-red/runtime/lib/index.js', | ||||
|                     'packages/node_modules/@node-red/runtime/lib/api/*.js', | ||||
|                     'packages/node_modules/@node-red/runtime/lib/events.js' | ||||
|                 ], | ||||
|                 dest: 'packages/node_modules/@node-red/runtime/docs/api.md' | ||||
|             }, | ||||
|             nodeREDUtil: { | ||||
| @@ -528,12 +530,15 @@ module.exports = function(grunt) { | ||||
|     }); | ||||
|  | ||||
|     grunt.registerTask('verifyPackageDependencies', function() { | ||||
|         var done = this.async(); | ||||
|         var verifyDependencies = require("./scripts/verify-package-dependencies.js"); | ||||
|         var failures = verifyDependencies(); | ||||
|         if (failures.length > 0) { | ||||
|             failures.forEach(f => grunt.log.error(f)); | ||||
|             grunt.fail.fatal("Failed to verify package dependencies"); | ||||
|         } | ||||
|         verifyDependencies().then(function(failures) { | ||||
|             if (failures.length > 0) { | ||||
|                 failures.forEach(f => grunt.log.error(f)); | ||||
|                 grunt.fail.fatal("Failed to verify package dependencies"); | ||||
|             } | ||||
|             done(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     grunt.registerTask('setDevEnv', | ||||
|   | ||||
							
								
								
									
										36
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "node-red", | ||||
|     "version": "0.20.0-alpha.0", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "description": "A visual tool for wiring the Internet of Things", | ||||
|     "homepage": "http://nodered.org", | ||||
|     "license": "Apache-2.0", | ||||
| @@ -24,7 +24,7 @@ | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "ajv": "6.5.4", | ||||
|         "ajv": "6.6.1", | ||||
|         "basic-auth": "2.0.1", | ||||
|         "bcryptjs": "2.4.3", | ||||
|         "body-parser": "1.18.3", | ||||
| @@ -32,29 +32,31 @@ | ||||
|         "clone": "2.1.2", | ||||
|         "cookie": "0.3.1", | ||||
|         "cookie-parser": "1.4.3", | ||||
|         "cors": "2.8.4", | ||||
|         "cron": "1.5.0", | ||||
|         "denque": "1.3.0", | ||||
|         "cors": "2.8.5", | ||||
|         "cron": "1.5.1", | ||||
|         "denque": "1.4.0", | ||||
|         "express": "4.16.4", | ||||
|         "express-session": "1.15.6", | ||||
|         "fs-extra": "5.0.0", | ||||
|         "fs-extra": "7.0.1", | ||||
|         "fs.notify": "0.0.4", | ||||
|         "hash-sum": "1.0.2", | ||||
|         "https-proxy-agent": "2.2.1", | ||||
|         "i18next": "11.6.0", | ||||
|         "i18next": "12.1.0", | ||||
|         "is-utf8": "0.2.1", | ||||
|         "js-yaml": "3.12.0", | ||||
|         "json-stringify-safe": "5.0.1", | ||||
|         "jsonata": "1.5.4", | ||||
|         "media-typer": "0.3.0", | ||||
|         "media-typer": "1.0.1", | ||||
|         "memorystore": "1.6.0", | ||||
|         "mime": "1.4.1", | ||||
|         "mime": "2.4.0", | ||||
|         "mqtt": "2.18.8", | ||||
|         "multer": "1.4.1", | ||||
|         "mustache": "2.3.2", | ||||
|         "node-red-node-email": "0.1.*", | ||||
|         "node-red-node-feedparser": "^0.1.12", | ||||
|         "mustache": "3.0.1", | ||||
|         "node-red-node-email": "1.0.*", | ||||
|         "node-red-node-feedparser": "^0.1.14", | ||||
|         "node-red-node-rbe": "0.2.*", | ||||
|         "node-red-node-sentiment": "^0.1.0", | ||||
|         "node-red-node-tail": "^0.0.1", | ||||
|         "node-red-node-twitter": "^1.1.0", | ||||
|         "nopt": "4.0.1", | ||||
|         "oauth2orize": "1.11.0", | ||||
| @@ -78,7 +80,7 @@ | ||||
|         "chromedriver": "2.43.1", | ||||
|         "grunt": "~1.0.3", | ||||
|         "grunt-chmod": "~1.1.1", | ||||
|         "grunt-cli": "~1.3.1", | ||||
|         "grunt-cli": "~1.3.2", | ||||
|         "grunt-concurrent": "~2.3.1", | ||||
|         "grunt-contrib-clean": "~1.1.0", | ||||
|         "grunt-contrib-compress": "~1.4.0", | ||||
| @@ -104,12 +106,12 @@ | ||||
|         "mosca": "^2.8.3", | ||||
|         "should": "^8.4.0", | ||||
|         "sinon": "1.17.7", | ||||
|         "stoppable": "^1.0.7", | ||||
|         "stoppable": "^1.1.0", | ||||
|         "supertest": "3.3.0", | ||||
|         "wdio-chromedriver-service": "^0.1.3", | ||||
|         "wdio-mocha-framework": "^0.6.2", | ||||
|         "wdio-chromedriver-service": "^0.1.5", | ||||
|         "wdio-mocha-framework": "^0.6.4", | ||||
|         "wdio-spec-reporter": "^0.1.5", | ||||
|         "webdriverio": "^4.13.1", | ||||
|         "webdriverio": "^4.14.1", | ||||
|         "node-red-node-test-helper": "node-red/node-red-node-test-helper", | ||||
|         "jsdoc-nr-template": "node-red/jsdoc-nr-template" | ||||
|     }, | ||||
|   | ||||
| @@ -57,7 +57,7 @@ module.exports = { | ||||
|         } | ||||
|         runtimeAPI.nodes.getIcon(opts).then(function(data) { | ||||
|             if (data) { | ||||
|                 var contentType = mime.lookup(icon); | ||||
|                 var contentType = mime.getType(icon); | ||||
|                 res.set("Content-Type", contentType); | ||||
|                 res.send(data); | ||||
|             } else { | ||||
|   | ||||
| @@ -100,5 +100,5 @@ module.exports = { | ||||
|     auth: { | ||||
|         needsPermission: auth.needsPermission | ||||
|     }, | ||||
|     get adminApp() { return adminApp; } | ||||
|     get httpAdmin() { return adminApp; } | ||||
| }; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@node-red/editor-api", | ||||
|     "version": "0.20.0-alpha.0", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "license": "Apache-2.0", | ||||
|     "main": "./lib/index.js", | ||||
|     "repository": { | ||||
| @@ -8,21 +8,25 @@ | ||||
|         "url": "https://github.com/node-red/node-red.git" | ||||
|     }, | ||||
|     "contributors": [ | ||||
|         { "name": "Nick O'Leary" }, | ||||
|         { "name": "Dave Conway-Jones"} | ||||
|         { | ||||
|             "name": "Nick O'Leary" | ||||
|         }, | ||||
|         { | ||||
|             "name": "Dave Conway-Jones" | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "@node-red/util": "*", | ||||
|         "@node-red/editor-client": "*", | ||||
|         "@node-red/util": "0.20.0-beta.2", | ||||
|         "@node-red/editor-client": "0.20.0-beta.2", | ||||
|         "bcryptjs": "2.4.3", | ||||
|         "body-parser": "1.18.3", | ||||
|         "clone": "2.1.2", | ||||
|         "cors": "2.8.4", | ||||
|         "cors": "2.8.5", | ||||
|         "express-session": "1.15.6", | ||||
|         "express": "4.16.4", | ||||
|         "memorystore": "1.6.0", | ||||
|         "mime": "1.4.1", | ||||
|         "mustache": "2.3.2", | ||||
|         "mime": "2.4.0", | ||||
|         "mustache": "3.0.1", | ||||
|         "oauth2orize": "1.11.0", | ||||
|         "passport-http-bearer": "1.0.1", | ||||
|         "passport-oauth2-client-password": "0.1.2", | ||||
|   | ||||
| @@ -1,14 +1,18 @@ | ||||
| { | ||||
|    "name": "@node-red/editor-client", | ||||
|    "version": "0.20.0-alpha.0", | ||||
|    "license": "Apache-2.0", | ||||
|    "repository": { | ||||
|        "type": "git", | ||||
|        "url": "https://github.com/node-red/node-red.git" | ||||
|    }, | ||||
|    "contributors": [ | ||||
|        { "name": "Nick O'Leary" }, | ||||
|        { "name": "Dave Conway-Jones"} | ||||
|    ], | ||||
|    "main": "./lib/index.js" | ||||
|     "name": "@node-red/editor-client", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "license": "Apache-2.0", | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|         "url": "https://github.com/node-red/node-red.git" | ||||
|     }, | ||||
|     "contributors": [ | ||||
|         { | ||||
|             "name": "Nick O'Leary" | ||||
|         }, | ||||
|         { | ||||
|             "name": "Dave Conway-Jones" | ||||
|         } | ||||
|     ], | ||||
|     "main": "./lib/index.js" | ||||
| } | ||||
|   | ||||
| @@ -865,7 +865,7 @@ RED.editor = (function() { | ||||
|         var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel"); | ||||
|         var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel"); | ||||
|  | ||||
|         $('<div class="form-row"><span style="margin-left: 10px;" data-i18n="editor.labelInputs"></span><div id="node-label-form-inputs"></div></div>').appendTo(dialogForm); | ||||
|         $('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelInputs"></span><div id="node-label-form-inputs"></div></div>').appendTo(dialogForm); | ||||
|         var inputsDiv = $("#node-label-form-inputs"); | ||||
|         if (inputCount > 0) { | ||||
|             for (i=0;i<inputCount;i++) { | ||||
| @@ -874,7 +874,7 @@ RED.editor = (function() { | ||||
|         } else { | ||||
|             buildLabelRow().appendTo(inputsDiv); | ||||
|         } | ||||
|         $('<div class="form-row"><span style="margin-left: 10px;" data-i18n="editor.labelOutputs"></span><div id="node-label-form-outputs"></div></div>').appendTo(dialogForm); | ||||
|         $('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelOutputs"></span><div id="node-label-form-outputs"></div></div>').appendTo(dialogForm); | ||||
|         var outputsDiv = $("#node-label-form-outputs"); | ||||
|         if (outputCount > 0) { | ||||
|             for (i=0;i<outputCount;i++) { | ||||
|   | ||||
| @@ -16,6 +16,10 @@ | ||||
| RED.notifications = (function() { | ||||
|  | ||||
|     /* | ||||
|     If RED.notifications.hide is set to true, all notifications will be hidden. | ||||
|     This is to help with UI testing in certain cases and not intended for the | ||||
|     end-user. | ||||
|  | ||||
|     // Example usage for a modal dialog with buttons | ||||
|     var myNotification = RED.notify("This is the message to display",{ | ||||
|         modal: true, | ||||
| @@ -108,7 +112,9 @@ RED.notifications = (function() { | ||||
|  | ||||
|  | ||||
|         $("#notifications").append(n); | ||||
|         $(n).slideDown(300); | ||||
|         if (!RED.notifications.hide) { | ||||
|             $(n).slideDown(300); | ||||
|         } | ||||
|         n.close = (function() { | ||||
|             var nn = n; | ||||
|             return function() { | ||||
| @@ -123,9 +129,13 @@ RED.notifications = (function() { | ||||
|                         notificationButtonWrapper.hide(); | ||||
|                     } | ||||
|                 } | ||||
|                 $(nn).slideUp(300, function() { | ||||
|                 if (!RED.notifications.hide) { | ||||
|                     $(nn).slideUp(300, function() { | ||||
|                         nn.parentNode.removeChild(nn); | ||||
|                     }); | ||||
|                 } else { | ||||
|                     nn.parentNode.removeChild(nn); | ||||
|                 }); | ||||
|                 } | ||||
|                 if (options.modal) { | ||||
|                     $("#full-shade").hide(); | ||||
|                 } | ||||
| @@ -138,7 +148,9 @@ RED.notifications = (function() { | ||||
|                     return | ||||
|                 } | ||||
|                 nn.hidden = true; | ||||
|                 $(nn).slideUp(300); | ||||
|                 if (!RED.notifications.hide) { | ||||
|                     $(nn).slideUp(300); | ||||
|                 } | ||||
|             } | ||||
|         })(); | ||||
|         n.showNotification = (function() { | ||||
| @@ -148,7 +160,9 @@ RED.notifications = (function() { | ||||
|                     return | ||||
|                 } | ||||
|                 nn.hidden = false; | ||||
|                 $(nn).slideDown(300); | ||||
|                 if (!RED.notifications.hide) { | ||||
|                     $(nn).slideDown(300); | ||||
|                 } | ||||
|             } | ||||
|         })(); | ||||
|  | ||||
|   | ||||
| @@ -789,7 +789,11 @@ RED.utils = (function() { | ||||
|                 return RED.settings.apiRootUrl+"icons/"+iconPath.module+"/"+iconPath.file; | ||||
|             } | ||||
|         } else { | ||||
|             if (def.category === 'subflows') { | ||||
|             // This could be a non-core node trying to use a core icon. | ||||
|             iconPath.module = 'node-red'; | ||||
|             if (isIconExists(iconPath)) { | ||||
|                 return RED.settings.apiRootUrl+"icons/"+iconPath.module+"/"+iconPath.file; | ||||
|             } else if (def.category === 'subflows') { | ||||
|                 return RED.settings.apiRootUrl+"icons/node-red/subflow.png"; | ||||
|             } else { | ||||
|                 return RED.settings.apiRootUrl+"icons/node-red/arrow-in.png"; | ||||
|   | ||||
| @@ -343,7 +343,7 @@ | ||||
|     top: -3000px; | ||||
| } | ||||
| .node-label-form-row { | ||||
|     margin: 5px 0; | ||||
|     margin: 5px 0 0 50px; | ||||
|     label { | ||||
|         margin-right: 20px; | ||||
|         text-align: right; | ||||
|   | ||||
| @@ -1,37 +0,0 @@ | ||||
|  | ||||
| <script type="text/x-red" data-template-name="sentiment"> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="node-red:common.label.property"></span></label> | ||||
|         <input type="text" id="node-input-property" style="width:70%;"/> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label> | ||||
|         <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"> | ||||
|     </div> | ||||
| </script> | ||||
|  | ||||
| <script type="text/javascript"> | ||||
|     RED.nodes.registerType('sentiment',{ | ||||
|         category: 'analysis-function', | ||||
|         color:"#E6E0F8", | ||||
|         defaults: { | ||||
|             name: {value:""}, | ||||
|             property: {value:"payload",required:true} | ||||
|         }, | ||||
|         inputs:1, | ||||
|         outputs:1, | ||||
|         icon: "arrow-in.png", | ||||
|         label: function() { | ||||
|             return this.name||"sentiment"; | ||||
|         }, | ||||
|         labelStyle: function() { | ||||
|             return this.name?"node_label_italic":""; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             if (this.property === undefined) { | ||||
|                 $("#node-input-property").val("payload"); | ||||
|             } | ||||
|             $("#node-input-property").typedInput({default:'msg',types:['msg']}); | ||||
|         } | ||||
|     }); | ||||
| </script> | ||||
| @@ -1,23 +0,0 @@ | ||||
|  | ||||
| module.exports = function(RED) { | ||||
|     "use strict"; | ||||
|     var sentiment = require('sentiment'); | ||||
|  | ||||
|     function SentimentNode(n) { | ||||
|         RED.nodes.createNode(this,n); | ||||
|         this.property = n.property||"payload"; | ||||
|         var node = this; | ||||
|  | ||||
|         this.on("input", function(msg) { | ||||
|             var value = RED.util.getMessageProperty(msg,node.property); | ||||
|             if (value !== undefined) { | ||||
|                 sentiment(value, msg.overrides || null, function (err, result) { | ||||
|                     msg.sentiment = result; | ||||
|                     node.send(msg); | ||||
|                 }); | ||||
|             } | ||||
|             else { node.send(msg); } // If no matching property - just pass it on. | ||||
|         }); | ||||
|     } | ||||
|     RED.nodes.registerType("sentiment",SentimentNode); | ||||
| } | ||||
| @@ -2,10 +2,10 @@ | ||||
| <script type="text/x-red" data-template-name="template"> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label> | ||||
|         <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"> | ||||
|         <div style="display: inline-block; width: calc(100% - 105px)"><input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"></div> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-field"><i class="fa fa-edit"></i> <span data-i18n="template.label.property"></span></label> | ||||
|         <label for="node-input-field"><i class="fa fa-ellipsis-h"></i> <span data-i18n="template.label.property"></span></label> | ||||
|         <input type="text" id="node-input-field" placeholder="payload" style="width:250px;"> | ||||
|         <input type="hidden" id="node-input-fieldType"> | ||||
|     </div> | ||||
|   | ||||
| @@ -131,8 +131,16 @@ module.exports = function(RED) { | ||||
|             if (msg.hasOwnProperty('followRedirects')) { | ||||
|                 opts.followRedirect = msg.followRedirects; | ||||
|             } | ||||
|             var redirectList = []; | ||||
|             if (!opts.hasOwnProperty('followRedirect') || opts.followRedirect) { | ||||
|                 opts.followRedirect = function(res) { | ||||
|                     var redirectInfo = { | ||||
|                         location: res.headers.location, | ||||
|                     }; | ||||
|                     if (res.headers.hasOwnProperty('set-cookie')) { | ||||
|                         redirectInfo.cookies = extractCookies(res.headers['set-cookie']); | ||||
|                     } | ||||
|                     redirectList.push(redirectInfo); | ||||
|                     if (this.headers.cookie) { | ||||
|                         delete this.headers.cookie; | ||||
|                     } | ||||
| @@ -256,17 +264,10 @@ module.exports = function(RED) { | ||||
|                     msg.headers = res.headers; | ||||
|                     msg.responseUrl = res.request.uri.href; | ||||
|                     msg.payload = body; | ||||
|                     msg.redirectList = redirectList; | ||||
|  | ||||
|                     if (msg.headers.hasOwnProperty('set-cookie')) { | ||||
|                         msg.responseCookies = {}; | ||||
|                         msg.headers['set-cookie'].forEach(function(c) { | ||||
|                             var parsedCookie = cookie.parse(c); | ||||
|                             var eq_idx = c.indexOf('='); | ||||
|                             var key = c.substr(0, eq_idx).trim() | ||||
|                             parsedCookie.value = parsedCookie[key]; | ||||
|                             delete parsedCookie[key]; | ||||
|                             msg.responseCookies[key] = parsedCookie; | ||||
|                         }); | ||||
|                         msg.responseCookies = extractCookies(msg.headers['set-cookie']); | ||||
|                     } | ||||
|                     msg.headers['x-node-red-request-node'] = hashSum(msg.headers); | ||||
|                     // msg.url = url;   // revert when warning above finally removed | ||||
| @@ -299,6 +300,19 @@ module.exports = function(RED) { | ||||
|         this.on("close",function() { | ||||
|             node.status({}); | ||||
|         }); | ||||
|  | ||||
|         function extractCookies(setCookie) { | ||||
|             var cookies = {}; | ||||
|             setCookie.forEach(function(c) { | ||||
|                 var parsedCookie = cookie.parse(c); | ||||
|                 var eq_idx = c.indexOf('='); | ||||
|                 var key = c.substr(0, eq_idx).trim() | ||||
|                 parsedCookie.value = parsedCookie[key]; | ||||
|                 delete parsedCookie[key]; | ||||
|                 cookies[key] = parsedCookie; | ||||
|             }); | ||||
|             return cookies; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     RED.nodes.registerType("http request",HTTPRequest,{ | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|         <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label data-i18n="switch.label.property"></label> | ||||
|         <label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="switch.label.property"></span></label> | ||||
|         <input type="text" id="node-input-property" style="width: 70%"/> | ||||
|         <input type="hidden" id="node-input-outputs"/> | ||||
|     </div> | ||||
|   | ||||
| @@ -1,51 +0,0 @@ | ||||
|  | ||||
| <script type="text/x-red" data-template-name="tail"> | ||||
|     <div class="form-row"> | ||||
|          <label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="tail.label.filename"></span></label> | ||||
|          <input id="node-input-filename" type="text"> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-filetype"><i class="fa fa-file-text-o"></i> <span data-i18n="tail.label.type"></span></label> | ||||
|         <select type="text" id="node-input-filetype"> | ||||
|             <option value="text" data-i18n="tail.action.text"></option> | ||||
|             <option value="binary" data-i18n="tail.action.binary"></option> | ||||
|         </select> | ||||
|     </div> | ||||
|     <div class="form-row" id="node-tail-split"> | ||||
|         <label> </label> | ||||
|         <input type="checkbox" id="node-input-split" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;"> | ||||
|         <label for="node-input-split" style="width: 70%;"><span data-i18n="tail.label.splitlines"></span></label> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label> | ||||
|         <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name"> | ||||
|     </div> | ||||
| </script> | ||||
|  | ||||
| <script type="text/javascript"> | ||||
|     RED.nodes.registerType('tail',{ | ||||
|         category: 'storage-input', | ||||
|         defaults: { | ||||
|             name: {value:""}, | ||||
|             filetype: {value:"text"}, | ||||
|             split: {value:false}, | ||||
|             filename: {value:"",required:true} | ||||
|         }, | ||||
|         color:"BurlyWood", | ||||
|         inputs:0, | ||||
|         outputs:1, | ||||
|         icon: "file.png", | ||||
|         label: function() { | ||||
|             return this.name||this.filename||this._("tail.tail"); | ||||
|         }, | ||||
|         labelStyle: function() { | ||||
|             return this.name?"node_label_italic":""; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             $("#node-input-filetype").on("change",function() { | ||||
|                 if (this.value === "text") { $("#node-tail-split").show(); } | ||||
|                 else { $("#node-tail-split").hide(); } | ||||
|             }); | ||||
|         } | ||||
|     }); | ||||
| </script> | ||||
| @@ -1,75 +0,0 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * 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. | ||||
|  **/ | ||||
|  | ||||
| module.exports = function(RED) { | ||||
|     "use strict"; | ||||
|     var spawn = require('child_process').spawn; | ||||
|     var plat = require('os').platform(); | ||||
|  | ||||
|     if (plat.match(/^win/)) { | ||||
|         throw RED._("tail.errors.windowsnotsupport"); | ||||
|     } | ||||
|  | ||||
|     function TailNode(n) { | ||||
|         RED.nodes.createNode(this,n); | ||||
|  | ||||
|         this.filename = n.filename; | ||||
|         this.filetype = n.filetype || "text"; | ||||
|         this.split = n.split || false; | ||||
|         var node = this; | ||||
|  | ||||
|         var err = ""; | ||||
|         // TODO: rewrite to use node-tail | ||||
|         var tail = spawn("tail", ["-F", "-n", "0", this.filename]); | ||||
|         tail.stdout.on("data", function (data) { | ||||
|             var msg = { topic:node.filename }; | ||||
|             if (node.filetype === "text") { | ||||
|                 if (node.split) { | ||||
|                     // TODO: allow customisation of the line break - as we do elsewhere | ||||
|                     var strings = data.toString().split("\n"); | ||||
|                     for (var s in strings) { | ||||
|                         //TODO: should we really filter blanks? Is that expected? | ||||
|                         if (strings[s] !== "") { | ||||
|                             node.send({ | ||||
|                                 topic: node.filename, | ||||
|                                 payload: strings[s] | ||||
|                             }); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 else { | ||||
|                     msg.payload = data.toString(); | ||||
|                     node.send(msg); | ||||
|                 } | ||||
|             } | ||||
|             else { | ||||
|                 msg.payload = data; | ||||
|                 node.send(msg); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         tail.stderr.on("data", function(data) { | ||||
|             node.error(data.toString()); | ||||
|         }); | ||||
|  | ||||
|         this.on("close", function() { | ||||
|             /* istanbul ignore else */ | ||||
|             if (tail) { tail.kill(); } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     RED.nodes.registerType("tail",TailNode); | ||||
| } | ||||
| @@ -1,35 +0,0 @@ | ||||
| <!-- | ||||
|   Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   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. | ||||
| --> | ||||
|  | ||||
| <script type="text/x-red" data-help-name="sentiment"> | ||||
|     <p>Analyses the chosen property, default <code>payload</code>, and adds a <code>sentiment</code> object.</p> | ||||
|     <h3>Outputs</h3> | ||||
|     <dl class="message-properties"> | ||||
|         <dt>sentiment <span class="property-type">object</span></dt> | ||||
|         <dd>contains the resulting AFINN-111 sentiment.</dd> | ||||
|         <dt>sentiment.score <span class="property-type">number</span></dt> | ||||
|         <dd>the sentiment score.</dd> | ||||
|     </dl> | ||||
|     <h3>Inputs</h3> | ||||
|     <dl class="message-properties"> | ||||
|         <dt>overrides <span class="property-type">object</span></dt> | ||||
|         <dd>an object of word score overrides can be supplied - <code>{ word:score,... }</code>.</dd> | ||||
|     </dl> | ||||
|     <h3>Details</h3> | ||||
|     <p>A score greater than zero is positive and less than zero is negative.</p> | ||||
|     <p>The score typically ranges from -5 to +5, but can go higher and lower.</p> | ||||
|     <p>See <a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_blank">the Sentiment docs here</a>.</p> | ||||
| </script> | ||||
| @@ -53,6 +53,8 @@ | ||||
|             Otherwise, the url of the original request.</dd> | ||||
|         <dt>responseCookies <span class="property-type">object</span></dt> | ||||
|         <dd>If the response includes cookies, this propery is an object of name/value pairs for each cookie.</dd> | ||||
|         <dt>redirectList <span class="property-type">array</span></dt> | ||||
|         <dd>If the request was redirected one or more times, the accumulated information will be added to this property. `location` is the next redirect destination. `cookies` is the cookies returned from the redirect source.</dd> | ||||
|     </dl> | ||||
|     <h3>Details</h3> | ||||
|     <p>When configured within the node, the URL property can contain <a href="http://mustache.github.io/mustache.5.html" target="_blank">mustache-style</a> tags. These allow the | ||||
|   | ||||
| @@ -206,7 +206,7 @@ | ||||
|         "template": "template", | ||||
|         "label": { | ||||
|             "template": "Template", | ||||
|             "property": "Set property", | ||||
|             "property": "Property", | ||||
|             "format": "Syntax Highlight", | ||||
|             "syntax": "Format", | ||||
|             "output": "Output as", | ||||
| @@ -827,21 +827,6 @@ | ||||
|             "pythoncommandnotfound": "nrpgio python command not running" | ||||
|         } | ||||
|     }, | ||||
|     "tail": { | ||||
|         "tail": "tail", | ||||
|         "label": { | ||||
|             "filename": "Filename", | ||||
|             "type": "File type", | ||||
|             "splitlines": "Split lines on \\n?" | ||||
|         }, | ||||
|         "action": { | ||||
|             "text": "Text - returns String", | ||||
|             "binary": "Binary - returns Buffer" | ||||
|         }, | ||||
|         "errors": { | ||||
|             "windowsnotsupport": "Not currently supported on Windows." | ||||
|         } | ||||
|     }, | ||||
|     "file": { | ||||
|         "label": { | ||||
|             "filename": "Filename", | ||||
|   | ||||
| @@ -1,25 +0,0 @@ | ||||
| <!-- | ||||
|   Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   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. | ||||
| --> | ||||
|  | ||||
| <script type="text/x-red" data-help-name="tail"> | ||||
|     <p>Tails (watches for things to be added) to the configured file. (Linux/Mac ONLY)</p> | ||||
|     <p>This will not work on Windows filesystems, as it relies on the <b>tail -F</b> command.</p> | ||||
|     <h3>Outputs</h3> | ||||
|     <ul> | ||||
|         <li>Text (UTF-8) files will be returned as strings.</li> | ||||
|         <li>Binary files will be returned as Buffer objects.</li> | ||||
|     </ul> | ||||
| </script> | ||||
| @@ -1,35 +0,0 @@ | ||||
| <!-- | ||||
|   Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   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. | ||||
| --> | ||||
|  | ||||
| <script type="text/x-red" data-help-name="sentiment"> | ||||
|     <p>指定したプロパティ(デフォルトは<code>payload</code>)を分析し、<code>sentiment</code>オブジェクトを追加します。</p> | ||||
|     <h3>出力</h3> | ||||
|     <dl class="message-properties"> | ||||
|         <dt>sentiment <span class="property-type">オブジェクト</span></dt> | ||||
|         <dd>AFINN-111による感情分析の結果</dd> | ||||
|         <dt>sentiment.score <span class="property-type">数値</span></dt> | ||||
|         <dd>感情分析スコア</dd> | ||||
|     </dl> | ||||
|     <h3>入力</h3> | ||||
|     <dl class="message-properties"> | ||||
|         <dt>overrides <span class="property-type">オブジェクト</span></dt> | ||||
|         <dd>単語スコアの上書きをするためのオブジェクト - <code>{ word:score,... }</code></dd> | ||||
|     </dl> | ||||
|     <h3>詳細</h3> | ||||
|     <p>ゼロ以上のスコアはポジティブ、ゼロ以下はネガティブを意味します。</p> | ||||
|     <p>スコアの範囲は通常-5から+5ですが、より大きかったり小さかったりすることもあります。</p> | ||||
|     <p>詳細は<a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_blank">the Sentiment docs here</a>を参照してください。</p> | ||||
| </script> | ||||
| @@ -46,6 +46,8 @@ | ||||
|         <dd>リクエストの処理時にリダイレクトが発生した場合、このプロパティが最後にリダイレクトされたURLを表します。リダイレクトが起こらなかった場合、最初リクエストのURLを表します。</dd> | ||||
|         <dt>responseCookies <span class="property-type">オブジェクト</span></dt> | ||||
|         <dd>レスポンスがクッキーを含む場合、このプロパティは各クッキーの名前/値を含むオブジェクトを表します。</dd> | ||||
|         <dt>redirectList <span class="property-type">配列</span></dt> | ||||
|         <dd>リクエストが一回以上リダイレクトされた場合は、このプロパティに情報が蓄積されます。`location`は、リダイレクト先を示します。`cookies`は、リダイレクト元から返されたクッキー情報です。</dd> | ||||
|     </dl> | ||||
|     <h3>詳細</h3> | ||||
|     <p>ノードの設定でurlプロパティを指定する場合、<a href="http://mustache.github.io/mustache.5.html" target="_blank">mustache形式</a>のタグを含めることができます。これにより、URLを入力メッセージの値から構成することができます。例えば、urlが<code>example.com/{{{topic}}}</code>の場合、<code>msg.topic</code>の値による置き換えを自動的に行います。{{{...}}}表記を使うと、/、&といった文字をmustacheがエスケープするのを抑止できます。</p> | ||||
|   | ||||
| @@ -206,7 +206,7 @@ | ||||
|         "template": "template", | ||||
|         "label": { | ||||
|             "template": "テンプレート", | ||||
|             "property": "設定先", | ||||
|             "property": "プロパティ", | ||||
|             "format": "構文", | ||||
|             "syntax": "形式", | ||||
|             "output": "出力形式", | ||||
| @@ -825,21 +825,6 @@ | ||||
|             "pythoncommandnotfound": "nrpgio python コマンドが実行されていません" | ||||
|         } | ||||
|     }, | ||||
|     "tail": { | ||||
|         "tail": "tail", | ||||
|         "label": { | ||||
|             "filename": "ファイル名", | ||||
|             "type": "ファイル形式", | ||||
|             "splitlines": "改行でメッセージを分割" | ||||
|         }, | ||||
|         "action": { | ||||
|             "text": "文字列", | ||||
|             "binary": "バイナリバッファ" | ||||
|         }, | ||||
|         "errors": { | ||||
|             "windowsnotsupport": "現在Windows上での動作は対応していません" | ||||
|         } | ||||
|     }, | ||||
|     "file": { | ||||
|         "label": { | ||||
|             "filename": "ファイル名", | ||||
|   | ||||
| @@ -1,25 +0,0 @@ | ||||
| <!-- | ||||
|   Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  | ||||
|   Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|   you may not use this file except in compliance with the License. | ||||
|   You may obtain a copy of the License at | ||||
|  | ||||
|   http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
|   Unless required by applicable law or agreed to in writing, software | ||||
|   distributed under the License is distributed on an "AS IS" BASIS, | ||||
|   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. | ||||
| --> | ||||
|  | ||||
| <script type="text/x-red" data-help-name="tail"> | ||||
|     <p>設定したファイルの末尾を出力(追加されたデータを監視)します。(Linux/Macのみ)</p> | ||||
|     <p>このノードは<b>tail -F</b>コマンドを内部で利用しているため、Windowsファイルシステムでは動作しません。</p> | ||||
|     <h3>出力</h3> | ||||
|     <ul> | ||||
|         <li>(UTF-8形式の)テキストファイルは文字列を返却。</li> | ||||
|         <li>バイナルファイルはバッファオブジェクトを返却。</li> | ||||
|     </ul> | ||||
| </script> | ||||
| @@ -196,7 +196,7 @@ | ||||
|     "template": { | ||||
|         "label": { | ||||
|             "template": "模版", | ||||
|             "property": "设定属性", | ||||
|             "property": "属性", | ||||
|             "format": "语法高亮", | ||||
|             "syntax": "格式", | ||||
|             "output": "输出为", | ||||
| @@ -784,20 +784,6 @@ | ||||
|             "pythoncommandnotfound": "nrpgio python命令未处于运行状态" | ||||
|         } | ||||
|     }, | ||||
|     "tail": { | ||||
|         "label": { | ||||
|             "filename": "文件名", | ||||
|             "type": "文件类型", | ||||
|             "splitlines": "以\\n来拆分行?" | ||||
|         }, | ||||
|         "action": { | ||||
|             "text": "文本 - 返回字符串", | ||||
|             "binary": "二进制 - 返回Buffer" | ||||
|         }, | ||||
|         "errors": { | ||||
|             "windowsnotsupport": "Windows目前不支持." | ||||
|         } | ||||
|     }, | ||||
|     "file": { | ||||
|         "label": { | ||||
|             "filename": "文件名", | ||||
|   | ||||
| @@ -1,34 +1,38 @@ | ||||
| { | ||||
|     "name": "@node-red/nodes", | ||||
|     "version": "0.20.0-alpha.0", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "license": "Apache-2.0", | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|         "url": "https://github.com/node-red/node-red.git" | ||||
|     }, | ||||
|     "contributors": [ | ||||
|         { "name": "Nick O'Leary" }, | ||||
|         { "name": "Dave Conway-Jones"} | ||||
|         { | ||||
|             "name": "Nick O'Leary" | ||||
|         }, | ||||
|         { | ||||
|             "name": "Dave Conway-Jones" | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "ajv": "6.5.4", | ||||
|         "ajv": "6.6.1", | ||||
|         "body-parser": "1.18.3", | ||||
|         "cheerio": "0.22.0", | ||||
|         "cookie-parser": "1.4.3", | ||||
|         "cookie": "0.3.1", | ||||
|         "cors": "2.8.4", | ||||
|         "cron": "1.5.0", | ||||
|         "denque": "1.3.0", | ||||
|         "fs-extra": "5.0.0", | ||||
|         "cors": "2.8.5", | ||||
|         "cron": "1.5.1", | ||||
|         "denque": "1.4.0", | ||||
|         "fs-extra": "7.0.1", | ||||
|         "fs.notify": "0.0.4", | ||||
|         "hash-sum": "1.0.2", | ||||
|         "https-proxy-agent": "2.2.1", | ||||
|         "is-utf8": "0.2.1", | ||||
|         "js-yaml": "3.12.0", | ||||
|         "media-typer": "0.3.0", | ||||
|         "media-typer": "1.0.1", | ||||
|         "mqtt": "2.18.8", | ||||
|         "multer": "1.4.1", | ||||
|         "mustache": "2.3.2", | ||||
|         "mustache": "3.0.1", | ||||
|         "on-headers": "1.0.1", | ||||
|         "raw-body": "2.3.3", | ||||
|         "request": "2.88.0", | ||||
|   | ||||
| @@ -13,33 +13,44 @@ | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|   | ||||
|  | ||||
| /* | ||||
|  * This provides a list of node types that have at one time been included with | ||||
|  * the core of Node-RED but have since moved out to their own module. | ||||
|  * | ||||
|  * If a user has a flow that depends on one of these types and they do not have | ||||
|  * the new module installed, this will help them identify the missing module. | ||||
|  */ | ||||
| var nodes = { | ||||
|     "irc in":     {module:"node-red-node-irc"}, | ||||
|     "irc out":    {module:"node-red-node-irc"}, | ||||
|     "irc-server": {module:"node-red-node-irc"}, | ||||
|      | ||||
|  | ||||
|     "arduino in":    {module:"node-red-node-arduino"}, | ||||
|     "arduino out":   {module:"node-red-node-arduino"}, | ||||
|     "arduino-board": {module:"node-red-node-arduino"}, | ||||
|      | ||||
|  | ||||
|     "redis out": {module:"node-red-node-redis"}, | ||||
|      | ||||
|  | ||||
|     "mongodb": {module:"node-red-node-mongodb"}, | ||||
|     "mongodb out": {module:"node-red-node-mongodb"}, | ||||
|      | ||||
|  | ||||
|     "serial in": {module:"node-red-node-serialport"}, | ||||
|     "serial out": {module:"node-red-node-serialport"}, | ||||
|     "serial-port": {module:"node-red-node-serialport"}, | ||||
|      | ||||
|  | ||||
|     "twitter-credentials": {module:"node-red-node-twitter"}, | ||||
|     "twitter in": {module:"node-red-node-twitter"}, | ||||
|     "twitter out": {module:"node-red-node-twitter"}, | ||||
|      | ||||
|  | ||||
|     "e-mail": {module:"node-red-node-email"}, | ||||
|     "e-mail in": {module:"node-red-node-email"}, | ||||
|      | ||||
|     "feedparse": {module:"node-red-node-feedparser"} | ||||
|  | ||||
|     "feedparse": {module:"node-red-node-feedparser"}, | ||||
|  | ||||
|     "sentiment": {module:"node-red-node-sentiment"}, | ||||
|  | ||||
|     "tail": {module:"node-red-node-tail"} | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|   | ||||
| @@ -235,12 +235,17 @@ function checkPrereq() { | ||||
|         return Promise.resolve(); | ||||
|     } else { | ||||
|         return new Promise(resolve => { | ||||
|             child_process.execFile(npmCommand,['-v'],function(err) { | ||||
|             child_process.execFile(npmCommand,['-v'],function(err,stdout) { | ||||
|                 if (err) { | ||||
|                     log.info(log._("server.palette-editor.npm-not-found")); | ||||
|                     paletteEditorEnabled = false; | ||||
|                 } else { | ||||
|                     paletteEditorEnabled = true; | ||||
|                     if (parseInt(stdout.split(".")[0]) < 3) { | ||||
|                         log.info(log._("server.palette-editor.npm-too-old")); | ||||
|                         paletteEditorEnabled = false; | ||||
|                     } else { | ||||
|                         paletteEditorEnabled = true; | ||||
|                     } | ||||
|                 } | ||||
|                 resolve(); | ||||
|             }); | ||||
|   | ||||
| @@ -21,8 +21,8 @@ var semver = require("semver"); | ||||
|  | ||||
| var localfilesystem = require("./localfilesystem"); | ||||
| var registry = require("./registry"); | ||||
|  | ||||
| var i18n = require("@node-red/util").i18n; // TODO: separate module | ||||
| var registryUtil = require("./util") | ||||
| var i18n = require("@node-red/util").i18n; | ||||
|  | ||||
| var settings; | ||||
| var runtime; | ||||
| @@ -31,6 +31,7 @@ function init(_runtime) { | ||||
|     runtime = _runtime; | ||||
|     settings = runtime.settings; | ||||
|     localfilesystem.init(runtime); | ||||
|     registryUtil.init(runtime); | ||||
| } | ||||
|  | ||||
| function load(defaultNodesDir,disableNodePathScan) { | ||||
| @@ -44,92 +45,6 @@ function load(defaultNodesDir,disableNodePathScan) { | ||||
|     return loadNodeFiles(nodeFiles); | ||||
| } | ||||
|  | ||||
| function copyObjectProperties(src,dst,copyList,blockList) { | ||||
|     if (!src) { | ||||
|         return; | ||||
|     } | ||||
|     if (copyList && !blockList) { | ||||
|         copyList.forEach(function(i) { | ||||
|             if (src.hasOwnProperty(i)) { | ||||
|                 var propDescriptor = Object.getOwnPropertyDescriptor(src,i); | ||||
|                 Object.defineProperty(dst,i,propDescriptor); | ||||
|             } | ||||
|         }); | ||||
|     } else if (!copyList && blockList) { | ||||
|         for (var i in src) { | ||||
|             if (src.hasOwnProperty(i) && blockList.indexOf(i) === -1) { | ||||
|                 var propDescriptor = Object.getOwnPropertyDescriptor(src,i); | ||||
|                 Object.defineProperty(dst,i,propDescriptor); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| function requireModule(name) { | ||||
|     var moduleInfo = registry.getModuleInfo(name); | ||||
|     if (moduleInfo && moduleInfo.path) { | ||||
|         var relPath = path.relative(__dirname, moduleInfo.path); | ||||
|         return require(relPath); | ||||
|     } else { | ||||
|         var err = new Error(`Cannot find module '${name}'`); | ||||
|         err.code = "MODULE_NOT_FOUND"; | ||||
|         throw err; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function createNodeApi(node) { | ||||
|     var red = { | ||||
|         nodes: {}, | ||||
|         log: {}, | ||||
|         settings: {}, | ||||
|         events: runtime.events, | ||||
|         util: runtime.util, | ||||
|         version: runtime.version, | ||||
|         require: requireModule, | ||||
|         comms: { | ||||
|             publish: function(topic,data,retain) { | ||||
|                 runtime.events.emit("comms",{ | ||||
|                     topic: topic, | ||||
|                     data: data, | ||||
|                     retain: retain | ||||
|                 }) | ||||
|             } | ||||
|         }, | ||||
|         library: { | ||||
|             register: function(type) { | ||||
|                 return runtime.library.register(node.id,type); | ||||
|             } | ||||
|         }, | ||||
|         httpNode: runtime.nodeApp, | ||||
|         server: runtime.server | ||||
|     } | ||||
|     copyObjectProperties(runtime.nodes,red.nodes,["createNode","getNode","eachNode","addCredentials","getCredentials","deleteCredentials" ]); | ||||
|     red.nodes.registerType = function(type,constructor,opts) { | ||||
|         runtime.nodes.registerType(node.id,type,constructor,opts); | ||||
|     } | ||||
|     copyObjectProperties(runtime.log,red.log,null,["init"]); | ||||
|     copyObjectProperties(runtime.settings,red.settings,null,["init","load","reset"]); | ||||
|     if (runtime.adminApi) { | ||||
|         red.auth = runtime.adminApi.auth; | ||||
|         red.httpAdmin = runtime.adminApi.adminApp; | ||||
|     } else { | ||||
|         //TODO: runtime.adminApi is always stubbed if not enabled, so this block | ||||
|         // is unused - but may be needed for the unit tests | ||||
|         red.auth = { | ||||
|             needsPermission: function() {} | ||||
|         }; | ||||
|         // TODO: stub out httpAdmin/httpNode/server | ||||
|     } | ||||
|     red["_"] = function() { | ||||
|         var args = Array.prototype.slice.call(arguments, 0); | ||||
|         if (args[0].indexOf(":") === -1) { | ||||
|             args[0] = node.namespace+":"+args[0]; | ||||
|         } | ||||
|         return i18n._.apply(null,args); | ||||
|     } | ||||
|     return red; | ||||
| } | ||||
|  | ||||
|  | ||||
| function loadNodeFiles(nodeFiles) { | ||||
|     var promises = []; | ||||
|     var nodes = []; | ||||
| @@ -332,7 +247,7 @@ function loadNodeSet(node) { | ||||
|         var r = require(node.file); | ||||
|         if (typeof r === "function") { | ||||
|  | ||||
|             var red = createNodeApi(node); | ||||
|             var red = registryUtil.createNodeApi(node); | ||||
|             var promise = r(red); | ||||
|             if (promise != null && typeof promise.then === "function") { | ||||
|                 loadPromise = promise.then(function() { | ||||
|   | ||||
							
								
								
									
										110
									
								
								packages/node_modules/@node-red/registry/lib/util.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								packages/node_modules/@node-red/registry/lib/util.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * 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. | ||||
|  **/ | ||||
|  | ||||
| var i18n = require("@node-red/util").i18n; | ||||
| var runtime; | ||||
|  | ||||
| function copyObjectProperties(src,dst,copyList,blockList) { | ||||
|     if (!src) { | ||||
|         return; | ||||
|     } | ||||
|     if (copyList && !blockList) { | ||||
|         copyList.forEach(function(i) { | ||||
|             if (src.hasOwnProperty(i)) { | ||||
|                 var propDescriptor = Object.getOwnPropertyDescriptor(src,i); | ||||
|                 Object.defineProperty(dst,i,propDescriptor); | ||||
|             } | ||||
|         }); | ||||
|     } else if (!copyList && blockList) { | ||||
|         for (var i in src) { | ||||
|             if (src.hasOwnProperty(i) && blockList.indexOf(i) === -1) { | ||||
|                 var propDescriptor = Object.getOwnPropertyDescriptor(src,i); | ||||
|                 Object.defineProperty(dst,i,propDescriptor); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| function requireModule(name) { | ||||
|     var moduleInfo = registry.getModuleInfo(name); | ||||
|     if (moduleInfo && moduleInfo.path) { | ||||
|         var relPath = path.relative(__dirname, moduleInfo.path); | ||||
|         return require(relPath); | ||||
|     } else { | ||||
|         var err = new Error(`Cannot find module '${name}'`); | ||||
|         err.code = "MODULE_NOT_FOUND"; | ||||
|         throw err; | ||||
|     } | ||||
| } | ||||
|  | ||||
| function createNodeApi(node) { | ||||
|     var red = { | ||||
|         nodes: {}, | ||||
|         log: {}, | ||||
|         settings: {}, | ||||
|         events: runtime.events, | ||||
|         util: runtime.util, | ||||
|         version: runtime.version, | ||||
|         require: requireModule, | ||||
|         comms: { | ||||
|             publish: function(topic,data,retain) { | ||||
|                 runtime.events.emit("comms",{ | ||||
|                     topic: topic, | ||||
|                     data: data, | ||||
|                     retain: retain | ||||
|                 }) | ||||
|             } | ||||
|         }, | ||||
|         library: { | ||||
|             register: function(type) { | ||||
|                 return runtime.library.register(node.id,type); | ||||
|             } | ||||
|         }, | ||||
|         httpNode: runtime.nodeApp, | ||||
|         httpAdmin: runtime.adminApp, | ||||
|         server: runtime.server | ||||
|     } | ||||
|     copyObjectProperties(runtime.nodes,red.nodes,["createNode","getNode","eachNode","addCredentials","getCredentials","deleteCredentials" ]); | ||||
|     red.nodes.registerType = function(type,constructor,opts) { | ||||
|         runtime.nodes.registerType(node.id,type,constructor,opts); | ||||
|     } | ||||
|     copyObjectProperties(runtime.log,red.log,null,["init"]); | ||||
|     copyObjectProperties(runtime.settings,red.settings,null,["init","load","reset"]); | ||||
|     if (runtime.adminApi) { | ||||
|         red.auth = runtime.adminApi.auth; | ||||
|     } else { | ||||
|         //TODO: runtime.adminApi is always stubbed if not enabled, so this block | ||||
|         // is unused - but may be needed for the unit tests | ||||
|         red.auth = { | ||||
|             needsPermission: function(v) { return function(req,res,next) {next()} } | ||||
|         }; | ||||
|         // TODO: stub out httpAdmin/httpNode/server | ||||
|     } | ||||
|     red["_"] = function() { | ||||
|         var args = Array.prototype.slice.call(arguments, 0); | ||||
|         if (args[0].indexOf(":") === -1) { | ||||
|             args[0] = node.namespace+":"+args[0]; | ||||
|         } | ||||
|         return i18n._.apply(null,args); | ||||
|     } | ||||
|     return red; | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     init: function(_runtime) { | ||||
|         runtime = _runtime; | ||||
|     }, | ||||
|     createNodeApi: createNodeApi | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@node-red/registry", | ||||
|     "version": "0.20.0-alpha.0", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "license": "Apache-2.0", | ||||
|     "main": "./lib/index.js", | ||||
|     "repository": { | ||||
| @@ -8,11 +8,15 @@ | ||||
|         "url": "https://github.com/node-red/node-red.git" | ||||
|     }, | ||||
|     "contributors": [ | ||||
|         { "name": "Nick O'Leary" }, | ||||
|         { "name": "Dave Conway-Jones"} | ||||
|         { | ||||
|             "name": "Nick O'Leary" | ||||
|         }, | ||||
|         { | ||||
|             "name": "Dave Conway-Jones" | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "@node-red/util": "*", | ||||
|         "@node-red/util": "0.20.0-beta.2", | ||||
|         "semver": "5.6.0", | ||||
|         "uglify-js": "3.4.9", | ||||
|         "when": "3.7.8" | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| /** | ||||
| /*! | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| @@ -14,6 +14,30 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var events = require("events");  | ||||
| var events = require("events"); | ||||
|  | ||||
| module.exports = new events.EventEmitter();  | ||||
| module.exports = new events.EventEmitter(); | ||||
|  | ||||
| /** | ||||
|  * Runtime events emitter | ||||
|  * @mixin @node-red/runtime_events | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Register an event listener for a runtime event | ||||
|  * @name on | ||||
|  * @function | ||||
|  * @memberof @node-red/runtime_events | ||||
|  * @param {String} eventName - the name of the event to listen to | ||||
|  * @param {Function} listener - the callback function for the event | ||||
|  */ | ||||
|  | ||||
|  /** | ||||
|   * Emit an event to all of its registered listeners | ||||
|   * @name emit | ||||
|   * @function | ||||
|   * @memberof @node-red/runtime_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 | ||||
|   */ | ||||
|   | ||||
| @@ -53,6 +53,7 @@ var adminApi = { | ||||
| } | ||||
|  | ||||
| var nodeApp; | ||||
| var adminApp; | ||||
| var server; | ||||
|  | ||||
|  | ||||
| @@ -64,12 +65,13 @@ var server; | ||||
|  *                              better abstracted. | ||||
|  * @memberof @node-red/runtime | ||||
|  */ | ||||
| function init(userSettings,httpServer,_adminApi) { | ||||
| function init(userSettings,httpServer,_adminApi,__util) { | ||||
|     server = httpServer; | ||||
|     userSettings.version = getVersion(); | ||||
|     settings.init(userSettings); | ||||
|  | ||||
|     nodeApp = express(); | ||||
|     adminApp = express(); | ||||
|  | ||||
|     if (_adminApi) { | ||||
|         adminApi = _adminApi; | ||||
| @@ -78,6 +80,13 @@ function init(userSettings,httpServer,_adminApi) { | ||||
|     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; | ||||
| @@ -103,7 +112,6 @@ function getVersion() { | ||||
|  * @memberof @node-red/runtime | ||||
|  */ | ||||
| function start() { | ||||
|  | ||||
|     return i18n.registerMessageCatalog("runtime",path.resolve(path.join(__dirname,"..","locales")),"runtime.json") | ||||
|         .then(function() { return storage.init(runtime)}) | ||||
|         .then(function() { return settings.load(storage)}) | ||||
| @@ -269,6 +277,7 @@ var runtime = { | ||||
|     exec: exec, | ||||
|     util: require("@node-red/util").util, | ||||
|     get adminApi() { return adminApi }, | ||||
|     get adminApp() { return adminApp }, | ||||
|     get nodeApp() { return nodeApp }, | ||||
|     get server() { return server }, | ||||
|     isStarted: function() { | ||||
| @@ -346,8 +355,12 @@ module.exports = { | ||||
|  | ||||
|     storage: storage, | ||||
|     events: events, | ||||
|     util: require("@node-red/util").util, | ||||
|     get httpNode() { return nodeApp }, | ||||
|     get server() { return server } | ||||
|     get httpAdmin() { return adminApp }, | ||||
|     get server() { return server }, | ||||
|  | ||||
|     "_": runtime | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,8 @@ | ||||
|         "loading": "Loading palette nodes", | ||||
|         "palette-editor": { | ||||
|             "disabled": "Palette editor disabled : user settings", | ||||
|             "npm-not-found": "Palette editor disabled : npm command not found" | ||||
|             "npm-not-found": "Palette editor disabled : npm command not found", | ||||
|             "npm-too-old": "Palette editor disabled : npm version too old. Requires npm >= 3.x" | ||||
|         }, | ||||
|         "errors": "Failed to register __count__ node type", | ||||
|         "errors_plural": "Failed to register __count__ node types", | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@node-red/runtime", | ||||
|     "version": "0.20.0-alpha.0", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "license": "Apache-2.0", | ||||
|     "main": "./lib/index.js", | ||||
|     "repository": { | ||||
| @@ -8,15 +8,19 @@ | ||||
|         "url": "https://github.com/node-red/node-red.git" | ||||
|     }, | ||||
|     "contributors": [ | ||||
|         { "name": "Nick O'Leary" }, | ||||
|         { "name": "Dave Conway-Jones"} | ||||
|         { | ||||
|             "name": "Nick O'Leary" | ||||
|         }, | ||||
|         { | ||||
|             "name": "Dave Conway-Jones" | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "@node-red/registry": "*", | ||||
|         "@node-red/util": "*", | ||||
|         "@node-red/registry": "0.20.0-beta.2", | ||||
|         "@node-red/util": "0.20.0-beta.2", | ||||
|         "clone": "2.1.2", | ||||
|         "express": "4.16.4", | ||||
|         "fs-extra": "5.0.0", | ||||
|         "fs-extra": "7.0.1", | ||||
|         "json-stringify-safe": "5.0.1", | ||||
|         "when": "3.7.8" | ||||
|     } | ||||
|   | ||||
							
								
								
									
										20
									
								
								packages/node_modules/@node-red/util/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								packages/node_modules/@node-red/util/index.js
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /** | ||||
| /*! | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| @@ -14,17 +14,20 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
|  /** | ||||
|   * @module @node-red/util | ||||
|   */ | ||||
| const log = require("./lib/log"); | ||||
| const i18n = require("./lib/i18n"); | ||||
| const util = require("./lib/util"); | ||||
|  | ||||
| /** | ||||
|  * This module provides common utilities for the Node-RED runtime and editor | ||||
|  * | ||||
|  * @namespace @node-red/util | ||||
|  */ | ||||
| module.exports = { | ||||
|     /** | ||||
|     * Initialise the module with the runtime settings | ||||
|     * @param {Object} settings | ||||
|     * @memberof @node-red/util | ||||
|     */ | ||||
|     init: function(settings) { | ||||
|         log.init(settings); | ||||
| @@ -33,19 +36,22 @@ module.exports = { | ||||
|  | ||||
|     /** | ||||
|     * Logging utilities | ||||
|     * @see module:@node-red/util.module:log | ||||
|     * @mixes @node-red/util_log | ||||
|     * @memberof @node-red/util | ||||
|     */ | ||||
|     log: log, | ||||
|  | ||||
|     /** | ||||
|     * Internationalization utilities | ||||
|     * @see module:@node-red/util.module:i18n | ||||
|     * @mixes @node-red/util_i18n | ||||
|     * @memberof @node-red/util | ||||
|     */ | ||||
|     i18n: i18n, | ||||
|  | ||||
|     /** | ||||
|     * General utilities | ||||
|     * @see module:@node-red/util.module:util | ||||
|     * @mixes @node-red/util_util | ||||
|     * @memberof @node-red/util | ||||
|     */ | ||||
|     util: util, | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								packages/node_modules/@node-red/util/lib/i18n.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								packages/node_modules/@node-red/util/lib/i18n.js
									
									
									
									
										vendored
									
									
								
							| @@ -15,10 +15,10 @@ | ||||
|  * @ignore | ||||
|  **/ | ||||
|  | ||||
|  /** | ||||
|   * @module i18n | ||||
|   * @memberof module:@node-red/util | ||||
|   */ | ||||
| /** | ||||
|  * Internationalization utilities | ||||
|  * @mixin @node-red/util_i18n | ||||
|  */ | ||||
|  | ||||
| var i18n = require("i18next"); | ||||
|  | ||||
| @@ -34,7 +34,7 @@ var initPromise; | ||||
|  | ||||
| /** | ||||
|  * Register multiple message catalogs with i18n. | ||||
|  * @memberof module:@node-red/util.module:i18n | ||||
|  * @memberof @node-red/util_i18n | ||||
|  */ | ||||
| function registerMessageCatalogs(catalogs) { | ||||
|     var promises = catalogs.map(function(catalog) { | ||||
| @@ -45,7 +45,7 @@ function registerMessageCatalogs(catalogs) { | ||||
|  | ||||
| /** | ||||
|  * Register a message catalog with i18n. | ||||
|  * @memberof module:@node-red/util.module:i18n | ||||
|  * @memberof @node-red/util_i18n | ||||
|  */ | ||||
| function registerMessageCatalog(namespace,dir,file) { | ||||
|     return initPromise.then(function() { | ||||
| @@ -146,7 +146,7 @@ function init() { | ||||
|  * Gets a message catalog. | ||||
|  * @name catalog | ||||
|  * @function | ||||
|  * @memberof module:@node-red/util.module:i18n | ||||
|  * @memberof @node-red/util_i18n | ||||
|  */ | ||||
| function getCatalog(namespace,lang) { | ||||
|     var result = null; | ||||
| @@ -182,7 +182,7 @@ var obj = module.exports = { | ||||
|  * Perform a message catalog lookup. | ||||
|  * @name _ | ||||
|  * @function | ||||
|  * @memberof module:@node-red/util.module:i18n | ||||
|  * @memberof @node-red/util_i18n | ||||
|  */ | ||||
| obj['_'] = function() { | ||||
|     //var opts = {}; | ||||
|   | ||||
							
								
								
									
										34
									
								
								packages/node_modules/@node-red/util/lib/log.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								packages/node_modules/@node-red/util/lib/log.js
									
									
									
									
										vendored
									
									
								
							| @@ -16,8 +16,8 @@ | ||||
|  **/ | ||||
|  | ||||
| /** | ||||
|  * @module log | ||||
|  * @memberof module:@node-red/util | ||||
|  * Logging utilities | ||||
|  * @mixin @node-red/util_log | ||||
|  */ | ||||
|  | ||||
| var util = require("util"); | ||||
| @@ -128,14 +128,16 @@ var log = module.exports = { | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Add a log handler function. | ||||
|      * Add a log handler function | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     addHandler: function(func) { | ||||
|         logHandlers.push(func); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Remove a log handler function. | ||||
|      * Remove a log handler function | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     removeHandler: function(func) { | ||||
|         var index = logHandlers.indexOf(func); | ||||
| @@ -145,7 +147,8 @@ var log = module.exports = { | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Log a message object. | ||||
|      * Log a message object | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     log: function(msg) { | ||||
|         msg.timestamp = Date.now(); | ||||
| @@ -155,42 +158,48 @@ var log = module.exports = { | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Log a message at INFO level. | ||||
|      * Log a message at INFO level | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     info: function(msg) { | ||||
|         log.log({level:log.INFO,msg:msg}); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Log a message at WARN level. | ||||
|      * Log a message at WARN level | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     warn: function(msg) { | ||||
|         log.log({level:log.WARN,msg:msg}); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Log a message at ERROR level. | ||||
|      * Log a message at ERROR level | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     error: function(msg) { | ||||
|         log.log({level:log.ERROR,msg:msg}); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Log a message at TRACE level. | ||||
|      * Log a message at TRACE level | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     trace: function(msg) { | ||||
|         log.log({level:log.TRACE,msg:msg}); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Log a message at DEBUG level. | ||||
|      * Log a message at DEBUG level | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     debug: function(msg) { | ||||
|         log.log({level:log.DEBUG,msg:msg}); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Log a metric event. | ||||
|      * Check if metrics are enabled | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     metric: function() { | ||||
|         return metricsEnabled; | ||||
| @@ -198,6 +207,7 @@ var log = module.exports = { | ||||
|  | ||||
|     /** | ||||
|      * Log an audit event. | ||||
|      * @memberof @node-red/util_log | ||||
|      */ | ||||
|     audit: function(msg,req) { | ||||
|         msg.level = log.AUDIT; | ||||
| @@ -214,6 +224,6 @@ var log = module.exports = { | ||||
|  * Perform a message catalog lookup. | ||||
|  * @name _ | ||||
|  * @function | ||||
|  * @memberof module:@node-red/util.module:log | ||||
|  * @memberof @node-red/util_log | ||||
|  */ | ||||
| log["_"] = i18n._; | ||||
|   | ||||
							
								
								
									
										41
									
								
								packages/node_modules/@node-red/util/lib/util.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								packages/node_modules/@node-red/util/lib/util.js
									
									
									
									
										vendored
									
									
								
							| @@ -15,10 +15,9 @@ | ||||
|  * @ignore | ||||
|  **/ | ||||
|  | ||||
|  /** | ||||
|   * @module util | ||||
|   * @memberof module:@node-red/util | ||||
|   */ | ||||
| /** | ||||
|  * @mixin @node-red/util_util | ||||
|  */ | ||||
|  | ||||
|  | ||||
| const clone = require("clone"); | ||||
| @@ -29,7 +28,7 @@ const util = require("util"); | ||||
| /** | ||||
|  * Generates a psuedo-unique-random id. | ||||
|  * @return {String} a random-ish id | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function generateId() { | ||||
|     return (1+Math.random()*4294967295).toString(16); | ||||
| @@ -41,7 +40,7 @@ function generateId() { | ||||
|  * | ||||
|  * @param  {any}    o - the property to convert to a String | ||||
|  * @return {String} the stringified version | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function ensureString(o) { | ||||
|     if (Buffer.isBuffer(o)) { | ||||
| @@ -60,7 +59,7 @@ function ensureString(o) { | ||||
|  * | ||||
|  * @param  {any}    o - the property to convert to a Buffer | ||||
|  * @return {String} the Buffer version | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function ensureBuffer(o) { | ||||
|     if (Buffer.isBuffer(o)) { | ||||
| @@ -79,7 +78,7 @@ function ensureBuffer(o) { | ||||
|  * | ||||
|  * @param  {any}    msg - the message object to clone | ||||
|  * @return {Object} the cloned message | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function cloneMessage(msg) { | ||||
|     // Temporary fix for #97 | ||||
| @@ -106,7 +105,7 @@ function cloneMessage(msg) { | ||||
|  * @param  {any}    obj1 | ||||
|  * @param  {any}    obj2 | ||||
|  * @return {boolean} whether the two objects are the same | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function compareObjects(obj1,obj2) { | ||||
|     var i; | ||||
| @@ -189,7 +188,7 @@ function createError(code, message) { | ||||
|  * | ||||
|  * @param  {String} str - the property expression | ||||
|  * @return {Array} the normalised expression | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function normalisePropertyExpression(str) { | ||||
|     // This must be kept in sync with validatePropertyExpression | ||||
| @@ -304,7 +303,7 @@ function normalisePropertyExpression(str) { | ||||
|  * @param  {Object} msg - the message object | ||||
|  * @param  {String} str - the property expression | ||||
|  * @return {any} the message property, or undefined if it does not exist | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function getMessageProperty(msg,expr) { | ||||
|     if (expr.indexOf('msg.')===0) { | ||||
| @@ -319,7 +318,7 @@ function getMessageProperty(msg,expr) { | ||||
|  * @param  {Object} msg - the object | ||||
|  * @param  {String} str - the property expression | ||||
|  * @return {any} the object property, or undefined if it does not exist | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function getObjectProperty(msg,expr) { | ||||
|     var result = null; | ||||
| @@ -342,7 +341,7 @@ function getObjectProperty(msg,expr) { | ||||
|  * @param  {String}  prop          - the property expression | ||||
|  * @param  {any}     value         - the value to set | ||||
|  * @param  {boolean} createMissing - whether to create missing parent properties | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function setMessageProperty(msg,prop,value,createMissing) { | ||||
|     if (prop.indexOf('msg.')===0) { | ||||
| @@ -358,7 +357,7 @@ function setMessageProperty(msg,prop,value,createMissing) { | ||||
|  * @param  {String}  prop          - the property expression | ||||
|  * @param  {any}     value         - the value to set | ||||
|  * @param  {boolean} createMissing - whether to create missing parent properties | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function setObjectProperty(msg,prop,value,createMissing) { | ||||
|     if (typeof createMissing === 'undefined') { | ||||
| @@ -422,7 +421,7 @@ function setObjectProperty(msg,prop,value,createMissing) { | ||||
|  * will return `Hello Joe!`. | ||||
|  * @param  {String} value - the string to parse | ||||
|  * @return {String} The parsed string | ||||
| * @memberof module:@node-red/util.module:util | ||||
| * @memberof @node-red/util_util | ||||
|  */ | ||||
| function evaluateEnvProperty(value) { | ||||
|     if (/^\${[^}]+}$/.test(value)) { | ||||
| @@ -450,7 +449,7 @@ function evaluateEnvProperty(value) { | ||||
|  * | ||||
|  * @param  {String} value - the context property string to parse | ||||
|  * @return {Object} The parsed property | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function parseContextStore(key) { | ||||
|     var parts = {}; | ||||
| @@ -474,7 +473,7 @@ function parseContextStore(key) { | ||||
|  * @param  {Object}   msg      - the message object to evaluate against | ||||
|  * @param  {Function} callback - (optional) called when the property is evaluated | ||||
|  * @return {any} The evaluted property, if no `callback` is provided | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function evaluateNodeProperty(value, type, node, msg, callback) { | ||||
|     var result = value; | ||||
| @@ -531,7 +530,7 @@ function evaluateNodeProperty(value, type, node, msg, callback) { | ||||
|  * @param  {String} value - the JSONata expression | ||||
|  * @param  {Node}   node  - the node evaluating the property | ||||
|  * @return {Object} The JSONata expression that can be evaluated | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function prepareJSONataExpression(value,node) { | ||||
|     var expr = jsonata(value); | ||||
| @@ -559,7 +558,7 @@ function prepareJSONataExpression(value,node) { | ||||
|  * @param  {Object}   msg      - the message object to evaluate against | ||||
|  * @param  {Function} callback - (optional) called when the expression is evaluated | ||||
|  * @return {any} If no callback was provided, the result of the expression | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function evaluateJSONataExpression(expr,msg,callback) { | ||||
|     var context = msg; | ||||
| @@ -604,7 +603,7 @@ function evaluateJSONataExpression(expr,msg,callback) { | ||||
|  * | ||||
|  * @param  {String} name - the node type | ||||
|  * @return {String} The normalised name | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function normaliseNodeTypeName(name) { | ||||
|     var result = name.replace(/[^a-zA-Z0-9]/g, " "); | ||||
| @@ -628,7 +627,7 @@ function normaliseNodeTypeName(name) { | ||||
|  * @param  {Object} msg | ||||
|  * @param {Object} opts | ||||
|  * @return {Object} the encoded object | ||||
|  * @memberof module:@node-red/util.module:util | ||||
|  * @memberof @node-red/util_util | ||||
|  */ | ||||
| function encodeObject(msg,opts) { | ||||
|     var debuglength = 1000; | ||||
|   | ||||
| @@ -1,18 +1,22 @@ | ||||
| { | ||||
|     "name": "@node-red/util", | ||||
|     "version": "0.20.0-alpha.0", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "license": "Apache-2.0", | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|         "url": "https://github.com/node-red/node-red.git" | ||||
|     }, | ||||
|     "contributors": [ | ||||
|         { "name": "Nick O'Leary" }, | ||||
|         { "name": "Dave Conway-Jones"} | ||||
|         { | ||||
|             "name": "Nick O'Leary" | ||||
|         }, | ||||
|         { | ||||
|             "name": "Dave Conway-Jones" | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "clone": "2.1.2", | ||||
|         "i18next": "11.6.0", | ||||
|         "i18next": "12.1.0", | ||||
|         "json-stringify-safe": "5.0.1", | ||||
|         "jsonata": "1.5.4", | ||||
|         "when": "3.7.8" | ||||
|   | ||||
							
								
								
									
										1
									
								
								packages/node_modules/node-red/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packages/node_modules/node-red/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| CHANGELOG.md | ||||
							
								
								
									
										24
									
								
								packages/node_modules/node-red/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								packages/node_modules/node-red/README.md
									
									
									
									
										vendored
									
									
								
							| @@ -9,11 +9,6 @@ A visual tool for wiring the Internet of Things. | ||||
|  | ||||
|  | ||||
|  | ||||
| ### Repository Structure | ||||
|  | ||||
| This is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) containing the source | ||||
| code for all of the Node-RED component modules. | ||||
|  | ||||
| ## Quick Start | ||||
|  | ||||
| Check out http://nodered.org/docs/getting-started/ for full instructions on getting | ||||
| @@ -31,24 +26,7 @@ For further help, or general discussion, please use the [Node-RED Forum](https:/ | ||||
|  | ||||
| ## Developers | ||||
|  | ||||
| If you want to run the latest code from git, here's how to get started: | ||||
|  | ||||
| 1. Clone the code: | ||||
|  | ||||
|         git clone https://github.com/node-red/node-red.git | ||||
|         cd node-red | ||||
|  | ||||
| 2. Install the node-red dependencies | ||||
|  | ||||
|         npm install | ||||
|  | ||||
| 3. Build the code | ||||
|  | ||||
|         npm run build | ||||
|  | ||||
| 4. Run | ||||
|  | ||||
|         npm start | ||||
| The main Node-RED modules are maintained as a monorepo on [GitHub](https://github.com/node-red/node-red). | ||||
|  | ||||
| ## Contributing | ||||
|  | ||||
|   | ||||
							
								
								
									
										42
									
								
								packages/node_modules/node-red/lib/red.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								packages/node_modules/node-red/lib/red.js
									
									
									
									
										vendored
									
									
								
							| @@ -63,8 +63,13 @@ module.exports = { | ||||
|         } | ||||
|         redUtil.init(userSettings); | ||||
|         if (userSettings.httpAdminRoot !== false) { | ||||
|             // Initialise the runtime | ||||
|             runtime.init(userSettings,httpServer,api); | ||||
|             // Initialise the editor-api | ||||
|             api.init(userSettings,httpServer,runtime.storage,runtime); | ||||
|             // Attach the runtime admin app to the api admin app | ||||
|             api.httpAdmin.use(runtime.httpAdmin); | ||||
|  | ||||
|             apiEnabled = true; | ||||
|             server = httpServer; | ||||
|         } else { | ||||
| @@ -103,19 +108,46 @@ module.exports = { | ||||
|         }) | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Logging utilities | ||||
|      * @see @node-red/util_log | ||||
|      * @memberof node-red | ||||
|      */ | ||||
|     log: redUtil.log, | ||||
|  | ||||
|     /** | ||||
|      * General utilities | ||||
|      * @see @node-red/util_util | ||||
|      * @memberof node-red | ||||
|      */ | ||||
|     util: redUtil.util, | ||||
|  | ||||
|     get nodes() { console.log("Deprecated use of RED.nodes - refer to API documentation on RED.runtime.nodes"); return runtime._.nodes }, | ||||
|     get settings() { console.log("Deprecated use of RED.settings - refer to API documentation on RED.runtime.settings"); return runtime._.settings }, | ||||
|     get version() { console.log("Deprecated use of RED.version - refer to API documentation on RED.runtime.version"); return runtime._.version }, | ||||
|     get events() { console.log("Deprecated use of RED.events - refer to API documentation on RED.runtime.events"); return runtime.events }, | ||||
|     get nodes() { return runtime._.nodes }, | ||||
|  | ||||
|     /** | ||||
|      * Runtime events emitter | ||||
|      * @see @node-red/runtime_events | ||||
|      * @memberof node-red | ||||
|      */ | ||||
|     events: runtime.events, | ||||
|  | ||||
|     get settings() { return runtime._.settings }, | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Get the version of the runtime | ||||
|      * @return {String} - the runtime version | ||||
|      * @function | ||||
|      * @memberof node-red | ||||
|      */ | ||||
|     get version() { return runtime._.version }, | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * The express application for the Editor Admin API | ||||
|      * @memberof node-red | ||||
|      */ | ||||
|     get httpAdmin() { return api.adminApp }, | ||||
|     get httpAdmin() { return api.httpAdmin }, | ||||
|  | ||||
|     /** | ||||
|      * The express application for HTTP Nodes | ||||
|   | ||||
							
								
								
									
										26
									
								
								packages/node_modules/node-red/package.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								packages/node_modules/node-red/package.json
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "node-red", | ||||
|     "version": "0.20.0-alpha.0", | ||||
|     "version": "0.20.0-beta.2", | ||||
|     "description": "A visual tool for wiring the Internet of Things", | ||||
|     "homepage": "http://nodered.org", | ||||
|     "license": "Apache-2.0", | ||||
| @@ -17,8 +17,12 @@ | ||||
|         "node-red-pi": "bin/node-red-pi" | ||||
|     }, | ||||
|     "contributors": [ | ||||
|         { "name": "Nick O'Leary" }, | ||||
|         { "name": "Dave Conway-Jones"} | ||||
|         { | ||||
|             "name": "Nick O'Leary" | ||||
|         }, | ||||
|         { | ||||
|             "name": "Dave Conway-Jones" | ||||
|         } | ||||
|     ], | ||||
|     "keywords": [ | ||||
|         "editor", | ||||
| @@ -27,17 +31,19 @@ | ||||
|         "flow" | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "@node-red/editor-api": "0.20.0-alpha.0", | ||||
|         "@node-red/runtime": "0.20.0-alpha.0", | ||||
|         "@node-red/util": "0.20.0-alpha.0", | ||||
|         "@node-red/nodes": "0.20.0-alpha.0", | ||||
|         "@node-red/editor-api": "0.20.0-beta.2", | ||||
|         "@node-red/runtime": "0.20.0-beta.2", | ||||
|         "@node-red/util": "0.20.0-beta.2", | ||||
|         "@node-red/nodes": "0.20.0-beta.2", | ||||
|         "basic-auth": "2.0.1", | ||||
|         "bcryptjs": "2.4.3", | ||||
|         "express": "4.16.4", | ||||
|         "fs-extra": "5.0.0", | ||||
|         "node-red-node-email": "0.1.*", | ||||
|         "node-red-node-feedparser": "^0.1.12", | ||||
|         "fs-extra": "7.0.1", | ||||
|         "node-red-node-email": "1.0.*", | ||||
|         "node-red-node-feedparser": "^0.1.14", | ||||
|         "node-red-node-rbe": "0.2.*", | ||||
|         "node-red-node-sentiment": "^0.1.0", | ||||
|         "node-red-node-tail": "^0.0.1", | ||||
|         "node-red-node-twitter": "^1.1.0", | ||||
|         "nopt": "4.0.1", | ||||
|         "semver": "5.6.0" | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #!/usr/bin/env node | ||||
|  | ||||
| const path = require("path"); | ||||
| const fs = require("fs"); | ||||
| const fs = require("fs-extra"); | ||||
| const should = require("should"); | ||||
|  | ||||
| const rootPackage = require(path.join("..","package.json")); | ||||
| @@ -16,8 +16,11 @@ const packages = [ | ||||
|     "@node-red/util" | ||||
| ]; | ||||
|  | ||||
| const fixFlag = process.argv[2] === '--fix'; | ||||
|  | ||||
| function verifyDependencies() { | ||||
|     let failures = []; | ||||
|     let packageUpdates = {}; | ||||
|     packages.forEach(package => { | ||||
|         let modulePackage = require(path.join("../packages/node_modules",package,"package.json")); | ||||
|         let dependencies = Object.keys(modulePackage.dependencies||{}); | ||||
| @@ -25,22 +28,48 @@ function verifyDependencies() { | ||||
|             try { | ||||
|                 if (!/^@node-red\//.test(module)) { | ||||
|                     should.exist(rootDependencies[module],`[${package}] '${module}' missing from root package.json`); | ||||
|                     rootDependencies[module].should.eql(modulePackage.dependencies[module],`[${package}] '${module}' version mismatch. Expected '${modulePackage.dependencies[module]}' (got '${rootDependencies[module]}') `); | ||||
|                     try { | ||||
|                         rootDependencies[module].should.eql(modulePackage.dependencies[module],`[${package}] '${module}' version mismatch. Expected '${modulePackage.dependencies[module]}' (got '${rootDependencies[module]}') `); | ||||
|                     } catch(err) { | ||||
|                         if (fixFlag) { | ||||
|                             modulePackage.dependencies[module] = rootDependencies[module]; | ||||
|                             packageUpdates[package] = modulePackage; | ||||
|                         } else { | ||||
|                             failures.push(err.toString()); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } catch(err) { | ||||
|                 failures.push(err.toString()); | ||||
|             } | ||||
|         }); | ||||
|     }) | ||||
|     return failures; | ||||
|     if (failures.length === 0 && fixFlag) { | ||||
|         var promises = []; | ||||
|         packages.forEach(package => { | ||||
|             if (packageUpdates.hasOwnProperty(package)) { | ||||
|                 promises.push(fs.writeJSON(path.join(__dirname,"../packages/node_modules",package,"package.json"),packageUpdates[package],{spaces:4})); | ||||
|             } | ||||
|         }); | ||||
|         return Promise.all(promises).then(r => []).catch(e => { | ||||
|             console.log(e); | ||||
|             process.exit(1); | ||||
|         }) | ||||
|     } else { | ||||
|         return Promise.resolve(failures); | ||||
|     } | ||||
| } | ||||
|  | ||||
| if (require.main === module) { | ||||
|     let failures = verifyDependencies(); | ||||
|     if (failures.length > 0) { | ||||
|         failures.forEach(f => console.log(` - ${f}`)); | ||||
|     verifyDependencies().then(failures => { | ||||
|         if (failures.length > 0) { | ||||
|             failures.forEach(f => console.log(` - ${f}`)); | ||||
|             process.exit(1); | ||||
|         } | ||||
|     }).catch(e => { | ||||
|         console.log(e); | ||||
|         process.exit(1); | ||||
|     } | ||||
|     }); | ||||
| } else { | ||||
|     module.exports = verifyDependencies; | ||||
| } | ||||
|   | ||||
| @@ -1,178 +0,0 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * 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. | ||||
|  **/ | ||||
|  | ||||
| var should = require("should"); | ||||
| var sentimentNode = require("nr-test-utils").require("@node-red/nodes/core/analysis/72-sentiment.js"); | ||||
| var helper = require("node-red-node-test-helper"); | ||||
|  | ||||
| describe('sentiment Node', function() { | ||||
|  | ||||
|     before(function(done) { | ||||
|         helper.startServer(done); | ||||
|     }); | ||||
|  | ||||
|     after(function(done) { | ||||
|         helper.stopServer(done); | ||||
|     }); | ||||
|  | ||||
|     afterEach(function() { | ||||
|         helper.unload(); | ||||
|     }); | ||||
|  | ||||
|     it('should be loaded', function(done) { | ||||
|         var flow = [{id:"sentimentNode1", type:"sentiment", name: "sentimentNode" }]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var sentimentNode1 = helper.getNode("sentimentNode1"); | ||||
|             sentimentNode1.should.have.property('name', 'sentimentNode'); | ||||
|             done(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('should pass on msg if no payload', function(done) { | ||||
|         var flow = [{id:"jn1",type:"sentiment",wires:[["jn2"]]}, | ||||
|                     {id:"jn2", type:"helper"}]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var jn1 = helper.getNode("jn1"); | ||||
|             var jn2 = helper.getNode("jn2"); | ||||
|             jn2.on("input", function(msg) { | ||||
|                 msg.should.not.have.property('sentiment'); | ||||
|                 msg.topic.should.equal("pass on"); | ||||
|                 done(); | ||||
|             }); | ||||
|             var testString = 'good, great, best, brilliant'; | ||||
|             jn1.receive({topic:"pass on"}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('should add a positive score for good words', function(done) { | ||||
|         var flow = [{id:"jn1",type:"sentiment",wires:[["jn2"]]}, | ||||
|                     {id:"jn2", type:"helper"}]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var jn1 = helper.getNode("jn1"); | ||||
|             var jn2 = helper.getNode("jn2"); | ||||
|             jn2.on("input", function(msg) { | ||||
|                 try { | ||||
|                     msg.should.have.property('sentiment'); | ||||
|                     msg.sentiment.should.have.property('score'); | ||||
|                     msg.sentiment.score.should.be.a.Number(); | ||||
|                     msg.sentiment.score.should.be.above(10); | ||||
|                     done(); | ||||
|                 } catch(err) { | ||||
|                     done(err); | ||||
|                 } | ||||
|             }); | ||||
|             var testString = 'good, great, best, brilliant'; | ||||
|             jn1.receive({payload:testString}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('should add a positive score for good words - alternative property', function(done) { | ||||
|         var flow = [{id:"jn1",type:"sentiment",property:"foo",wires:[["jn2"]]}, | ||||
|                     {id:"jn2", type:"helper"}]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var jn1 = helper.getNode("jn1"); | ||||
|             var jn2 = helper.getNode("jn2"); | ||||
|             jn2.on("input", function(msg) { | ||||
|                 try { | ||||
|                     msg.should.have.property('sentiment'); | ||||
|                     msg.sentiment.should.have.property('score'); | ||||
|                     msg.sentiment.score.should.be.a.Number(); | ||||
|                     msg.sentiment.score.should.be.above(10); | ||||
|                     done(); | ||||
|                 } catch(err) { | ||||
|                     done(err); | ||||
|                 } | ||||
|             }); | ||||
|             var testString = 'good, great, best, brilliant'; | ||||
|             jn1.receive({foo:testString}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('should add a negative score for bad words', function(done) { | ||||
|         var flow = [{id:"jn1",type:"sentiment",wires:[["jn2"]]}, | ||||
|                     {id:"jn2", type:"helper"}]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var jn1 = helper.getNode("jn1"); | ||||
|             var jn2 = helper.getNode("jn2"); | ||||
|             jn2.on("input", function(msg) { | ||||
|                 msg.should.have.property('sentiment'); | ||||
|                 msg.sentiment.should.have.property('score'); | ||||
|                 msg.sentiment.score.should.be.a.Number(); | ||||
|                 msg.sentiment.score.should.be.below(-10); | ||||
|                 done(); | ||||
|             }); | ||||
|             var testString = 'bad, horrible, negative, awful'; | ||||
|             jn1.receive({payload:testString}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('should add a negative score for bad words - alternative property', function(done) { | ||||
|         var flow = [{id:"jn1",type:"sentiment",property:"foo",wires:[["jn2"]]}, | ||||
|                     {id:"jn2", type:"helper"}]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var jn1 = helper.getNode("jn1"); | ||||
|             var jn2 = helper.getNode("jn2"); | ||||
|             jn2.on("input", function(msg) { | ||||
|                 msg.should.have.property('sentiment'); | ||||
|                 msg.sentiment.should.have.property('score'); | ||||
|                 msg.sentiment.score.should.be.a.Number(); | ||||
|                 msg.sentiment.score.should.be.below(-10); | ||||
|                 done(); | ||||
|             }); | ||||
|             var testString = 'bad, horrible, negative, awful'; | ||||
|             jn1.receive({foo:testString}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('should allow you to override word scoring', function(done) { | ||||
|         var flow = [{id:"jn1",type:"sentiment",wires:[["jn2"]]}, | ||||
|                     {id:"jn2", type:"helper"}]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var jn1 = helper.getNode("jn1"); | ||||
|             var jn2 = helper.getNode("jn2"); | ||||
|             jn2.on("input", function(msg) { | ||||
|                 msg.should.have.property('sentiment'); | ||||
|                 msg.sentiment.should.have.property('score'); | ||||
|                 msg.sentiment.score.should.be.a.Number(); | ||||
|                 msg.sentiment.score.should.equal(20); | ||||
|                 done(); | ||||
|             }); | ||||
|             var testString = 'sick, wicked'; | ||||
|             var overrides = {'sick': 10, 'wicked': 10 }; | ||||
|             jn1.receive({payload:testString,overrides:overrides}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('should allow you to override word scoring - alternative property', function(done) { | ||||
|         var flow = [{id:"jn1",type:"sentiment",property:"foo",wires:[["jn2"]]}, | ||||
|                     {id:"jn2", type:"helper"}]; | ||||
|         helper.load(sentimentNode, flow, function() { | ||||
|             var jn1 = helper.getNode("jn1"); | ||||
|             var jn2 = helper.getNode("jn2"); | ||||
|             jn2.on("input", function(msg) { | ||||
|                 msg.should.have.property('sentiment'); | ||||
|                 msg.sentiment.should.have.property('score'); | ||||
|                 msg.sentiment.score.should.be.a.Number(); | ||||
|                 msg.sentiment.score.should.equal(20); | ||||
|                 done(); | ||||
|             }); | ||||
|             var testString = 'sick, wicked'; | ||||
|             var overrides = {'sick': 10, 'wicked': 10 }; | ||||
|             jn1.receive({foo:testString,overrides:overrides}); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
| }); | ||||
| @@ -52,30 +52,30 @@ describe('inject node', function() { | ||||
|     }); | ||||
|  | ||||
|     function basicTest(type, val, rval) { | ||||
| 	it('inject value ('+type+')', function (done) { | ||||
|         it('inject value ('+type+')', function (done) { | ||||
|             var flow = [{id: "n1", type: "inject", topic: "t1", payload: val, payloadType: type, wires: [["n2"]], z: "flow"}, | ||||
| 			{id: "n2", type: "helper"}]; | ||||
|             {id: "n2", type: "helper"}]; | ||||
|             helper.load(injectNode, flow, function () { | ||||
| 		var n1 = helper.getNode("n1"); | ||||
| 		var n2 = helper.getNode("n2"); | ||||
| 		n2.on("input", function (msg) { | ||||
|                 var n1 = helper.getNode("n1"); | ||||
|                 var n2 = helper.getNode("n2"); | ||||
|                 n2.on("input", function (msg) { | ||||
|                     try { | ||||
| 			msg.should.have.property("topic", "t1"); | ||||
| 			if (rval) { | ||||
| 			    msg.should.have.property("payload"); | ||||
| 			    should.deepEqual(msg.payload, rval); | ||||
| 			} | ||||
| 			else { | ||||
| 			    msg.should.have.property("payload", val); | ||||
| 			} | ||||
| 			done(); | ||||
|                         msg.should.have.property("topic", "t1"); | ||||
|                         if (rval) { | ||||
|                             msg.should.have.property("payload"); | ||||
|                             should.deepEqual(msg.payload, rval); | ||||
|                         } | ||||
|                         else { | ||||
|                             msg.should.have.property("payload", val); | ||||
|                         } | ||||
|                         done(); | ||||
|                     } catch (err) { | ||||
| 			done(err); | ||||
|                         done(err); | ||||
|                     } | ||||
| 		}); | ||||
| 		n1.receive({}); | ||||
|                 }); | ||||
|                 n1.receive({}); | ||||
|             }); | ||||
| 	}); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     basicTest("num", 10); | ||||
| @@ -503,16 +503,21 @@ describe('inject node', function() { | ||||
|                                      done(); | ||||
|                                  }); | ||||
|                              }); | ||||
|                              helper.request() | ||||
|                              try { | ||||
|                                  helper.request() | ||||
|                                  .post('/inject/n1') | ||||
|                                  .expect(200).end(function(err) { | ||||
|                                      if (err) { | ||||
|                                          console.log(err); | ||||
|                                          return helper.clearFlows() | ||||
|                                              .then(function () { | ||||
|                                                  done(err); | ||||
|                                              }); | ||||
|                                          .then(function () { | ||||
|                                              done(err); | ||||
|                                          }); | ||||
|                                      } | ||||
|                                  }); | ||||
|                              } catch(err) { | ||||
|                                  done(err); | ||||
|                              } | ||||
|                          }); | ||||
|         }); | ||||
|  | ||||
|   | ||||
| @@ -207,6 +207,12 @@ describe('HTTP Request Node', function() { | ||||
|             res.cookie('redirectToDifferentDomain','different1'); | ||||
|             res.redirect(getDifferentTestURL('/redirectReturn')); | ||||
|         }); | ||||
|         testApp.get('/redirectMultipleTimes', function(req, res) { | ||||
|             var key = req.headers.host + req.url; | ||||
|             receivedCookies[key] = req.cookies; | ||||
|             res.cookie('redirectMultipleTimes','multiple1'); | ||||
|             res.redirect(getTestURL('/redirectToDifferentDomain')); | ||||
|         }); | ||||
|         testApp.get('/redirectReturn', function(req, res) { | ||||
|             var key = req.headers.host + req.url; | ||||
|             receivedCookies[key] = req.cookies; | ||||
| @@ -277,6 +283,7 @@ describe('HTTP Request Node', function() { | ||||
|                         msg.should.have.property('headers'); | ||||
|                         msg.headers.should.have.property('content-length',''+('hello'.length)); | ||||
|                         msg.headers.should.have.property('content-type').which.startWith('text/html'); | ||||
|                         msg.redirectList.length.should.equal(0); | ||||
|                         done(); | ||||
|                     } catch(err) { | ||||
|                         done(err); | ||||
| @@ -1510,6 +1517,10 @@ describe('HTTP Request Node', function() { | ||||
|                         done(new Error('Invalid cookie(path:/rediectReurn)')); | ||||
|                        return; | ||||
|                     } | ||||
|                     var redirect1 = msg.redirectList[0]; | ||||
|                     redirect1.location.should.equal('http://localhost:'+testPort+'/redirectReturn'); | ||||
|                     redirect1.cookies.redirectToSameDomainCookie.Path.should.equal('/'); | ||||
|                     redirect1.cookies.redirectToSameDomainCookie.value.should.equal('same1'); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 n1.receive({}); | ||||
| @@ -1533,6 +1544,10 @@ describe('HTTP Request Node', function() { | ||||
|                         done(new Error('Invalid cookie(path:/rediectReurn)')); | ||||
|                         return; | ||||
|                     } | ||||
|                     var redirect1 = msg.redirectList[0]; | ||||
|                     redirect1.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn'); | ||||
|                     redirect1.cookies.redirectToDifferentDomain.Path.should.equal('/'); | ||||
|                     redirect1.cookies.redirectToDifferentDomain.value.should.equal('different1'); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 n1.receive({}); | ||||
| @@ -1559,6 +1574,10 @@ describe('HTTP Request Node', function() { | ||||
|                         done(new Error('Invalid cookie(path:/rediectReurn)')); | ||||
|                         return; | ||||
|                     } | ||||
|                     var redirect1 = msg.redirectList[0]; | ||||
|                     redirect1.location.should.equal('http://localhost:'+testPort+'/redirectReturn'); | ||||
|                     redirect1.cookies.redirectToSameDomainCookie.Path.should.equal('/'); | ||||
|                     redirect1.cookies.redirectToSameDomainCookie.value.should.equal('same1'); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 n1.receive({ | ||||
| @@ -1585,6 +1604,10 @@ describe('HTTP Request Node', function() { | ||||
|                         done(new Error('Invalid cookie(path:/rediectReurn)')); | ||||
|                         return; | ||||
|                     } | ||||
|                     var redirect1 = msg.redirectList[0]; | ||||
|                     redirect1.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn'); | ||||
|                     redirect1.cookies.redirectToDifferentDomain.Path.should.equal('/'); | ||||
|                     redirect1.cookies.redirectToDifferentDomain.value.should.equal('different1'); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 n1.receive({ | ||||
| @@ -1613,6 +1636,10 @@ describe('HTTP Request Node', function() { | ||||
|                         done(new Error('Invalid cookie(path:/rediectReurn)')); | ||||
|                         return; | ||||
|                     } | ||||
|                     var redirect1 = msg.redirectList[0]; | ||||
|                     redirect1.location.should.equal('http://localhost:'+testPort+'/redirectReturn'); | ||||
|                     redirect1.cookies.redirectToSameDomainCookie.Path.should.equal('/'); | ||||
|                     redirect1.cookies.redirectToSameDomainCookie.value.should.equal('same1'); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 n1.receive({ | ||||
| @@ -1639,6 +1666,33 @@ describe('HTTP Request Node', function() { | ||||
|                         done(new Error('Invalid cookie(path:/rediectReurn)')); | ||||
|                         return; | ||||
|                     } | ||||
|                     var redirect1 = msg.redirectList[0]; | ||||
|                     redirect1.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn'); | ||||
|                     redirect1.cookies.redirectToDifferentDomain.Path.should.equal('/'); | ||||
|                     redirect1.cookies.redirectToDifferentDomain.value.should.equal('different1'); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 n1.receive({ | ||||
|                     headers: { cookie: 'requestCookie=request1' } | ||||
|                 }); | ||||
|             }); | ||||
|         }); | ||||
|         it('should return all redirect information when redirected multiple times', function(done) { | ||||
|             var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectMultipleTimes')}, | ||||
|                 {id:"n2", type:"helper"}]; | ||||
|             receivedCookies = {}; | ||||
|             helper.load(httpRequestNode, flow, function() { | ||||
|                 var n1 = helper.getNode("n1"); | ||||
|                 var n2 = helper.getNode("n2"); | ||||
|                 n2.on("input", function(msg) { | ||||
|                     var redirect1 = msg.redirectList[0]; | ||||
|                     redirect1.location.should.equal('http://localhost:'+testPort+'/redirectToDifferentDomain'); | ||||
|                     redirect1.cookies.redirectMultipleTimes.Path.should.equal('/'); | ||||
|                     redirect1.cookies.redirectMultipleTimes.value.should.equal('multiple1'); | ||||
|                     var redirect2 = msg.redirectList[1]; | ||||
|                     redirect2.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn'); | ||||
|                     redirect2.cookies.redirectToDifferentDomain.Path.should.equal('/'); | ||||
|                     redirect2.cookies.redirectToDifferentDomain.value.should.equal('different1'); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 n1.receive({ | ||||
|   | ||||
| @@ -1,206 +0,0 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * 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. | ||||
|  **/ | ||||
|  | ||||
| var should = require("should"); | ||||
| var path = require('path'); | ||||
| var os = require('os'); | ||||
| var fs = require('fs-extra'); | ||||
| var sinon = require('sinon'); | ||||
| var tailNode = require("nr-test-utils").require("@node-red/nodes/core/storage/28-tail.js"); | ||||
| var helper = require("node-red-node-test-helper"); | ||||
|  | ||||
| describe('tail Node', function() { | ||||
|  | ||||
|     var wait = 150; | ||||
|     var resourcesDir = path.join(__dirname,"..","..","..","resources"); | ||||
|     var fileToTail = path.join(resourcesDir,"28-tail-test-file.txt"); | ||||
|  | ||||
|     beforeEach(function(done) { | ||||
|         fs.writeFileSync(fileToTail, "Tail message line 1\nTail message line 2\n"); | ||||
|         helper.startServer(done); | ||||
|     }); | ||||
|  | ||||
|     afterEach(function(done) { | ||||
|         helper.unload().then(function() { | ||||
|             fs.unlinkSync(fileToTail); | ||||
|             helper.stopServer(done); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     if (os.type() !== "Windows_NT") { | ||||
|         it('should be loaded', function(done) { | ||||
|             var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail}]; | ||||
|             helper.load(tailNode, flow, function() { | ||||
|                 var tailNode1 = helper.getNode("tailNode1"); | ||||
|                 tailNode1.should.have.property('name', 'tailNode'); | ||||
|                 done(); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should tail a file', function(done) { | ||||
|             var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail, "wires":[["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper", wires:[]}]; | ||||
|             helper.load(tailNode, flow, function() { | ||||
|                 var tailNode1 = helper.getNode("tailNode1"); | ||||
|                 var helperNode1 = helper.getNode("helperNode1"); | ||||
|                 var inputCounter = 0; | ||||
|                 helperNode1.on("input", function(msg) { | ||||
|                     //console.log(msg); | ||||
|                     msg.should.have.property('topic', fileToTail); | ||||
|                     msg.payload.should.equal("Tail message line " + (++inputCounter + 2)); | ||||
|                     if (inputCounter === 2) { | ||||
|                         done(); | ||||
|                     } | ||||
|                 }); | ||||
|                 setTimeout( function() { | ||||
|                     fs.appendFileSync(fileToTail, "Tail message line 3\n"); | ||||
|                     fs.appendFileSync(fileToTail, "Tail message line 4\n"); | ||||
|                 },wait); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should work in non-split mode', function(done) { | ||||
|             var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":false, "filename":fileToTail, "wires":[["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper", wires:[]}]; | ||||
|             helper.load(tailNode, flow, function() { | ||||
|                 var tailNode1 = helper.getNode("tailNode1"); | ||||
|                 var helperNode1 = helper.getNode("helperNode1"); | ||||
|                 helperNode1.on("input", function(msg) { | ||||
|                     //console.log(msg); | ||||
|                     msg.should.have.property('topic', fileToTail); | ||||
|                     msg.payload.should.equal("Tail message line 5\nTail message line 6\n"); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 setTimeout( function() { | ||||
|                     fs.appendFileSync(fileToTail, "Tail message line 5\nTail message line 6\n"); | ||||
|                 },wait); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should work in binary mode', function(done) { | ||||
|             var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "filetype":"binary", "filename":fileToTail, "wires":[["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper", wires:[]}]; | ||||
|             helper.load(tailNode, flow, function() { | ||||
|                 var tailNode1 = helper.getNode("tailNode1"); | ||||
|                 var helperNode1 = helper.getNode("helperNode1"); | ||||
|                 helperNode1.on("input", function(msg) { | ||||
|                     //console.log(msg); | ||||
|                     msg.should.have.property('topic', fileToTail); | ||||
|                     msg.payload.toString().should.equal("Tail message line 7\nTail message line 8\n"); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 setTimeout( function() { | ||||
|                     fs.appendFileSync(fileToTail, "Tail message line 7\nTail message line 8\n"); | ||||
|                 },wait); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should handle a non-existent file', function(done) { | ||||
|             fs.writeFileSync(fileToTail, "Tail message line.\n"); | ||||
|             var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail, "wires":[["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper", wires:[]}]; | ||||
|             helper.load(tailNode, flow, function() { | ||||
|                 var tailNode1 = helper.getNode("tailNode1"); | ||||
|                 var helperNode1 = helper.getNode("helperNode1"); | ||||
|                 helperNode1.on("input", function(msg) { | ||||
|                     msg.should.have.property('topic', fileToTail); | ||||
|                     msg.payload.should.equal("Tail message line"); | ||||
|                     done(); | ||||
|                 }); | ||||
|                 setTimeout(function() { | ||||
|                     fs.unlinkSync(fileToTail); | ||||
|                 },500); | ||||
|                 setTimeout( function() { | ||||
|                     fs.writeFile(fileToTail, "Tail message line\n"); | ||||
|                 },1000); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     it('should throw an error if run on Windows', function() { | ||||
|         // Stub os platform so we can make it look like windows | ||||
|         var os = require('os'); | ||||
|         var spy = sinon.stub(os, 'platform', function(arg) { return("windows"); }); | ||||
|  | ||||
|         /*jshint immed: false */ | ||||
|         try { | ||||
|             (function() { tailNode("1234"); }).should.throw(); | ||||
|         } catch (err) { | ||||
|             throw err; | ||||
|         } | ||||
|         finally { | ||||
|             os.platform.restore(); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     /* | ||||
|     it('tail should handle file truncation', function(done) { | ||||
|         var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail, "wires":[["helperNode1"]]}, | ||||
|                     {id:"helperNode1", type:"helper", wires:[]}]; | ||||
|         helper.load(tailNode, flow, function() { | ||||
|             var tailNode1 = helper.getNode("tailNode1"); | ||||
|             var helperNode1 = helper.getNode("helperNode1"); | ||||
|             var inputCounter = 0; | ||||
|             var warned = false; | ||||
|             tailNode1.on("log", function(msg) { | ||||
|                 if (msg.level == "warn") { warned = true; } | ||||
|             }); | ||||
|             helperNode1.on("input", function(msg) { | ||||
|                 console.log("inputCounter =",inputCounter); | ||||
|                 console.log(msg); | ||||
|                 msg.should.have.property('topic', fileToTail); | ||||
|                 inputCounter++; | ||||
|                 if (inputCounter === 1) { | ||||
|                     warned.should.be.false(); | ||||
|                     msg.payload.should.equal("Tail message line append"); | ||||
|                 } else if (inputCounter === 2) { | ||||
|                     msg.payload.should.equal("Tail message line truncate"); | ||||
|                 } else { | ||||
|                     msg.payload.should.equal("Tail message line append "+inputCounter); | ||||
|                 } | ||||
|  | ||||
|                 if (inputCounter === 5) { | ||||
|                     setTimeout(function() { | ||||
|                         warned.should.be.true(); | ||||
|                         done(); | ||||
|                     },100); | ||||
|                 } | ||||
|             }); | ||||
|             var actions = [ | ||||
|                 function() { fs.appendFileSync(fileToTail, "Tail message line append\n");}, | ||||
|                 function() { fs.writeFileSync(fileToTail, "Tail message line truncate\n");}, | ||||
|                 function() { fs.appendFileSync(fileToTail, "Tail message line append 3\n");}, | ||||
|                 function() { fs.appendFileSync(fileToTail, "Tail message line append 4\n");}, | ||||
|                 function() { fs.appendFileSync(fileToTail, "Tail message line append 5\n");} | ||||
|             ]; | ||||
|  | ||||
|             function processAction() { | ||||
|                 var action = actions.shift(); | ||||
|                 action(); | ||||
|                 if (actions.length > 0) { | ||||
|                     setTimeout(function() { | ||||
|                         processAction(); | ||||
|                     },250); | ||||
|                 } | ||||
|             } | ||||
|             setTimeout( function() { | ||||
|                 processAction(); | ||||
|             },wait); | ||||
|         }); | ||||
|     }); | ||||
|     */ | ||||
|  | ||||
| }); | ||||
| @@ -59,8 +59,8 @@ describe("api/index", function() { | ||||
|     afterEach(afterEach); | ||||
|  | ||||
|     it("does not setup admin api if httpAdminRoot is false", function(done) { | ||||
|         api.init({},{ httpAdminRoot: false },{},{}); | ||||
|         should.not.exist(api.adminApp); | ||||
|         api.init({ httpAdminRoot: false },{},{},{}); | ||||
|         should.not.exist(api.httpAdmin); | ||||
|         done(); | ||||
|     }); | ||||
|     describe('initalises admin api without adminAuth', function(done) { | ||||
| @@ -70,30 +70,30 @@ describe("api/index", function() { | ||||
|         }); | ||||
|         after(afterEach); | ||||
|         it('exposes the editor',function(done) { | ||||
|             request(api.adminApp).get("/editor").expect(200).end(done); | ||||
|             request(api.httpAdmin).get("/editor").expect(200).end(done); | ||||
|         }) | ||||
|         it('exposes the admin api',function(done) { | ||||
|             request(api.adminApp).get("/admin").expect(200).end(done); | ||||
|             request(api.httpAdmin).get("/admin").expect(200).end(done); | ||||
|         }) | ||||
|         it('exposes the auth api',function(done) { | ||||
|             request(api.adminApp).get("/auth/login").expect(200).end(done); | ||||
|             request(api.httpAdmin).get("/auth/login").expect(200).end(done); | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|     describe('initalises admin api without editor', function(done) { | ||||
|         before(function() { | ||||
|             beforeEach(); | ||||
|             api.init({},{ disableEditor: true },{},{}); | ||||
|             api.init({ disableEditor: true },{},{},{}); | ||||
|         }); | ||||
|         after(afterEach); | ||||
|         it('does not expose the editor',function(done) { | ||||
|             request(api.adminApp).get("/editor").expect(404).end(done); | ||||
|             request(api.httpAdmin).get("/editor").expect(404).end(done); | ||||
|         }) | ||||
|         it('exposes the admin api',function(done) { | ||||
|             request(api.adminApp).get("/admin").expect(200).end(done); | ||||
|             request(api.httpAdmin).get("/admin").expect(200).end(done); | ||||
|         }) | ||||
|         it('exposes the auth api',function(done) { | ||||
|             request(api.adminApp).get("/auth/login").expect(200).end(done) | ||||
|             request(api.httpAdmin).get("/auth/login").expect(200).end(done) | ||||
|         }) | ||||
|     }); | ||||
| }); | ||||
|   | ||||
							
								
								
									
										20
									
								
								test/unit/@node-red/registry/lib/util_spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								test/unit/@node-red/registry/lib/util_spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * 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. | ||||
|  **/ | ||||
|  | ||||
|  | ||||
| describe("red/nodes/registry/util",function() { | ||||
|     it.skip("NEEDS TESTS"); | ||||
| }); | ||||
| @@ -25,6 +25,8 @@ var runtime = NR_TEST_UTILS.require("@node-red/runtime"); | ||||
| var redNodes = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes"); | ||||
| var storage = NR_TEST_UTILS.require("@node-red/runtime/lib/storage"); | ||||
| 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; | ||||
|  | ||||
| describe("runtime", function() { | ||||
| @@ -41,6 +43,7 @@ describe("runtime", function() { | ||||
|         delete process.env.NODE_RED_HOME; | ||||
|     }); | ||||
|     function mockUtil(metrics) { | ||||
|  | ||||
|         return { | ||||
|             log:{ | ||||
|                 log: sinon.stub(), | ||||
| @@ -95,6 +98,7 @@ describe("runtime", function() { | ||||
|         var redNodesLoadFlows; | ||||
|         var redNodesStartFlows; | ||||
|         var redNodesLoadContextsPlugin; | ||||
|         var i18nRegisterMessageCatalog; | ||||
|  | ||||
|         beforeEach(function() { | ||||
|             storageInit = sinon.stub(storage,"init",function(settings) {return Promise.resolve();}); | ||||
| @@ -104,6 +108,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()}); | ||||
|         }); | ||||
|         afterEach(function() { | ||||
|             storageInit.restore(); | ||||
| @@ -114,6 +119,7 @@ describe("runtime", function() { | ||||
|             redNodesLoadFlows.restore(); | ||||
|             redNodesStartFlows.restore(); | ||||
|             redNodesLoadContextsPlugin.restore(); | ||||
|             i18nRegisterMessageCatalog.restore(); | ||||
|         }); | ||||
|         it("reports errored/missing modules",function(done) { | ||||
|             redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function(cb) { | ||||
| @@ -199,10 +205,14 @@ describe("runtime", function() { | ||||
|             var stopFlows = sinon.stub(redNodes,"stopFlows",function() { return Promise.resolve();} ); | ||||
|             redNodesGetNodeList = sinon.stub(redNodes,"getNodeList", function() {return []}); | ||||
|             var util = mockUtil(true); | ||||
|             runtime.init({testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return Promise.resolve();}},util); | ||||
|             sinon.stub(console,"log"); | ||||
|             runtime.init( | ||||
|                 {testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return Promise.resolve();}}, | ||||
|                 {}, | ||||
|                 undefined, | ||||
|                 util); | ||||
|             // sinon.stub(console,"log"); | ||||
|             runtime.start().then(function() { | ||||
|                 console.log.restore(); | ||||
|                 // console.log.restore(); | ||||
|                 setTimeout(function() { | ||||
|                     try { | ||||
|                         util.log.log.args.should.have.lengthOf(3); | ||||
|   | ||||
| @@ -31,31 +31,31 @@ var api = NR_TEST_UTILS.require("@node-red/runtime/lib/api"); | ||||
|  | ||||
| describe("red/red", function() { | ||||
|  | ||||
|     describe("check build", function() { | ||||
|         beforeEach(function() { | ||||
|             sinon.stub(runtime,"init",function() {}); | ||||
|             sinon.stub(api,"init",function() {}); | ||||
|             sinon.stub(RED,"version",function() { return "version";}); | ||||
|         }); | ||||
|         afterEach(function() { | ||||
|             runtime.init.restore(); | ||||
|             api.init.restore(); | ||||
|             fs.statSync.restore(); | ||||
|             RED.version.restore(); | ||||
|         }); | ||||
|         it.skip('warns if build has not been run',function() { | ||||
|             sinon.stub(fs,"statSync",function() { throw new Error();}); | ||||
|  | ||||
|             /*jshint immed: false */ | ||||
|             (function() { | ||||
|                 RED.init({},{}); | ||||
|             }).should.throw("Node-RED not built"); | ||||
|         }); | ||||
|         it('passed if build has been run',function() { | ||||
|             sinon.stub(fs,"statSync",function() { }); | ||||
|             RED.init({},{}); | ||||
|         }); | ||||
|     }); | ||||
|     // describe("check build", function() { | ||||
|     //     beforeEach(function() { | ||||
|     //         sinon.stub(runtime,"init",function() {}); | ||||
|     //         sinon.stub(api,"init",function() {}); | ||||
|     //         // sinon.stub(RED,"version",function() { return "version";}); | ||||
|     //     }); | ||||
|     //     afterEach(function() { | ||||
|     //         runtime.init.restore(); | ||||
|     //         api.init.restore(); | ||||
|     //         fs.statSync.restore(); | ||||
|     //         // RED.version.restore(); | ||||
|     //     }); | ||||
|     //     it.skip('warns if build has not been run',function() { | ||||
|     //         sinon.stub(fs,"statSync",function() { throw new Error();}); | ||||
|     // | ||||
|     //         /*jshint immed: false */ | ||||
|     //         (function() { | ||||
|     //             RED.init({},{}); | ||||
|     //         }).should.throw("Node-RED not built"); | ||||
|     //     }); | ||||
|     //     it('passed if build has been run',function() { | ||||
|     //         sinon.stub(fs,"statSync",function() { }); | ||||
|     //         RED.init({},{}); | ||||
|     //     }); | ||||
|     // }); | ||||
|  | ||||
|     describe("externals", function() { | ||||
|         it('reports version', function() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user