@gregoriusrippenstein/node-red-contrib-introspection 0.3.0 → 0.3.2

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
@@ -85,6 +85,14 @@ GetFlows supports version selection of the flows and it has limited authenticati
85
85
 
86
86
  Inspired by the [dsm](https://flows.nodered.org/node/node-red-contrib-dsm) package that has a [backup](https://github.com/cflurin/node-red-contrib-dsm/wiki/Backup) state machine.
87
87
 
88
+ ### SendFlow
89
+
90
+ 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.
91
+
92
+ ### TriggerImport
93
+
94
+ This node will open the Node-RED import dialog and insert the payload, i.e. a flow object, into the dialog. The flow can then be imported into the existing workspace. See the [RSS example](https://flowhub.org/f/e02ba6e534f7a0f4) for more details. Payload must be a valid flow object, i.e. a Javascript array with one object per node. The import dialog will complain should this not be the case.
95
+
88
96
  ## Node-RED Versions
89
97
 
90
98
  These nodes have been tested and found to work on Node-RED 3.0.2 and 3.1.0.beta.4.
@@ -97,6 +105,8 @@ There are [example flows](/examples) contained in the package, examples can also
97
105
  - [Sink and Seeker](https://flowhub.org/f/139a816449acd89f)
98
106
  - [Screenshot](https://flowhub.org/f/07b2d0f3b0445ab5)
99
107
  - [DrawSVG](https://flowhub.org/f/141037dcda5b69fd)
108
+ - [GetFlows](https://flowhub.org/f/0b1bfbf6e540be66)
109
+ - [TriggerImport](https://flowhub.org/f/e02ba6e534f7a0f4)
100
110
 
101
111
  ## License
102
112
 
@@ -0,0 +1,126 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('SendFlow',{
3
+ color: '#e5e4ef',
4
+ icon: "icons/subflow.svg",
5
+ category: 'introspection',
6
+ defaults: {
7
+ name: {
8
+ value:"",
9
+ },
10
+ hostUrl: {
11
+ value: ""
12
+ },
13
+ flowVersion: {
14
+ value: "v1"
15
+ },
16
+ useAuthentication: {
17
+ value:false
18
+ },
19
+ apiUsername: {
20
+ value: "",
21
+ },
22
+ apiUsernameType: {
23
+ value: "env",
24
+ },
25
+ apiPassword: {
26
+ value: "",
27
+ },
28
+ apiPasswordType: {
29
+ value: "env",
30
+ },
31
+ },
32
+ inputs:1,
33
+ outputs:1,
34
+
35
+ label: function() {
36
+ return (this.name || this._def.paletteLabel);
37
+ },
38
+
39
+ labelStyle: function() {
40
+ return this.name?"node_label_italic":"";
41
+ },
42
+ oneditprepare: function() {
43
+ $("#node-input-apiUsername").typedInput({
44
+ types:["env", "msg", "flow","global", "cred"],
45
+ typeField: "#node-input-apiUsernameType"
46
+ });
47
+
48
+ $("#node-input-apiPassword").typedInput({
49
+ types:["env", "msg", "flow","global", "env", "cred"],
50
+ typeField: "#node-input-apiPasswordType"
51
+ });
52
+
53
+ if ( $('#node-input-useAuthentication').is(":checked") ) {
54
+ $('#useAuthentication-input-fields').show();
55
+ } else {
56
+ $('#useAuthentication-input-fields').hide()
57
+ }
58
+
59
+ $('#node-input-useAuthentication').on( 'change', function() {
60
+ if ( $('#node-input-useAuthentication').is(":checked") ) {
61
+ $('#useAuthentication-input-fields').show();
62
+ } else {
63
+ $('#useAuthentication-input-fields').hide()
64
+ }
65
+ });
66
+ },
67
+ });
68
+ </script>
69
+
70
+ <script type="text/html" data-template-name="SendFlow">
71
+ <div class="form-row">
72
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
73
+ <input type="text" id="node-input-name" placeholder="Name">
74
+ </div>
75
+
76
+ <div class="form-row">
77
+ <label for="node-input-hostUrl"><i class="fa fa-tag"></i> Host</label>
78
+ <input type="text" id="node-input-hostUrl" placeholder="Host URL">
79
+ </div>
80
+
81
+ <div class="form-row">
82
+ <label for="node-input-flowVersion">
83
+ <i class="fa fa-tag"></i>
84
+ <span>Flow Version</span>
85
+ </label>
86
+
87
+ <select id="node-input-flowVersion">
88
+ <option value="v1" selected=selected>Version 1</option>
89
+ <option value="v2">Version 2</option>
90
+ </select>
91
+ </div>
92
+
93
+ <div class="form-row">
94
+ <label for="node-input-useAuthentication">
95
+ <i class="fa "></i>
96
+ <span>Use Authentication?</span>
97
+ </label>
98
+
99
+ <input type="checkbox" id="node-input-useAuthentication"
100
+ style="display:inline-block; width:15px; vertical-align:baseline;">
101
+ </div>
102
+
103
+ <div id="useAuthentication-input-fields" class="hidden">
104
+ <div class="form-row">
105
+ <label for="node-input-apiUsername">
106
+ <i class="fa fa-tag"></i>
107
+ Username
108
+ </label>
109
+ <input type="text" id="node-input-apiUsername">
110
+ <input type="hidden" id="node-input-apiUsernameType">
111
+ </div>
112
+
113
+ <div class="form-row">
114
+ <label for="node-input-apiPassword">
115
+ <i class="fa fa-tag"></i>
116
+ Password
117
+ </label>
118
+ <input type="text" id="node-input-apiPassword">
119
+ <input type="hidden" id="node-input-apiPasswordType">
120
+ </div>
121
+ </div>
122
+ </script>
123
+
124
+ <script type="text/html" data-help-name="SendFlow">
125
+ <p>Send flow to another Node-RED instance.</p>
126
+ </script>
@@ -0,0 +1,112 @@
1
+ module.exports = function(RED) {
2
+ function SendFlowFunctionality(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
+ var sendFlow = (hdrs, got) => {
14
+ got.post( cfg.hostUrl + "/flows", {
15
+ headers: {
16
+ "Node-RED-API-Version": cfg.flowVersion,
17
+ "Content-type": "application/json",
18
+ "Node-RED-Deployment-Type": "full",
19
+ ...hdrs
20
+ },
21
+ body: JSON.stringify(msg.payload)
22
+ }).then( res => {
23
+ var bodySize = res.body.length;
24
+
25
+ send({
26
+ ...msg,
27
+ payload: res.body
28
+ });
29
+
30
+ node.status({fill:"green",shape:"dot",text:"Good"});
31
+ setTimeout( function() {
32
+ node.status({})
33
+ }, 450);
34
+
35
+ }).catch( err => {
36
+ node.status({fill:"red",shape:"dot",text:"Failed"});
37
+ node.error(err)
38
+ });
39
+ };
40
+
41
+ /**
42
+ * Authentication
43
+ **/
44
+ if ( cfg.useAuthentication ) {
45
+ var username = undefined;
46
+ var password = undefined;
47
+
48
+ node.status({fill:"blue",shape:"dot",text:"Requesting token"});
49
+
50
+ RED.util.evaluateNodeProperty(cfg.apiUsername, cfg.apiUsernameType,
51
+ node, msg, (err, result) => {
52
+ if (err) {
53
+ node.status({fill:"red",shape:"dot",text:"Failed"});
54
+ node.error(err)
55
+ } else {
56
+ username = result;
57
+
58
+ RED.util.evaluateNodeProperty(cfg.apiPassword, cfg.apiPasswordType,
59
+ node, msg, (err, result) => {
60
+ if (err) {
61
+ node.status({fill:"red",shape:"dot",text:"Failed"});
62
+ node.error(err)
63
+ } else {
64
+ password = result;
65
+
66
+ var data = {
67
+ "client_id": "node-red-admin",
68
+ "grant_type": "password",
69
+ "scope": "*",
70
+ "username": username,
71
+ "password": password
72
+ }
73
+
74
+ import('got').then( (module) => {
75
+ module.got.post( cfg.hostUrl + "/auth/token", {
76
+ json: data
77
+ }).then( res => {
78
+ node.status({
79
+ fill:"blue",
80
+ shape:"dot",
81
+ text:"Sending flow"
82
+ });
83
+
84
+ var access_token = JSON.parse(res.body).access_token;
85
+
86
+ sendFlow({
87
+ "Authorization": "Bearer " + access_token
88
+ }, module.got);
89
+
90
+ }).catch((err) => {
91
+ node.status({fill:"red",shape:"dot",text:"Failed"});
92
+ node.error( err );
93
+ });
94
+ });
95
+ }
96
+ })
97
+ }
98
+ })
99
+ } else {
100
+ /*
101
+ * Authentication free zone...
102
+ */
103
+ node.status({fill:"blue",shape:"dot",text:"Sending flow"});
104
+ import('got').then( (module) => {
105
+ sendFlow({}, module.got);
106
+ });
107
+ }
108
+ });
109
+ }
110
+
111
+ RED.nodes.registerType("SendFlow", SendFlowFunctionality);
112
+ }
@@ -0,0 +1,48 @@
1
+ <script type="text/javascript">
2
+ RED.comms.subscribe('introspect:trigger-import-tripped', (event,data) => {
3
+ if ( data.msg == "import-flow" ) {
4
+ RED.clipboard.import();
5
+
6
+ setTimeout( () => {
7
+ var content = data.flowContent;
8
+
9
+ $('#red-ui-clipboard-dialog-import-text').val(
10
+ JSON.stringify(content)
11
+ ).trigger("paste");
12
+ }, 300);
13
+ }
14
+ });
15
+
16
+ RED.nodes.registerType('TriggerImport',{
17
+ color: '#e5e4ef',
18
+ icon: "icons/subflow.svg",
19
+ category: 'introspection',
20
+ paletteLabel: "TriggerImport",
21
+ defaults: {
22
+ name: {
23
+ value:"",
24
+ },
25
+ },
26
+ inputs:1,
27
+ outputs:1,
28
+
29
+ label: function() {
30
+ return (this.name || this._def.paletteLabel);
31
+ },
32
+
33
+ labelStyle: function() {
34
+ return this.name?"node_label_italic":"";
35
+ },
36
+ });
37
+ </script>
38
+
39
+ <script type="text/html" data-template-name="TriggerImport">
40
+ <div class="form-row">
41
+ <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name">Name</span></label>
42
+ <input type="text" id="node-input-name" placeholder="Name">
43
+ </div>
44
+ </script>
45
+
46
+ <script type="text/html" data-help-name="TriggerImport">
47
+ <p>Trigger import opens the flow import dialog with data that came from the server.</p>
48
+ </script>
@@ -0,0 +1,24 @@
1
+ module.exports = function(RED) {
2
+ function TriggerImportFunctionality(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
+ RED.comms.publish("introspect:trigger-import-tripped",
14
+ RED.util.encodeObject({
15
+ flowContent: msg.payload,
16
+ msg: "import-flow",
17
+ })
18
+ );
19
+
20
+ send(msg);
21
+ });
22
+ }
23
+ RED.nodes.registerType("TriggerImport", TriggerImportFunctionality);
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gregoriusrippenstein/node-red-contrib-introspection",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "dependencies": {
5
5
  "got": "latest"
6
6
  },
@@ -16,14 +16,16 @@
16
16
  "node-red": {
17
17
  "version": ">=2.0.0",
18
18
  "nodes": {
19
- "seeker": "nodes/05-seeker.js",
20
- "sink": "nodes/10-sink.js",
21
- "screenshot": "nodes/15-screenshot.js",
22
- "orphans": "nodes/20-orphans.js",
23
- "ismobile": "nodes/25-ismobile.js",
24
- "navigator": "nodes/30-navigator.js",
25
- "drawsvg": "nodes/40-drawsvg.js",
26
- "getflows": "nodes/45-get-flows.js"
19
+ "seeker": "nodes/05-seeker.js",
20
+ "sink": "nodes/10-sink.js",
21
+ "screenshot": "nodes/15-screenshot.js",
22
+ "orphans": "nodes/20-orphans.js",
23
+ "ismobile": "nodes/25-ismobile.js",
24
+ "navigator": "nodes/30-navigator.js",
25
+ "drawsvg": "nodes/40-drawsvg.js",
26
+ "getflows": "nodes/45-get-flows.js",
27
+ "sendflow": "nodes/50-send-flow.js",
28
+ "triggerimport": "nodes/55-trigger-import.js"
27
29
  }
28
30
  },
29
31
  "description": "Node-RED Editor-only nodes for introspecting flows.",