@gregoriusrippenstein/node-red-contrib-introspection 0.6.17 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -99,6 +99,12 @@ Inspired by the [dsm](https://flows.nodered.org/node/node-red-contrib-dsm) packa
99
99
 
100
100
  Send a flow to another Node-RED instance. This will replace **any existing** flows on the other server, use with care. Under the hood this uses the [Node-RED API](https://nodered.org/docs/api/admin/methods/post/flows/) to post a new flow to the server. This node also supports authentication if the other server happens to have some.
101
101
 
102
+ ### InstallPackage
103
+
104
+ Node used to install packages on other Node-RED installations. Can be used to install existing modules using or .tgz files that can installed on the instance. To install an existing package, use `msg.payload = { module: '@fubar/example' }` with an optional `version`, this defaults to 'latest'.
105
+
106
+ To install a package on the fly, generate a .tgz as a Buffer and set the the payload to: `msg.payload = { data: Buffer[...]}` where buffer contains the .tgz contents.
107
+
102
108
  ### ClientCode
103
109
 
104
110
  ClientCode is a node for executing client side, i.e., in the editor, Javascript code triggered by a server side event. Any code that can be executed in the browseer console can be executed in the ClientCode node. A ClientCode node can also send a message back to the server using `node.send(...)` which becomes the server side output of the node.
@@ -165,6 +171,7 @@ There are [example flows](/examples) contained in the package, examples can also
165
171
  - [Orphans](https://flowhub.org/f/2401c255b056e0e1)
166
172
  - [Sink and Seeker](https://flowhub.org/f/139a816449acd89f)
167
173
  - [Obfuscation](https://flowhub.org/f/825ddf24d98eb011)
174
+ - [InstallPackage](https://flowhub.org/f/6dcbd2643ea80615)
168
175
 
169
176
  ## License
170
177
 
@@ -42,7 +42,7 @@ module.exports = function(RED) {
42
42
 
43
43
  }).catch( err => {
44
44
  node.status({fill:"red",shape:"dot",text:"Failed"});
45
- node.error(err)
45
+ node.error("error occurred", { ...msg, _err: err})
46
46
  });
47
47
  };
48
48
 
@@ -56,7 +56,7 @@ module.exports = function(RED) {
56
56
  node, msg, (err, result) => {
57
57
  if (err) {
58
58
  node.status({fill:"red",shape:"dot",text:"Failed"});
59
- node.error(err)
59
+ node.error("error occurred", {...msg, _err:err})
60
60
  } else {
61
61
  username = result;
62
62
 
@@ -64,7 +64,7 @@ module.exports = function(RED) {
64
64
  node, msg, (err, result) => {
65
65
  if (err) {
66
66
  node.status({fill:"red",shape:"dot",text:"Failed"});
67
- node.error(err)
67
+ node.error("error occurred", { ...msg, _err: err })
68
68
  } else {
69
69
  password = result;
70
70
 
@@ -94,7 +94,7 @@ module.exports = function(RED) {
94
94
 
95
95
  }).catch((err) => {
96
96
  node.status({fill:"red",shape:"dot",text:"Failed"});
97
- node.error( err );
97
+ node.error( "error occurred", {...msg, _err: err });
98
98
  });
99
99
  });
100
100
  }
@@ -34,7 +34,7 @@ module.exports = function(RED) {
34
34
 
35
35
  }).catch( err => {
36
36
  node.status({fill:"red",shape:"dot",text:"Failed"});
37
- node.error(err)
37
+ node.error("error occurred", { ...msg, _err: err})
38
38
  });
39
39
  };
40
40
 
@@ -51,7 +51,7 @@ module.exports = function(RED) {
51
51
  node, msg, (err, result) => {
52
52
  if (err) {
53
53
  node.status({fill:"red",shape:"dot",text:"Failed"});
54
- node.error(err)
54
+ node.error("error occurred", { ...msg, _err: err})
55
55
  } else {
56
56
  username = result;
57
57
 
@@ -59,7 +59,7 @@ module.exports = function(RED) {
59
59
  node, msg, (err, result) => {
60
60
  if (err) {
61
61
  node.status({fill:"red",shape:"dot",text:"Failed"});
62
- node.error(err)
62
+ node.error("error occurred", {...msg, _err: err})
63
63
  } else {
64
64
  password = result;
65
65
 
@@ -89,7 +89,7 @@ module.exports = function(RED) {
89
89
 
90
90
  }).catch((err) => {
91
91
  node.status({fill:"red",shape:"dot",text:"Failed"});
92
- node.error( err );
92
+ node.error( "error occurred", { ...msg, _err: err });
93
93
  });
94
94
  });
95
95
  }
@@ -0,0 +1,111 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('InstallPackage',{
3
+ color: '#e5e4ef',
4
+ icon: "introspesubflow.svg",
5
+ category: 'introspection',
6
+ defaults: {
7
+ name: {
8
+ value:"",
9
+ },
10
+ hostUrl: {
11
+ value: ""
12
+ },
13
+ useAuthentication: {
14
+ value:false
15
+ },
16
+ apiUsername: {
17
+ value: "",
18
+ },
19
+ apiUsernameType: {
20
+ value: "env",
21
+ },
22
+ apiPassword: {
23
+ value: "",
24
+ },
25
+ apiPasswordType: {
26
+ value: "env",
27
+ },
28
+ },
29
+ inputs:1,
30
+ outputs:1,
31
+
32
+ label: function() {
33
+ return (this.name || this._def.paletteLabel);
34
+ },
35
+
36
+ labelStyle: function() {
37
+ return this.name?"node_label_italic":"";
38
+ },
39
+ oneditprepare: function() {
40
+ $("#node-input-apiUsername").typedInput({
41
+ types:["env", "msg", "flow","global", "cred"],
42
+ typeField: "#node-input-apiUsernameType"
43
+ });
44
+
45
+ $("#node-input-apiPassword").typedInput({
46
+ types:["env", "msg", "flow","global", "env", "cred"],
47
+ typeField: "#node-input-apiPasswordType"
48
+ });
49
+
50
+ if ( $('#node-input-useAuthentication').is(":checked") ) {
51
+ $('#useAuthentication-input-fields').show();
52
+ } else {
53
+ $('#useAuthentication-input-fields').hide()
54
+ }
55
+
56
+ $('#node-input-useAuthentication').on( 'change', function() {
57
+ if ( $('#node-input-useAuthentication').is(":checked") ) {
58
+ $('#useAuthentication-input-fields').show();
59
+ } else {
60
+ $('#useAuthentication-input-fields').hide()
61
+ }
62
+ });
63
+ },
64
+ });
65
+ </script>
66
+
67
+ <script type="text/html" data-template-name="InstallPackage">
68
+ <div class="form-row">
69
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
70
+ <input type="text" id="node-input-name" placeholder="Name">
71
+ </div>
72
+
73
+ <div class="form-row">
74
+ <label for="node-input-hostUrl"><i class="fa fa-tag"></i> Host</label>
75
+ <input type="text" id="node-input-hostUrl" placeholder="Host URL">
76
+ </div>
77
+
78
+ <div class="form-row">
79
+ <label for="node-input-useAuthentication">
80
+ <i class="fa "></i>
81
+ <span>Use Authentication?</span>
82
+ </label>
83
+
84
+ <input type="checkbox" id="node-input-useAuthentication"
85
+ style="display:inline-block; width:15px; vertical-align:baseline;">
86
+ </div>
87
+
88
+ <div id="useAuthentication-input-fields" class="hidden">
89
+ <div class="form-row">
90
+ <label for="node-input-apiUsername">
91
+ <i class="fa fa-tag"></i>
92
+ Username
93
+ </label>
94
+ <input type="text" id="node-input-apiUsername">
95
+ <input type="hidden" id="node-input-apiUsernameType">
96
+ </div>
97
+
98
+ <div class="form-row">
99
+ <label for="node-input-apiPassword">
100
+ <i class="fa fa-tag"></i>
101
+ Password
102
+ </label>
103
+ <input type="text" id="node-input-apiPassword">
104
+ <input type="hidden" id="node-input-apiPasswordType">
105
+ </div>
106
+ </div>
107
+ </script>
108
+
109
+ <script type="text/html" data-help-name="InstallPackage">
110
+ <p>Send flow to another Node-RED instance.</p>
111
+ </script>
@@ -0,0 +1,137 @@
1
+ module.exports = function(RED) {
2
+ function InstallPackageFunctionality(config) {
3
+ RED.nodes.createNode(this,config);
4
+
5
+ var node = this;
6
+ var cfg = config;
7
+
8
+ node.on('close', function() {
9
+ node.status({});
10
+ });
11
+
12
+ node.on("input", function(msg, send, done) {
13
+
14
+ if (!msg.payload || Object.prototype.toString.call(msg.payload) !== '[object Object]') {
15
+ return node.error("msg.payload missing or payload not hash", msg)
16
+ }
17
+
18
+ var installPackage = (hdrs, got) => {
19
+ let body = undefined
20
+ let headers = {}
21
+
22
+ if ( msg.payload.module ) {
23
+ body = JSON.stringify({
24
+ module: msg.payload.module,
25
+ version: msg.payload.version || "latest"
26
+ })
27
+
28
+ headers = {
29
+ "Content-Type": "application/json"
30
+ }
31
+ } else if ( msg.payload.data && Buffer.isBuffer(msg.payload.data) ) {
32
+
33
+ let formData = require('form-data')
34
+ body = new formData();
35
+ body.append("tarball", msg.payload.data, "tarball.tgz");
36
+ headers = body.getHeaders()
37
+ body = body.getBuffer()
38
+
39
+ } else {
40
+ return node.error("msg.payload not well defined", msg)
41
+ }
42
+
43
+ got.post( cfg.hostUrl + "/nodes", {
44
+ headers: {
45
+ ...headers,
46
+ ...hdrs
47
+ },
48
+ body: body
49
+ }).then( res => {
50
+ send({
51
+ ...msg,
52
+ payload: JSON.parse(res.body)
53
+ });
54
+
55
+ node.status({fill:"green",shape:"dot",text:"Good"});
56
+ setTimeout( function() {
57
+ node.status({})
58
+ }, 450);
59
+
60
+ }).catch( err => {
61
+ node.status({fill:"red",shape:"dot",text:"Failed"});
62
+ node.error("error occurred", { ...msg, _err: err })
63
+ });
64
+ };
65
+
66
+ /**
67
+ * Authentication
68
+ **/
69
+ if ( cfg.useAuthentication ) {
70
+ var username = undefined;
71
+ var password = undefined;
72
+
73
+ node.status({fill:"blue",shape:"dot",text:"Requesting token"});
74
+
75
+ RED.util.evaluateNodeProperty(cfg.apiUsername, cfg.apiUsernameType,
76
+ node, msg, (err, result) => {
77
+ if (err) {
78
+ node.status({fill:"red",shape:"dot",text:"Failed"});
79
+ node.error("error occurred", { ...msg, _err: err})
80
+ } else {
81
+ username = result;
82
+
83
+ RED.util.evaluateNodeProperty(cfg.apiPassword, cfg.apiPasswordType,
84
+ node, msg, (err, result) => {
85
+ if (err) {
86
+ node.status({fill:"red",shape:"dot",text:"Failed"});
87
+ node.error("error occurred", { ...msg, _err: err} )
88
+ } else {
89
+ password = result;
90
+
91
+ var data = {
92
+ "client_id": "node-red-admin",
93
+ "grant_type": "password",
94
+ "scope": "*",
95
+ "username": username,
96
+ "password": password
97
+ }
98
+
99
+ import('got').then( (module) => {
100
+ module.got.post( cfg.hostUrl + "/auth/token", {
101
+ json: data
102
+ }).then( res => {
103
+ node.status({
104
+ fill:"blue",
105
+ shape:"dot",
106
+ text:"Sending flow"
107
+ });
108
+
109
+ var access_token = JSON.parse(res.body).access_token;
110
+
111
+ installPackage({
112
+ "Authorization": "Bearer " + access_token
113
+ }, module.got);
114
+
115
+ }).catch((err) => {
116
+ node.status({fill:"red",shape:"dot",text:"Failed"});
117
+ node.error( "error occured", { ...msg, _err: err } );
118
+ });
119
+ });
120
+ }
121
+ })
122
+ }
123
+ })
124
+ } else {
125
+ /*
126
+ * Authentication free zone...
127
+ */
128
+ node.status({fill:"blue",shape:"dot",text:"Sending flow"});
129
+ import('got').then( (module) => {
130
+ installPackage({}, module.got);
131
+ });
132
+ }
133
+ });
134
+ }
135
+
136
+ RED.nodes.registerType("InstallPackage", InstallPackageFunctionality);
137
+ }
@@ -42,8 +42,6 @@ module.exports = function(RED) {
42
42
  }
43
43
  } catch(err) {
44
44
  res.sendStatus(500);
45
- node.error("ClientCode: Submission failed: " +
46
- err.toString())
47
45
  }
48
46
  } else {
49
47
  res.sendStatus(404);
@@ -64,8 +62,6 @@ module.exports = function(RED) {
64
62
  }
65
63
  } catch (err) {
66
64
  res.sendStatus(500);
67
- node.error("ClientCode: Submission failed: " +
68
- err.toString())
69
65
  }
70
66
  } else {
71
67
  res.sendStatus(404);
@@ -135,8 +131,6 @@ module.exports = function(RED) {
135
131
  }
136
132
  } catch (err) {
137
133
  res.sendStatus(500);
138
- node.error("ClientCode: Submission failed: " +
139
- err.toString())
140
134
  }
141
135
  });
142
136
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gregoriusrippenstein/node-red-contrib-introspection",
3
- "version": "0.6.17",
3
+ "version": "0.7.1",
4
4
  "dependencies": {
5
5
  "got": "^13",
6
6
  "uglify-js": "^3.17.4",
@@ -28,11 +28,12 @@
28
28
  "screenshot": "plugins/sidebar.html"
29
29
  },
30
30
  "nodes": {
31
- "seeker": "nodes/05-seeker.js",
32
- "sink": "nodes/10-sink.js",
33
- "getflows": "nodes/45-get-flows.js",
34
- "sendflow": "nodes/50-send-flow.js",
35
- "clientcode": "nodes/60-client-code.js"
31
+ "seeker": "nodes/05-seeker.js",
32
+ "sink": "nodes/10-sink.js",
33
+ "getflows": "nodes/45-get-flows.js",
34
+ "sendflow": "nodes/50-send-flow.js",
35
+ "installpackage": "nodes/51-install-package.js",
36
+ "clientcode": "nodes/60-client-code.js"
36
37
  }
37
38
  },
38
39