@node-red/registry 4.0.0-beta.1 → 4.0.0-beta.3

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.
@@ -28,11 +28,6 @@ let installEnabled = true;
28
28
  let installAllowList = ['*'];
29
29
  let installDenyList = [];
30
30
 
31
- let IMPORT_SUPPORTED = true;
32
- const nodeVersionParts = process.versions.node.split(".").map(v => parseInt(v));
33
- if (nodeVersionParts[0] < 12 || (nodeVersionParts[0] === 12 && nodeVersionParts[1] < 17)) {
34
- IMPORT_SUPPORTED = false;
35
- }
36
31
 
37
32
  function getInstallDir() {
38
33
  return path.resolve(settings.userDir || process.env.NODE_RED_HOME || ".");
@@ -110,18 +105,6 @@ function requireModule(module) {
110
105
  return require(moduleDir);
111
106
  }
112
107
  function importModule(module) {
113
- if (!IMPORT_SUPPORTED) {
114
- // On Node < 12.17 - fall back to try a require
115
- return new Promise((resolve, reject) => {
116
- try {
117
- const mod = requireModule(module);
118
- resolve(mod);
119
- } catch(err) {
120
- reject(err);
121
- }
122
- });
123
- }
124
-
125
108
  if (!registryUtil.checkModuleAllowed( module, null,installAllowList,installDenyList)) {
126
109
  const e = new Error("Module not allowed");
127
110
  e.code = "module_not_allowed";
@@ -273,7 +256,7 @@ async function installModule(moduleDetails) {
273
256
  let extraArgs = triggerPayload.args || [];
274
257
  let args = ['install', ...extraArgs, installSpec]
275
258
  log.trace(NPM_COMMAND + JSON.stringify(args));
276
- return exec.run(NPM_COMMAND, args, { cwd: installDir },true)
259
+ return exec.run(NPM_COMMAND, args, { cwd: installDir, shell: true },true)
277
260
  } else {
278
261
  log.trace("skipping npm install");
279
262
  }
package/lib/index.js CHANGED
@@ -319,6 +319,7 @@ module.exports = {
319
319
  getPluginsByType: plugins.getPluginsByType,
320
320
  getPluginList: plugins.getPluginList,
321
321
  getPluginConfigs: plugins.getPluginConfigs,
322
+ getPluginConfig: plugins.getPluginConfig,
322
323
  exportPluginSettings: plugins.exportPluginSettings,
323
324
 
324
325
 
package/lib/installer.js CHANGED
@@ -25,12 +25,17 @@ const registryUtil = require("./util");
25
25
  const library = require("./library");
26
26
  const {exec,log,events,hooks} = require("@node-red/util");
27
27
  const child_process = require('child_process');
28
- const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
29
- let installerEnabled = false;
30
28
 
29
+ const plugins = require("./plugins");
30
+
31
+ const isWindows = process.platform === 'win32'
32
+ const npmCommand = isWindows ? 'npm.cmd' : 'npm';
33
+
34
+ let installerEnabled = false;
31
35
  let settings;
36
+
32
37
  const moduleRe = /^(@[^/@]+?[/])?[^/@]+?$/;
33
- const slashRe = process.platform === "win32" ? /\\|[/]/ : /[/]/;
38
+ const slashRe = isWindows ? /\\|[/]/ : /[/]/;
34
39
  const pkgurlRe = /^(https?|git(|\+https?|\+ssh|\+file)):\/\//;
35
40
  const localtgzRe = /^([a-zA-Z]:|\/).+tgz$/;
36
41
 
@@ -225,7 +230,7 @@ async function installModule(module,version,url) {
225
230
  let extraArgs = triggerPayload.args || [];
226
231
  let args = ['install', ...extraArgs, installName]
227
232
  log.trace(npmCommand + JSON.stringify(args));
228
- return exec.run(npmCommand,args,{ cwd: installDir}, true)
233
+ return exec.run(npmCommand,args,{ cwd: installDir, shell: true }, true)
229
234
  } else {
230
235
  log.trace("skipping npm install");
231
236
  }
@@ -260,7 +265,7 @@ async function installModule(module,version,url) {
260
265
  log.warn("------------------------------------------");
261
266
  e = new Error(log._("server.install.install-failed")+": "+err.toString());
262
267
  if (err.hook === "postInstall") {
263
- return exec.run(npmCommand,["remove",module],{ cwd: installDir}, false).finally(() => {
268
+ return exec.run(npmCommand,["remove",module],{ cwd: installDir, shell: true }, false).finally(() => {
264
269
  throw e;
265
270
  })
266
271
  }
@@ -330,10 +335,18 @@ function reportRemovedModules(removedNodes) {
330
335
  //comms.publish("node/removed",removedNodes,false);
331
336
  log.info(log._("server.removed-types"));
332
337
  for (var j=0;j<removedNodes.length;j++) {
333
- for (var i=0;i<removedNodes[j].types.length;i++) {
338
+ for (var i=0;i<removedNodes[j].types?.length;i++) {
334
339
  log.info(" - "+(removedNodes[j].module?removedNodes[j].module+":":"")+removedNodes[j].types[i]);
335
340
  }
336
341
  }
342
+
343
+ log.info(log._("server.removed-plugins"));
344
+ for (let j=0;j<removedNodes.length;j++) {
345
+ for (var i=0;i<removedNodes[j].plugins?.length;i++) {
346
+ log.info(" - "+(removedNodes[j].module?removedNodes[j].module+":":"")+removedNodes[j].plugins[i].id);
347
+ }
348
+ }
349
+
337
350
  return removedNodes;
338
351
  }
339
352
 
@@ -356,7 +369,7 @@ async function getModuleVersionFromNPM(module, version) {
356
369
  }
357
370
 
358
371
  return new Promise((resolve, reject) => {
359
- child_process.execFile(npmCommand,['info','--json',installName],function(err,stdout,stderr) {
372
+ child_process.execFile(npmCommand,['info','--json',installName],{ shell: true },function(err,stdout,stderr) {
360
373
  try {
361
374
  if (!stdout) {
362
375
  log.warn(log._("server.install.install-failed-not-found",{name:module}));
@@ -495,8 +508,12 @@ function uninstallModule(module) {
495
508
  } catch(err) {
496
509
  return reject(new Error(log._("server.install.uninstall-failed",{name:module})));
497
510
  }
511
+
512
+ // need to remove the plugins first,
513
+ // as registry data necessary to perform this operation
514
+ var list = plugins.removeModule(module);
515
+ list = list.concat(registry.removeModule(module));
498
516
 
499
- var list = registry.removeModule(module);
500
517
  log.info(log._("server.install.uninstalling",{name:module}));
501
518
 
502
519
  let triggerPayload = {
@@ -511,7 +528,7 @@ function uninstallModule(module) {
511
528
  let extraArgs = triggerPayload.args || [];
512
529
  let args = ['remove', ...extraArgs, module]
513
530
  log.trace(npmCommand + JSON.stringify(args));
514
- return exec.run(npmCommand,args,{ cwd: installDir}, true)
531
+ return exec.run(npmCommand,args,{ cwd: installDir, shell: true }, true)
515
532
  } else {
516
533
  log.trace("skipping npm uninstall");
517
534
  }
@@ -578,7 +595,7 @@ async function checkPrereq() {
578
595
  installerEnabled = false;
579
596
  } else {
580
597
  return new Promise(resolve => {
581
- child_process.execFile(npmCommand,['-v'],function(err,stdout) {
598
+ child_process.execFile(npmCommand,['-v'],{ shell: true },function(err,stdout) {
582
599
  if (err) {
583
600
  log.info(log._("server.palette-editor.npm-not-found"));
584
601
  installerEnabled = false;
package/lib/plugins.js CHANGED
@@ -39,6 +39,8 @@ function registerPlugin(nodeSetId,id,definition) {
39
39
  pluginSettings[id] = definition.settings;
40
40
  }
41
41
 
42
+ // reset the cache when a new plugin is incoming!
43
+ pluginConfigCache = {};
42
44
 
43
45
  if (definition.onadd && typeof definition.onadd === 'function') {
44
46
  definition.onadd();
@@ -55,29 +57,47 @@ function getPluginsByType(type) {
55
57
  }
56
58
 
57
59
  function getPluginConfigs(lang) {
60
+ // we're not re-using getPluginConfig() here,
61
+ // to avoid calling registry.getModuleList() multiple times!
62
+
58
63
  if (!pluginConfigCache[lang]) {
59
64
  var result = "";
60
- var script = "";
61
65
  var moduleConfigs = registry.getModuleList();
62
66
  for (var module in moduleConfigs) {
63
67
  /* istanbul ignore else */
64
68
  if (moduleConfigs.hasOwnProperty(module)) {
65
- var plugins = moduleConfigs[module].plugins;
66
- for (var plugin in plugins) {
67
- if (plugins.hasOwnProperty(plugin)) {
68
- var config = plugins[plugin];
69
- if (config.enabled && !config.err && config.config) {
70
- result += "\n<!-- --- [red-plugin:"+config.id+"] --- -->\n";
71
- result += config.config;
72
- }
73
- }
74
- }
69
+ result += generateModulePluginConfig(moduleConfigs[module]);
75
70
  }
76
71
  }
77
72
  pluginConfigCache[lang] = result;
78
73
  }
79
74
  return pluginConfigCache[lang];
80
75
  }
76
+
77
+ function getPluginConfig(id, lang) {
78
+ let result = '';
79
+ let moduleConfigs = registry.getModuleList();
80
+ if (moduleConfigs.hasOwnProperty(id)) {
81
+ result = generateModulePluginConfig(moduleConfigs[id]);
82
+ }
83
+ return result;
84
+ }
85
+
86
+ function generateModulePluginConfig(module) {
87
+ let result = '';
88
+ const plugins = module.plugins
89
+ for (let plugin in plugins) {
90
+ if (plugins.hasOwnProperty(plugin)) {
91
+ let config = plugins[plugin];
92
+ if (config.enabled && !config.err && config.config) {
93
+ result += "\n<!-- --- [red-plugin:"+config.id+"] --- -->\n";
94
+ result += config.config;
95
+ }
96
+ }
97
+ }
98
+ return result;
99
+ }
100
+
81
101
  function getPluginList() {
82
102
  var list = [];
83
103
  var moduleConfigs = registry.getModuleList();
@@ -142,12 +162,51 @@ function exportPluginSettings(safeSettings) {
142
162
  return safeSettings;
143
163
  }
144
164
 
165
+ function removeModule(moduleId) {
166
+
167
+ // clean the (plugin) registry when a module is removed / uninstalled
168
+
169
+ let pluginList = [];
170
+ let module = registry.getModule(moduleId);
171
+ let keys = Object.keys(module.plugins ?? {});
172
+ keys.forEach( key => {
173
+ let _plugins = module.plugins[key].plugins ?? [];
174
+ _plugins.forEach( plugin => {
175
+ let id = plugin.id;
176
+
177
+ if (plugin.onremove && typeof plugin.onremove === 'function') {
178
+ plugin.onremove();
179
+ }
180
+
181
+ delete pluginToId[id];
182
+ delete plugins[id];
183
+ delete pluginSettings[id];
184
+ pluginConfigCache = {};
185
+
186
+ let psbtype = pluginsByType[plugin.type] ?? [];
187
+ for (let i=psbtype.length; i>0; i--) {
188
+ let pbt = psbtype[i-1];
189
+ if (pbt.id == id) {
190
+ psbtype.splice(i-1, 1);
191
+ }
192
+ }
193
+ })
194
+
195
+ pluginList.push(registry.filterNodeInfo(module.plugins[key]));
196
+
197
+ })
198
+
199
+ return pluginList;
200
+ }
201
+
145
202
  module.exports = {
146
203
  init,
147
204
  registerPlugin,
148
205
  getPlugin,
149
206
  getPluginsByType,
150
207
  getPluginConfigs,
208
+ getPluginConfig,
151
209
  getPluginList,
152
- exportPluginSettings
210
+ exportPluginSettings,
211
+ removeModule
153
212
  }
package/lib/registry.js CHANGED
@@ -65,7 +65,13 @@ function filterNodeInfo(n) {
65
65
  r.err = n.err;
66
66
  }
67
67
  if (n.hasOwnProperty("plugins")) {
68
- r.plugins = n.plugins;
68
+ r.plugins = n.plugins.map(p => {
69
+ return {
70
+ id: p.id,
71
+ type: p.type,
72
+ module: p.module
73
+ }
74
+ });
69
75
  }
70
76
  if (n.type === "plugin") {
71
77
  r.editor = !!n.template;
@@ -386,7 +392,8 @@ function getModuleInfo(module) {
386
392
  local: moduleConfigs[module].local,
387
393
  user: moduleConfigs[module].user,
388
394
  path: moduleConfigs[module].path,
389
- nodes: []
395
+ nodes: [],
396
+ plugins: []
390
397
  };
391
398
  if (moduleConfigs[module].dependencies) {
392
399
  m.dependencies = moduleConfigs[module].dependencies;
@@ -399,6 +406,14 @@ function getModuleInfo(module) {
399
406
  nodeInfo.version = m.version;
400
407
  m.nodes.push(nodeInfo);
401
408
  }
409
+
410
+ let plugins = Object.values(moduleConfigs[module].plugins ?? {});
411
+ plugins.forEach((plugin) => {
412
+ let nodeInfo = filterNodeInfo(plugin);
413
+ nodeInfo.version = m.version;
414
+ m.plugins.push(nodeInfo);
415
+ });
416
+
402
417
  return m;
403
418
  } else {
404
419
  return null;
package/lib/subflow.js CHANGED
@@ -88,7 +88,7 @@ function generateSubflowConfig(subflow) {
88
88
  this.credentials['has_' + prop.name] = (this.credentials[prop.name] !== "");
89
89
  } else {
90
90
  switch(prop.type) {
91
- case "str": this[prop.name] = prop.value||""; break;
91
+ case "str": case "conf-type": this[prop.name] = prop.value||""; break;
92
92
  case "bool": this[prop.name] = (typeof prop.value === 'boolean')?prop.value:prop.value === "true" ; break;
93
93
  case "num": this[prop.name] = (typeof prop.value === 'number')?prop.value:Number(prop.value); break;
94
94
  default:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/registry",
3
- "version": "4.0.0-beta.1",
3
+ "version": "4.0.0-beta.3",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./lib/index.js",
6
6
  "repository": {
@@ -16,11 +16,11 @@
16
16
  }
17
17
  ],
18
18
  "dependencies": {
19
- "@node-red/util": "4.0.0-beta.1",
19
+ "@node-red/util": "4.0.0-beta.3",
20
20
  "clone": "2.1.2",
21
21
  "fs-extra": "11.1.1",
22
22
  "semver": "7.5.4",
23
- "tar": "6.1.13",
23
+ "tar": "6.2.1",
24
24
  "uglify-js": "3.17.4"
25
25
  }
26
26
  }