@gregoriusrippenstein/node-red-contrib-introspection 0.4.0 → 0.4.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
@@ -91,14 +91,15 @@ Send a flow to another Node-RED instance. This will replace **any existing** flo
91
91
 
92
92
  ### ClientCode
93
93
 
94
- 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. It replaces the TriggerImport node by being more generic, TriggerImport executed very specific code for a server side event, ClientCode can emulate that behaviour.
94
+ 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.
95
95
 
96
- The context for code execution includes the following:
96
+ The context in which the code is exected includes:
97
97
 
98
98
  - `payload` which is the the `msg.payload` value
99
99
  - `topic` which is the `msg.topic` value
100
+ - `node.send(payload)` where `payload` becomes the output the node on the server side
101
+ - `node.error("msg")` where msg is shown as a notification within the editor
100
102
 
101
- For more details, [client side code](https://github.com/gorenje/node-red-contrib-introspection/blob/2f5aca9374b28fcb6890c312f943f913ecb4cfce/nodes/60-client-code.html#L3-L8) with the context and [server side code](https://github.com/gorenje/node-red-contrib-introspection/blob/2f5aca9374b28fcb6890c312f943f913ecb4cfce/nodes/60-client-code.js#L13-L22).
102
103
 
103
104
  ## Node-RED Versions
104
105
 
@@ -2,7 +2,60 @@
2
2
 
3
3
  RED.comms.subscribe('introspect:client-code-perform', (event,data) => {
4
4
  if ( data.msg == "execfunc" ) {
5
+
6
+ var doSend = (data, nodeid, _msg) => {
7
+ if ( typeof data == "object" ) {
8
+ data = {
9
+ ..._msg,
10
+ ...data
11
+ };
12
+ }
13
+
14
+ $.ajax({
15
+ url: "ClientCode/" + nodeid,
16
+ type: "POST",
17
+ contentType: "application/json; charset=utf-8",
18
+ data: JSON.stringify(data),
19
+
20
+ success: function (resp) {
21
+ },
22
+
23
+ error: function (jqXHR, textStatus, errorThrown) {
24
+ RED.notify("ClientCode Communcation Failure: " +
25
+ nodeid + ": " + textStatus, {
26
+ type: "error",
27
+ id: nodeid,
28
+ timeout: 3000
29
+ });
30
+ }
31
+ });
32
+ };
33
+
34
+ var doError = (msg, nodeid, _msg) => {
35
+ RED.notify("ClientCode Failed: " + nodeid + ": " + msg, {
36
+ type: "error",
37
+ id: nodeid,
38
+ timeout: 3000
39
+ });
40
+
41
+ console.log( "ClientCode: Error with node: " + nodeid + ": " + msg);
42
+ };
43
+
44
+ var nodeid = data.nodeid;
45
+ var _msg = data._msg;
46
+
47
+ var node = {
48
+ send: (dt) => {
49
+ doSend(dt, nodeid, _msg)
50
+ },
51
+ error: (mg) => {
52
+ doError(mg, nodeid, _msg)
53
+ }
54
+ };
55
+
5
56
  var payload = data.payload;
57
+ var topic = data.topic;
58
+
6
59
  eval( data.func );
7
60
  }
8
61
  });
@@ -20,7 +73,7 @@
20
73
  value: ""
21
74
  },
22
75
  format: {
23
- value: ""
76
+ value: "javascript"
24
77
  }
25
78
  },
26
79
  inputs:1,
@@ -51,13 +104,11 @@
51
104
 
52
105
  this.editor = RED.editor.createEditor({
53
106
  id: 'node-input-clientcode-editor',
54
- mode: 'ace/mode/html',
107
+ mode: 'ace/mode/javascript',
55
108
  stateId: stateId,
56
- value: $("#node-input-screenshot").val()
109
+ value: $("#node-input-clientcode").val()
57
110
  });
58
111
 
59
- this.editor.setValue( that.clientcode );
60
-
61
112
  $("#node-input-format").on("change", function() {
62
113
  var mod = "ace/mode/"+$("#node-input-format").val();
63
114
  that.editor.getSession().setMode({
@@ -17,12 +17,34 @@ module.exports = function(RED) {
17
17
  payload: msg.payload,
18
18
  topic: msg.topic,
19
19
  func: cfg.clientcode,
20
- nodeid: node.id
20
+ nodeid: node.id,
21
+ _msg: msg
21
22
  })
22
23
  );
23
-
24
- send(msg);
25
24
  });
26
25
  }
27
26
  RED.nodes.registerType("ClientCode", ClientCodeFunctionality);
27
+
28
+ RED.httpAdmin.post("/ClientCode/:id",
29
+ RED.auth.needsPermission("ClientCode.write"),
30
+ (req,res) => {
31
+ var node = RED.nodes.getNode(req.params.id);
32
+ if (node != null) {
33
+ try {
34
+ if (req.body && node.type == "ClientCode" ) {
35
+ node.send(req.body);
36
+ res.sendStatus(200);
37
+ } else {
38
+ res.sendStatus(404);
39
+ }
40
+ } catch(err) {
41
+ res.sendStatus(500);
42
+ node.error("ClientCode: Submission failed: " +
43
+ err.toString())
44
+ }
45
+ } else {
46
+ res.sendStatus(404);
47
+ }
48
+ });
49
+
28
50
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gregoriusrippenstein/node-red-contrib-introspection",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "dependencies": {
5
5
  "got": "latest"
6
6
  },
@@ -1,158 +0,0 @@
1
- <script type="text/javascript">
2
-
3
- /*
4
- * How to connect nodes:
5
- var namesToId = {}
6
-
7
- RED.nodes.eachNode((n) => {
8
- if ( n._def.category == "rssfeeds") {
9
- namesToId[n.name] = n.id
10
- }
11
- })
12
-
13
- RED.nodes.eachNode((n) => {
14
- if ( n._def.category == "rssfeeds" && n._def.label() == "Hacker News: New Comments") {
15
- var title = n.name.match(/^New[ ]+comment[ ]+by.+\"(.*)\"/)[1];
16
- var tgtId = namesToId[title];
17
- if ( tgtId ) {
18
- var t = RED.nodes.node(tgtId);
19
- RED.nodes.addLink( { source: n, sourcePort: 0, target: t});
20
- RED.view.select([t,n])
21
- }
22
- }
23
- })
24
-
25
- * How to move
26
-
27
- var t = RED.nodes.node("23e18922a0b896f1")
28
- t.x = XXXX;
29
- t.y = YYYY;
30
- t.dirty = true;
31
- RED.view.redraw(true)
32
-
33
- */
34
-
35
- RED.comms.subscribe('introspect:trigger-import-delete', (event,data) => {
36
- if ( data.msg == "delete-old-nodes" ) {
37
- RED.view.select(false)
38
-
39
- // close any dialog that explains that there are duplicates and therefore
40
- // only a copy can be imported, hit the cancel button on that one.
41
- // Five clicks should do the job ...
42
- for ( var idx = 0 ; idx < 5; idx++ ) {
43
- $($('.ui-dialog-buttonset').find("button")[0]).trigger('click')
44
- }
45
-
46
- var allSelectNodes = [];
47
-
48
- RED.nodes.eachNode( function(e) {
49
- if ( e._def && e.env && e.env[1] &&
50
- e._def.category == data.payload.category &&
51
- (Date.parse(e.env[1].value) <
52
- (new Date().getTime() - parseInt(data.payload.old_than_ms))) ) {
53
- allSelectNodes.push(e)
54
- }
55
- });
56
-
57
- RED.view.select({ nodes: allSelectNodes })
58
- setTimeout( () => {
59
- RED.actions.invoke("core:delete-selection")
60
- }, 1500);
61
- }
62
- });
63
-
64
- RED.comms.subscribe('introspect:trigger-import-tripped', (event,data) => {
65
- if ( data.msg == "import-flow" ) {
66
- var content = data.flowContent;
67
-
68
- if ( data.removeduplicates ) {
69
- content = content.filter( (elem) => {
70
- return RED.nodes.node(elem.id) == undefined
71
- });
72
- }
73
-
74
- if ( content.length == 0 ) {
75
- RED.notify("No new content", {
76
- type: "ok",
77
- id: "TriggerImport",
78
- timeout: 2000
79
- });
80
- return;
81
- }
82
- RED.clipboard.import();
83
-
84
- setTimeout( () => {
85
- $('#red-ui-clipboard-dialog-import-text').val(
86
- JSON.stringify(content)
87
- ).trigger("paste");
88
-
89
- if ( data.autoimport ) {
90
- setTimeout( () => {
91
- $('#red-ui-clipboard-dialog-ok').trigger('click');
92
- }, 435);
93
- }
94
- }, 300);
95
- }
96
- });
97
-
98
- RED.nodes.registerType('TriggerImport',{
99
- color: '#e5e4ef',
100
- icon: "icons/subflow.svg",
101
- category: 'introspection',
102
- paletteLabel: "TriggerImport",
103
- defaults: {
104
- name: {
105
- value:"",
106
- },
107
- autoimport: {
108
- value: false
109
- },
110
- removeduplicates: {
111
- value: false
112
- },
113
- },
114
- inputs:1,
115
- outputs:1,
116
-
117
- label: function() {
118
- return (this.name || this._def.paletteLabel);
119
- },
120
-
121
- labelStyle: function() {
122
- return this.name?"node_label_italic":"";
123
- },
124
- });
125
- </script>
126
-
127
- <script type="text/html" data-template-name="TriggerImport">
128
- <div class="form-row">
129
- <label for="node-input-name">
130
- <i class="fa fa-tag"></i>
131
- <span data-i18n="common.label.name">Name</span>
132
- </label>
133
- <input type="text" id="node-input-name" placeholder="Name">
134
- </div>
135
-
136
- <div class="form-row">
137
- <label for="node-input-autoimport" style="width: 150px !important;">
138
- <span>Automatic Import?</span>
139
- </label>
140
- <input type="checkbox"
141
- id="node-input-autoimport"
142
- style="display:inline-block; width:15px; vertical-align:baseline;">
143
- </div>
144
-
145
- <div class="form-row">
146
- <label for="node-input-removeduplicates" style="width: 150px !important;">
147
- <span>Remove duplicates?</span>
148
- </label>
149
- <input type="checkbox"
150
- id="node-input-removeduplicates"
151
- style="display:inline-block; width:15px; vertical-align:baseline;">
152
- </div>
153
-
154
- </script>
155
-
156
- <script type="text/html" data-help-name="TriggerImport">
157
- <p>Trigger import opens the flow import dialog with data that came from the server.</p>
158
- </script>
File without changes