@gregoriusrippenstein/node-red-contrib-nodedev 0.0.10 → 0.1.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.
@@ -0,0 +1,286 @@
1
+ <script type="text/javascript">
2
+ (function(){
3
+
4
+ function sendToBackend(node,data = {}) {
5
+
6
+ $.ajax({
7
+ url: "NodeDevOps/" + node.id,
8
+ type: "POST",
9
+ contentType: "application/json; charset=utf-8",
10
+
11
+ data: JSON.stringify(data),
12
+
13
+ success: function (resp) {
14
+ RED.notify("Node Developer Operation trigger", {
15
+ type: "success",
16
+ id: "NodeDevOps",
17
+ timeout: 2000
18
+ });
19
+ },
20
+
21
+ error: function (jqXHR, textStatus, errorThrown) {
22
+ if (jqXHR.status == 404) {
23
+ RED.notify("Node has not yet been deployed, please deploy.", "error");
24
+ } else if (jqXHR.status == 405) {
25
+ RED.notify("Not Allowed.", "error");
26
+ } else if (jqXHR.status == 500) {
27
+ RED.notify(node._("common.notification.error", {
28
+ message: node._("inject.errors.failed")
29
+ }), "error");
30
+ } else if (jqXHR.status == 0) {
31
+ RED.notify(node._("common.notification.error", {
32
+ message: node._("common.notification.errors.no-response")
33
+ }), "error");
34
+ } else {
35
+ RED.notify(node._("common.notification.error", {
36
+ message: node._("common.notification.errors.unexpected", {
37
+ status: jqXHR.status, message: textStatus }) }), "error");
38
+ }
39
+ }
40
+ });
41
+ }
42
+
43
+ RED.nodes.registerType('NodeDevOps',{
44
+ color: '#e5e4ef',
45
+ icon: "font-awesome/fa-terminal",
46
+ category: 'nodedev',
47
+ defaults: {
48
+ name: { value:"" },
49
+
50
+ pname: { value: "", required: true },
51
+ pversion: { value: "", required: true },
52
+
53
+ noderedinstall: { value: false },
54
+ randompackagename: { value: false },
55
+
56
+ gitcommit: { value: false },
57
+ gitcheckforchange: { value: false },
58
+ githubowner: { value: ""},
59
+ githubrepo: { value: ""},
60
+ githubbranch: { value: "main"},
61
+ githubauthor: { value: ""},
62
+ githubauthoremail: { value: "" },
63
+ githubmessage: { value: "" },
64
+
65
+ npmpublish: { value: false },
66
+ npmunpublish: { value: false },
67
+ npmotp: { value: ""},
68
+ },
69
+
70
+ inputs: 0,
71
+ outputs: 1,
72
+
73
+ label: function() {
74
+ return (this.name || this._def.paletteLabel);
75
+ },
76
+
77
+ labelStyle: function() {
78
+ return this.name?"node_label_italic":"";
79
+ },
80
+
81
+ onpaletteadd: function() {
82
+ },
83
+
84
+ oneditprepare: function() {
85
+
86
+ $('#node-input-noderedinstall').on('change', () => {
87
+ if ( $('#node-input-noderedinstall').is(":checked") ) {
88
+ $("#noderedinstall-options").animate({opacity: 'show', height: 'show'}, 450);
89
+ } else {
90
+ $("#noderedinstall-options").animate({opacity: 'hide', height: 'hide'}, 450);
91
+ }
92
+ });
93
+
94
+ $('#node-input-gitcommit').on('change', () => {
95
+ if ( $('#node-input-gitcommit').is(":checked") ) {
96
+ $("#github-options").animate({opacity: 'show', height: 'show'}, 450);
97
+ $("#gitcommit-options").animate({opacity: 'show', height: 'show'}, 450);
98
+ $('#node-input-gitcheckforchange').prop('checked',false)
99
+ } else {
100
+ $("#gitcommit-options").animate({opacity: 'hide', height: 'hide'}, 450);
101
+ if ( !$('#node-input-gitcheckforchange').is(":checked") ) {
102
+ $("#github-options").animate({opacity: 'hide', height: 'hide'}, 450);
103
+ }
104
+ }
105
+ });
106
+
107
+ $('#node-input-gitcheckforchange').on('change', () => {
108
+ if ( $('#node-input-gitcheckforchange').is(":checked") ) {
109
+ $("#github-options").animate({opacity: 'show', height: 'show'}, 450);
110
+ $("#gitcommit-options").animate({opacity: 'hide', height: 'hide'}, 450);
111
+ $('#node-input-gitcommit').prop('checked',false)
112
+ } else {
113
+ if ( !$('#node-input-gitcommit').is(":checked") ) {
114
+ $("#github-options").animate({opacity: 'hide', height: 'hide'}, 450);
115
+ $("#gitcommit-options").animate({opacity: 'hide', height: 'hide'}, 450);
116
+ }
117
+ }
118
+ });
119
+
120
+ $('#node-input-npmpublish').on('change', () => {
121
+ if ( $('#node-input-npmpublish').is(":checked") ) {
122
+ $("#npmpublish-options").animate({opacity: 'show', height: 'show'}, 450);
123
+ $('#node-input-npmunpublish').prop('checked',false)
124
+ } else {
125
+ if ( !$('#node-input-npmunpublish').is(":checked") ) {
126
+ $("#npmpublish-options").animate({opacity: 'hide', height: 'hide'}, 450);
127
+ }
128
+ }
129
+ });
130
+
131
+ $('#node-input-npmunpublish').on('change', () => {
132
+ if ( $('#node-input-npmunpublish').is(":checked") ) {
133
+ $("#npmpublish-options").animate({opacity: 'show', height: 'show'}, 450);
134
+ $('#node-input-npmpublish').prop('checked',false)
135
+ } else {
136
+ if ( !$('#node-input-npmpublish').is(":checked") ) {
137
+ $("#npmpublish-options").animate({opacity: 'hide', height: 'hide'}, 450);
138
+ }
139
+ }
140
+ });
141
+
142
+ },
143
+
144
+ oneditcancel: function() {
145
+ },
146
+
147
+ oneditsave: function() {
148
+ },
149
+
150
+ onpaletteremove: function() {
151
+ },
152
+
153
+
154
+ button: {
155
+ enabled: function() {
156
+ return !this.changed
157
+ },
158
+
159
+ onclick: function () {
160
+ if (this.changed) {
161
+ return RED.notify(RED._("notification.warning", {
162
+ message: RED._("notification.warnings.undeployedChanges")
163
+ }), "warning");
164
+ }
165
+
166
+ var that = this;
167
+ var data = {}
168
+
169
+ Object.keys(that._def.defaults).forEach( kname => {
170
+ data[kname] = that[kname]
171
+ })
172
+
173
+ sendToBackend(that, data)
174
+ }
175
+ },
176
+
177
+ });
178
+ })();
179
+ </script>
180
+
181
+ <script type="text/html" data-template-name="NodeDevOps">
182
+ <div class="form-row">
183
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
184
+ <input type="text" id="node-input-name" placeholder="Name"/>
185
+ </div>
186
+
187
+ <hr/>
188
+
189
+ <div class="form-row">
190
+ <label for="node-input-pname" style="min-width: 150px;"><i class="fa fa-tag"></i> Package Name</label>
191
+ <input type="text" id="node-input-pname" placeholder="@username/node-red-contrib-somename"/>
192
+ </div>
193
+
194
+ <div class="form-row">
195
+ <label for="node-input-pversion" style="min-width: 150px;"><i class="fa fa-tag"></i> Package Version</label>
196
+ <input type="text" id="node-input-pversion" placeholder="0.0.1"/>
197
+ </div>
198
+
199
+ <hr/>
200
+
201
+ <div class="form-row">
202
+ <label for="node-input-noderedinstall" style="min-width: 120px;">
203
+ <span>Install locally?</span>
204
+ </label>
205
+ <input type="checkbox" id="node-input-noderedinstall" style="display:inline-block; width:15px; vertical-align:baseline;">
206
+ </div>
207
+
208
+ <div id="noderedinstall-options">
209
+ <div class="form-row">
210
+ <label for="node-input-randompackagename" style="min-width: 180px;">
211
+ <span>Randomise Package Name?</span>
212
+ </label>
213
+ <input type="checkbox" id="node-input-randompackagename" style="display:inline-block; width:15px; vertical-align:baseline;">
214
+ </div>
215
+ </div>
216
+
217
+ <hr/>
218
+ <div class="form-row">
219
+ <label for="node-input-npmpublish" style="min-width: 120px;">
220
+ <span>NPMjs: Publish</span>
221
+ </label>
222
+ <input type="checkbox" id="node-input-npmpublish" style="display:inline-block; width:15px; vertical-align:baseline;">
223
+ <label for="node-input-npmunpublish" style="margin-left: 30px; min-width: 100px;">
224
+ <span>Unpublish</span>
225
+ </label>
226
+ <input type="checkbox" id="node-input-npmunpublish" style="display:inline-block; width:15px; vertical-align:baseline;">
227
+ </div>
228
+
229
+ <div id="npmpublish-options">
230
+ <div class="form-row">
231
+ <label for="node-input-npmotp" style="min-width: 150px;"><i class="fa fa-tag"></i> One Time Password</label>
232
+ <input type="text" id="node-input-npmotp" placeholder="111999"/>
233
+ </div>
234
+ </div>
235
+
236
+ <hr />
237
+ <div class="form-row">
238
+ <label for="node-input-gitcommit" style="min-width: 120px;">
239
+ <span>GitHub: Commit?</span>
240
+ </label>
241
+ <input type="checkbox" id="node-input-gitcommit" style="display:inline-block; width:15px; vertical-align:baseline;">
242
+ <label for="node-input-gitcheckforchange" style="margin-left: 30px; min-width: 100px;">
243
+ <span>What changed?</span>
244
+ </label>
245
+ <input type="checkbox" id="node-input-gitcheckforchange" style="display:inline-block; width:15px; vertical-align:baseline;">
246
+ </div>
247
+
248
+
249
+ <div id="github-options">
250
+ <div class="form-row">
251
+ <label for="node-input-githubowner" style="min-width: 150px;"><i class="fa fa-tag"></i> GitHub Username</label>
252
+ <input type="text" id="node-input-githubowner" placeholder="username"/>
253
+ </div>
254
+ <div class="form-row">
255
+ <label for="node-input-githubrepo" style="min-width: 150px;"><i class="fa fa-tag"></i> Repository</label>
256
+ <input type="text" id="node-input-githubrepo" placeholder=""/>
257
+ </div>
258
+ <div class="form-row">
259
+ <label for="node-input-githubbranch" style="min-width: 150px;"><i class="fa fa-tag"></i> Branch</label>
260
+ <input type="text" id="node-input-githubbranch" placeholder="main"/>
261
+ </div>
262
+ </div>
263
+
264
+ <div id="gitcommit-options">
265
+ <div class="form-row">
266
+ <label for="node-input-githubmessage" style="min-width: 150px;"><i class="fa fa-tag"></i> Commit Message</label>
267
+ <input type="text" id="node-input-githubmessage" placeholder="Initial Commit"/>
268
+ </div>
269
+ <div class="form-row">
270
+ <label for="node-input-githubauthor" style="min-width: 150px;"><i class="fa fa-tag"></i> Author Name</label>
271
+ <input type="text" id="node-input-githubauthor" placeholder="Joe Blog"/>
272
+ </div>
273
+ <div class="form-row">
274
+ <label for="node-input-githubauthoremail" style="min-width: 150px;"><i class="fa fa-tag"></i> Author Email</label>
275
+ <input type="text" id="node-input-githubauthoremail" placeholder="joe@spreads-the.love"/>
276
+ </div>
277
+ </div>
278
+ </script>
279
+
280
+ <script type="text/html" data-help-name="NodeDevOps">
281
+ <p>NodeDevOps is the operations node that controals what happens with the package.</p>
282
+ Possible actions that can happen are GitHub commits and diffs, NPM publish or unpublish and installing the package
283
+ locally for local testing.
284
+
285
+ Local installations can be uninstalled so that changes can tested and modified quickly.
286
+ </script>
@@ -0,0 +1,51 @@
1
+ module.exports = function (RED) {
2
+ function NodeDevOpsFunctionality(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
+ msg.commit_message = msg.githubmessage;
14
+
15
+ if (msg.randompackagename) {
16
+ msg.pname += Math.random().toString().substring(2)
17
+ }
18
+
19
+ if (msg.randompackagename && (msg.gitcommit || msg.npmpublish || msg.npmunpublish) ) {
20
+ done("Cannot randomise package and perform GitHub or NPM operation", msg)
21
+ return
22
+ }
23
+ send(msg);
24
+ done();
25
+ });
26
+ }
27
+
28
+ RED.nodes.registerType("NodeDevOps", NodeDevOpsFunctionality);
29
+
30
+ RED.httpAdmin.post("/NodeDevOps/:id",
31
+ RED.auth.needsPermission("NodeDevOps.write"),
32
+ (req, res) => {
33
+ var node = RED.nodes.getNode(req.params.id);
34
+ if (node != null) {
35
+ try {
36
+ if (req.body && node.type == "NodeDevOps") {
37
+ node.receive(req.body);
38
+ res.status(200).send({ status: "ok" })
39
+ } else {
40
+ res.sendStatus(404);
41
+ }
42
+ } catch (err) {
43
+ console.error(err);
44
+ res.status(500).send(err.toString());
45
+ node.error("NodeDevOps: Submission failed: " + err.toString())
46
+ }
47
+ } else {
48
+ res.sendStatus(404);
49
+ }
50
+ });
51
+ }
@@ -62,6 +62,26 @@
62
62
  </div>
63
63
  </div>
64
64
 
65
+ <div class="form-row">
66
+ <label for="node-input-frt2bakcomm" style="min-width: 250px;">
67
+ <span>Frontend to Backend communication?</span>
68
+ </label>
69
+ <input type="checkbox" id="node-input-frt2bakcomm" style="display:inline-block; width:15px; vertical-align:baseline;">
70
+ </div>
71
+
72
+ <div class="form-row">
73
+ <label for="node-input-bak2frtcomm" style="min-width: 250px;">
74
+ <span>Backend to Frontend communication?</span>
75
+ </label>
76
+ <input type="checkbox" id="node-input-bak2frtcomm" style="display:inline-block; width:15px; vertical-align:baseline;">
77
+ </div>
78
+
79
+ <div class="form-row">
80
+ <label for="node-input-createmanifest" style="min-width: 250px;">
81
+ <span>Create manifest?</span>
82
+ </label>
83
+ <input type="checkbox" id="node-input-createmanifest" style="display:inline-block; width:15px; vertical-align:baseline;">
84
+ </div>
65
85
 
66
86
  <div class="form-row">
67
87
  <button id="node-input-generate-tmplnodes-but"
@@ -96,14 +116,19 @@
96
116
  */
97
117
  data["summary"] = node.editorSummary.getValue();
98
118
  data["description"] = node.editorDesc.getValue();
99
- data["hasbutton"] = $('#node-input-hasbutton').is(":checked");
100
- data["hasinput"] = $('#node-input-hasinput').is(":checked");
119
+
101
120
  data["color"] = $('#node-input-colour').val();
102
121
  data["icon"] = $('#red-ui-editor-node-icon').val();
103
122
  data["name"] = $('#node-input-nodename').val();
104
123
  data["outputcount"] = $('#node-input-outputcount').val();
105
124
  data["category"] = $('#node-input-category').val();
106
125
 
126
+ data["hasbutton"] = $('#node-input-hasbutton').is(":checked");
127
+ data["hasinput"] = $('#node-input-hasinput').is(":checked");
128
+ data["bak2frtcomm"] = $('#node-input-bak2frtcomm').is(":checked");
129
+ data["frt2bakcomm"] = $('#node-input-frt2bakcomm').is(":checked");
130
+ data["createmanifest"] = $('#node-input-createmanifest').is(":checked");
131
+
107
132
  data["__task"] = "generate_from_templates";
108
133
 
109
134
  $.ajax({
@@ -118,7 +143,7 @@
118
143
  success: function (resp) {
119
144
  $('#node-dialog-ok').trigger('click');
120
145
 
121
- RED.notify("Data sent", {
146
+ RED.notify("Preparing Node...", {
122
147
  type: "warning",
123
148
  timeout: 2000
124
149
  });
@@ -161,7 +186,10 @@
161
186
  category: { value: "" },
162
187
  summary: { value: ""},
163
188
  description: { value: ""},
164
- icon: { value: "font-awesome/fa-industry" }
189
+ icon: { value: "font-awesome/fa-industry" },
190
+ frt2bakcomm: { value: false },
191
+ bak2frtcomm: { value: false },
192
+ createmanifest: { value: false }
165
193
  },
166
194
  inputs: 1,
167
195
  outputs: 1,
@@ -300,6 +328,9 @@
300
328
  delete this.editorDesc;
301
329
  },
302
330
 
331
+ onpaletteremove: function() {
332
+ },
333
+
303
334
  oneditresize: function (size) {
304
335
  },
305
336
  });
@@ -9,6 +9,13 @@ module.exports = function (RED) {
9
9
  var streamx = require('streamx');
10
10
  var pakoGzip = require('pako');
11
11
 
12
+ var spcRepDict = {
13
+ "ocb2": "{{",
14
+ "ocb3": "{{{",
15
+ "ccb3": "}}}",
16
+ "ccb2": "}}"
17
+ };
18
+
12
19
  function extractTokens(tokens, set) {
13
20
  set = set || new Set();
14
21
  tokens.forEach(function (token) {
@@ -42,6 +49,14 @@ module.exports = function (RED) {
42
49
  return undefined;
43
50
  }
44
51
 
52
+ function parseIntern(key) {
53
+ var match = /^__\.(.+)$/.exec(key);
54
+ if (match) {
55
+ return match[1];
56
+ }
57
+ return undefined;
58
+ }
59
+
45
60
  /**
46
61
  * Custom Mustache Context capable to collect message property and node
47
62
  * flow and global context
@@ -72,6 +87,11 @@ module.exports = function (RED) {
72
87
  return value;
73
88
  }
74
89
 
90
+ var spcRep = parseIntern(name)
91
+ if ( spcRep ) {
92
+ return spcRepDict[spcRep] || ("UNFOUND - " + spcRep);
93
+ }
94
+
75
95
  // try env
76
96
  if (parseEnv(name)) {
77
97
  return this.cachedContextTokens[name];
@@ -88,6 +108,7 @@ module.exports = function (RED) {
88
108
  return this.cachedContextTokens[name];
89
109
  }
90
110
  }
111
+
91
112
  return '';
92
113
  }
93
114
  catch (err) {
@@ -160,11 +181,7 @@ module.exports = function (RED) {
160
181
  output: "str",
161
182
  x: 100,
162
183
  y: 50,
163
- wires: [
164
- [
165
- secondId
166
- ]
167
- ]
184
+ wires: [[secondId]]
168
185
  })
169
186
 
170
187
  allNodes.push({
@@ -178,15 +195,84 @@ module.exports = function (RED) {
178
195
  output: "str",
179
196
  x: 100,
180
197
  y: 100,
181
- wires: [
182
- [
183
- ]
184
- ]
198
+ wires: [[]]
185
199
  })
186
200
 
187
201
  return allNodes;
188
202
  }
189
203
 
204
+ function createManifestFiles(msg, node, nodeDefinitions) {
205
+ /* ASSUMPTION: assume the .js file is defined first and
206
+ then the .html file in the node definitions */
207
+
208
+ var packageJsonPath = path.join(__dirname, 'templates', 'tmplpackage.json');
209
+ var readmePath = path.join(__dirname, 'templates', 'tmplreadme.md');
210
+ var licensePath = path.join(__dirname, 'templates', 'tmpllicense');
211
+
212
+ var pkjsTmpl = fs.readFileSync(packageJsonPath, 'utf8');
213
+ var rdmeTmpl = fs.readFileSync(readmePath, 'utf8');
214
+ var lcnsTmpl = fs.readFileSync(licensePath, 'utf8');
215
+
216
+ spcRepDict["nodestanza"] = " \"" + msg.node.name.toLowerCase() + "\": \"" + nodeDefinitions[0].filename + "\""
217
+
218
+ var content = {};
219
+
220
+ var promises = [
221
+ handleTemplate(msg, node, pkjsTmpl).then((c) => { content["pkjs"] = c }),
222
+ handleTemplate(msg, node, rdmeTmpl).then((c) => { content["rdme"] = c }),
223
+ handleTemplate(msg, node, lcnsTmpl).then((c) => { content["lcns"] = c }),
224
+ ];
225
+
226
+ return Promise.all(promises).then( () => {
227
+ var secondId = RED.util.generateId();
228
+ var thirdId = RED.util.generateId();
229
+
230
+ nodeDefinitions.push({
231
+ id: RED.util.generateId(),
232
+ type: "PkgFile",
233
+ name: "LICENSE",
234
+ filename: "LICENSE",
235
+ template: content["lcns"],
236
+ syntax: "mustache",
237
+ format: "text",
238
+ output: "str",
239
+ x: 100,
240
+ y: -100,
241
+ wires: [[ secondId ]]
242
+ })
243
+
244
+ nodeDefinitions.push({
245
+ id: secondId,
246
+ type: "PkgFile",
247
+ name: "README.md",
248
+ filename: "README.md",
249
+ template: content["rdme"],
250
+ syntax: "mustache",
251
+ format: "markdown",
252
+ output: "str",
253
+ x: 100,
254
+ y: -50,
255
+ wires: [[thirdId]]
256
+ })
257
+
258
+ nodeDefinitions.push({
259
+ id: thirdId,
260
+ type: "PkgFile",
261
+ name: "package.json",
262
+ filename: "package.json",
263
+ template: content["pkjs"],
264
+ syntax: "mustache",
265
+ format: "json",
266
+ output: "str",
267
+ x: 100,
268
+ y: 0,
269
+ wires: [[nodeDefinitions[0].id]]
270
+ })
271
+
272
+ return nodeDefinitions;
273
+ })
274
+ }
275
+
190
276
  function NodeFactoryFunctionality(config) {
191
277
  RED.nodes.createNode(this, config);
192
278
 
@@ -208,22 +294,47 @@ module.exports = function (RED) {
208
294
 
209
295
  handleTemplate(msg, node, jsonTmpl).then(function (data) {
210
296
  var jsData = data;
297
+
211
298
  handleTemplate(msg, node, htmlTmpl).then(function (data) {
212
- var nodeImpStr = JSON.stringify(convertToPkgFileNodes(msg, jsData, data));
213
-
214
- send({ payload: nodeImpStr })
215
-
216
- RED.comms.publish(
217
- "nodedev:perform-autoimport-nodes",
218
- RED.util.encodeObject({
219
- msg: "autoimport",
220
- payload: nodeImpStr,
221
- topic: msg.topic,
222
- nodeid: node.id,
223
- _msg: msg
299
+ var nodeDef = convertToPkgFileNodes(msg, jsData, data)
300
+
301
+ if (msg.node.createmanifest ) {
302
+ /* create the package.json, readme and license files */
303
+ createManifestFiles(msg, node, nodeDef).then( (data) => {
304
+ var nodeImpStr = JSON.stringify(data);
305
+
306
+ send({ payload: nodeImpStr })
307
+
308
+ RED.comms.publish(
309
+ "nodedev:perform-autoimport-nodes",
310
+ RED.util.encodeObject({
311
+ msg: "autoimport",
312
+ payload: nodeImpStr,
313
+ topic: msg.topic,
314
+ nodeid: node.id,
315
+ _msg: msg
316
+ })
317
+ );
318
+ }).catch( (err) => {
319
+ msg.error = err
320
+ done(err.message, msg)
224
321
  })
225
- );
226
-
322
+ } else {
323
+ var nodeImpStr = JSON.stringify(nodeDef);
324
+
325
+ send({ payload: nodeImpStr })
326
+
327
+ RED.comms.publish(
328
+ "nodedev:perform-autoimport-nodes",
329
+ RED.util.encodeObject({
330
+ msg: "autoimport",
331
+ payload: nodeImpStr,
332
+ topic: msg.topic,
333
+ nodeid: node.id,
334
+ _msg: msg
335
+ })
336
+ );
337
+ }
227
338
  done()
228
339
  }).catch((err) => {
229
340
  msg.error = err
@@ -9,7 +9,7 @@
9
9
  },
10
10
  inputs: 1,
11
11
  outputs: 1,
12
- icon: "font-awesome/fa-birthday-cake",
12
+ icon: "font-awesome/fa-archive",
13
13
  label: function() {
14
14
  return this.name || this._def.paletteLabel;
15
15
  },
@@ -104,7 +104,7 @@
104
104
 
105
105
  RED.nodes.registerType('NodeRedInstall',{
106
106
  color: '#e5e4ef',
107
- icon: "icons/subflow.svg",
107
+ icon: "nodedevsubflow.svg",
108
108
  category: 'nodedev',
109
109
  paletteLabel: 'NRInstall',
110
110
  defaults: {
@@ -43,7 +43,7 @@ module.exports = function (RED) {
43
43
  var userscope = manifest.name.split("/")[0];
44
44
  opts[userscope + ":registry"] = "https://registry.npmjs.org"
45
45
 
46
- if (cfg.action == "publish") {
46
+ if (msg.npmpublish || cfg.action == "publish") {
47
47
  libpub.publish(
48
48
  manifest, tarball, opts
49
49
  ).then((data) => {
@@ -54,19 +54,19 @@ module.exports = function (RED) {
54
54
  msg.error = exp;
55
55
  done("publish failed", msg)
56
56
  })
57
- }
58
-
59
- if (cfg.action == "unpublish") {
60
- libpub.unpublish(
61
- manifest.name, opts
62
- ).then((data) => {
63
- msg.payload = JSON.stringify(data);
64
- send(msg)
65
- done()
66
- }).catch((exp) => {
67
- msg.error = exp;
68
- done("publish failed", msg)
69
- })
57
+ } else {
58
+ if (msg.npmunpublish || cfg.action == "unpublish") {
59
+ libpub.unpublish(
60
+ manifest.name, opts
61
+ ).then((data) => {
62
+ msg.payload = JSON.stringify(data);
63
+ send(msg)
64
+ done()
65
+ }).catch((exp) => {
66
+ msg.error = exp;
67
+ done("unpublish failed", msg)
68
+ })
69
+ }
70
70
  }
71
71
  })
72
72
  });
@@ -0,0 +1 @@
1
+ <svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M25 25.94h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1h-7c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zm-17 12h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1H8c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zm-.416 11C5.624 48.94 4 47.315 4 45.356V14.522c0-1.96 1.625-3.582 3.584-3.582h24.832c1.96 0 3.584 1.623 3.584 3.582v30.834c0 1.96-1.625 3.584-3.584 3.584zM32 36.94H19c0 2.19-1.81 4-4 4H7v4.416c0 .35.235.584.584.584h24.832c.35 0 .584-.235.584-.584v-8.417zm1-2v-6h-8c-2.19 0-4-1.81-4-4h-1c-4.333-.002-8.667.004-13 0v6h8c2.19 0 4 1.81 4 4h13zm0-16v-4.418c0-.35-.235-.582-.584-.582H7.584c-.35 0-.584.233-.584.582v8.417c4.333.002 8.667.001 13 .001h1c0-2.19 1.81-4 4-4h8z" color="#000" fill="#fff"/></svg>
@@ -1,5 +1,49 @@
1
1
  <script type="text/javascript">
2
2
  (function(){
3
+
4
+ {{ #node.frt2bakcomm }}
5
+ function sendToBackend(node,data = {}) {
6
+
7
+ $.ajax({
8
+ url: "{{ node.name }}/" + node.id,
9
+ type: "POST",
10
+ contentType: "application/json; charset=utf-8",
11
+
12
+ data: JSON.stringify({
13
+ ...data,
14
+ hello: "world",
15
+ }),
16
+
17
+ success: function (resp) {
18
+ RED.notify("Successfully sent something to the backend", {
19
+ type: "warning",
20
+ id: "{{node.name}}",
21
+ timeout: 2000
22
+ });
23
+ },
24
+
25
+ error: function (jqXHR, textStatus, errorThrown) {
26
+ if (jqXHR.status == 404) {
27
+ RED.notify("Node has not yet been deployed, please deploy.", "error");
28
+ } else if (jqXHR.status == 405) {
29
+ RED.notify("Not Allowed.", "error");
30
+ } else if (jqXHR.status == 500) {
31
+ RED.notify(node._("common.notification.error", {
32
+ message: node._("inject.errors.failed")
33
+ }), "error");
34
+ } else if (jqXHR.status == 0) {
35
+ RED.notify(node._("common.notification.error", {
36
+ message: node._("common.notification.errors.no-response")
37
+ }), "error");
38
+ } else {
39
+ RED.notify(node._("common.notification.error", {
40
+ message: node._("common.notification.errors.unexpected", {
41
+ status: jqXHR.status, message: textStatus }) }), "error");
42
+ }
43
+ }
44
+ });
45
+ }
46
+ {{ /node.frt2bakcomm }}
3
47
 
4
48
  function frontendSupportFunction() {
5
49
  }
@@ -36,6 +80,18 @@
36
80
  },
37
81
 
38
82
  onpaletteadd: function() {
83
+ {{#node.bak2frtcomm}}
84
+ this.messageFromBackendHandler = (topic,dataobj) => {
85
+ console.log( "here goes the code for handling a message from the backend", topic, dataobj);
86
+
87
+ RED.notify("Backend sent something to the frontend - check browser console.", {
88
+ type: "success",
89
+ id: "{{node.name}}",
90
+ timeout: 2000
91
+ });
92
+ };
93
+ RED.comms.subscribe('{{node.name}}:message-from-backend',this.messageFromBackendHandler);
94
+ {{/node.bak2frtcomm}}
39
95
  },
40
96
 
41
97
  oneditprepare: function() {
@@ -47,6 +103,13 @@
47
103
  oneditsave: function() {
48
104
  },
49
105
 
106
+ onpaletteremove: function() {
107
+ {{#node.bak2frtcomm}}
108
+ RED.comms.unsubscribe('{{node.name}}:message-from-backend',this.messageFromBackendHandler);
109
+ {{/node.bak2frtcomm}}
110
+ },
111
+
112
+
50
113
  {{#node.hasbutton}}
51
114
  button: {
52
115
  enabled: function() {
@@ -59,6 +122,12 @@
59
122
  message: RED._("notification.warnings.undeployedChanges")
60
123
  }), "warning");
61
124
  }
125
+
126
+ {{ #node.frt2bakcomm }}
127
+ var that = this;
128
+ sendToBackend(that, {"payload": "button pressed on frontend"})
129
+ {{ /node.frt2bakcomm }}
130
+
62
131
  /* here goes the button code to be executed on click */
63
132
  }
64
133
  },
@@ -11,10 +11,49 @@ module.exports = function(RED) {
11
11
 
12
12
  /* msg handler, in this case pass the message on unchanged */
13
13
  node.on("input", function(msg, send, done) {
14
+ {{#node.bak2frtcomm}}
15
+ RED.comms.publish("{{node.name}}:message-from-backend",
16
+ RED.util.encodeObject({
17
+ ...msg,
18
+ "data": "message from backend",
19
+ })
20
+ );
21
+ {{/node.bak2frtcomm}}
14
22
  send(msg);
15
23
  done();
16
24
  });
17
25
  }
18
26
 
19
27
  RED.nodes.registerType("{{ node.name }}", {{ node.name }}Functionality);
28
+
29
+ {{ #node.frt2bakcomm }}
30
+ RED.httpAdmin.post("/{{ node.name }}/:id",
31
+ RED.auth.needsPermission("{{ node.name }}.write"),
32
+ (req, res) => {
33
+ var node = RED.nodes.getNode(req.params.id);
34
+ if (node != null) {
35
+ try {
36
+ if (req.body && node.type == "{{ node.name }}") {
37
+ /* here goes the code for handling a request from the frontend */
38
+
39
+ /* this sends the request to the input handler above */
40
+ node.receive(req.body);
41
+
42
+ /* this tells the frontend that all went well */
43
+ res.status(200).send({
44
+ "status": "ok"
45
+ })
46
+ } else {
47
+ res.sendStatus(404);
48
+ }
49
+ } catch (err) {
50
+ console.error(err);
51
+ res.status(500).send(err.toString());
52
+ node.error("{{ node.name }}: Submission failed: " + err.toString())
53
+ }
54
+ } else {
55
+ res.sendStatus(404);
56
+ }
57
+ });
58
+ {{/node.frt2bakcomm}}
20
59
  }
@@ -0,0 +1,4 @@
1
+ # LICENSE
2
+
3
+ License texts comes here.
4
+
@@ -0,0 +1,33 @@
1
+ {
2
+ "name" : "{{__.ocb3}} pname {{__.ccb3}}",
3
+ "version": "{{__.ocb2}} pversion {{__.ccb2}}",
4
+ "dependencies": {
5
+ },
6
+
7
+ "keywords": [
8
+ "node-red"
9
+ ],
10
+
11
+ "homepage": "https://github.com/{{__.ocb2}} githubowner {{__.ccb2}}/{{__.ocb2}} githubrepo {{__.ccb2}}#readme",
12
+ "license": "Don't do evil.",
13
+ "author": "Joe Blog <joe.blog@spreads-the.love>",
14
+ "engines": {
15
+ "node": ">=14"
16
+ },
17
+
18
+ "node-red" : {
19
+ "version": ">=3.0.0",
20
+ "nodes": {
21
+ {{{__.nodestanza}}}
22
+ }
23
+ },
24
+
25
+ "description": "Description of what these nodes do.",
26
+ "repository": {
27
+ "type": "github",
28
+ "url": "git+https://github.com/{{__.ocb2}} githubowner {{__.ccb2}}/{{__.ocb2}} githubrepo {{__.ccb2}}.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/{{__.ocb2}} githubowner {{__.ccb2}}/{{__.ocb2}} githubrepo {{__.ccb2}}"
32
+ }
33
+ }
@@ -0,0 +1,4 @@
1
+ # {{ node.name }}
2
+
3
+ Describe what the package does here.
4
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name" : "@gregoriusrippenstein/node-red-contrib-nodedev",
3
- "version": "0.0.10",
3
+ "version": "0.1.1",
4
4
  "dependencies": {
5
5
  "pako": "latest",
6
6
  "tar-stream": "latest",
@@ -23,6 +23,7 @@
23
23
  "node-red" : {
24
24
  "version": ">=3.0.0",
25
25
  "nodes": {
26
+ "nodedevops": "nodes/05-node-dev-ops.js",
26
27
  "nodefactory": "nodes/10-node-factory.js",
27
28
  "pkgfile": "nodes/20-pkg-file.js",
28
29
  "npmtarball": "nodes/30-npm-tarball.js",