@node-red/registry 5.0.0-beta.5 → 5.0.0-beta.6

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.
@@ -12,11 +12,13 @@ const log = require("@node-red/util").log;
12
12
  const hooks = require("@node-red/util").hooks;
13
13
  const url = require("url");
14
14
  const { createRequire } = require("module");
15
+ const validateNpmPackageName = require("validate-npm-package-name");
15
16
 
16
17
  const BUILTIN_MODULES = require('module').builtinModules;
17
18
 
18
- // TODO: outsource running npm to a plugin
19
- const NPM_COMMAND = (process.platform === "win32") ? "npm.cmd" : "npm";
19
+ const npmPackageJson = require.resolve('npm/package.json')
20
+ const npmRoot = path.dirname(npmPackageJson);
21
+ const npmCli = path.join(npmRoot, 'bin', 'npm-cli.js');
20
22
 
21
23
  let registeredTypes = {};
22
24
  let subflowTypes = {};
@@ -246,6 +248,11 @@ async function installModule(moduleDetails) {
246
248
  e.code = "install_not_allowed";
247
249
  throw e;
248
250
  }
251
+ if (!validateNpmPackageName(moduleDetails.module).validForOldPackages) {
252
+ const e = new Error("Invalid module name");
253
+ e.code = "install_not_allowed";
254
+ throw e;
255
+ }
249
256
  if (moduleDetails.version) {
250
257
  installSpec = installSpec+"@"+moduleDetails.version;
251
258
  }
@@ -265,9 +272,10 @@ async function installModule(moduleDetails) {
265
272
  // - run install
266
273
  if (result !== false) {
267
274
  let extraArgs = triggerPayload.args || [];
268
- let args = ['install', ...extraArgs, installSpec]
269
- log.trace(NPM_COMMAND + JSON.stringify(args));
270
- return exec.run(NPM_COMMAND, args, { cwd: installDir, shell: true },true)
275
+ let args = [npmCli, 'install', ...extraArgs, '--', installSpec]
276
+ log.trace(`${process.execPath} ${npmCli} ${JSON.stringify(args)}`);
277
+ console.log('HIT EM ONE')
278
+ return exec.run(process.execPath, args, { cwd: installDir },true)
271
279
  } else {
272
280
  log.trace("skipping npm install");
273
281
  }
package/lib/installer.js CHANGED
@@ -29,12 +29,16 @@ const child_process = require('child_process');
29
29
  const plugins = require("./plugins");
30
30
 
31
31
  const isWindows = process.platform === 'win32'
32
- const npmCommand = isWindows ? 'npm.cmd' : 'npm';
32
+
33
+ const npmPackageJson = require.resolve('npm/package.json')
34
+ const npmRoot = path.dirname(npmPackageJson);
35
+ const npmCli = path.join(npmRoot, 'bin', 'npm-cli.js');
36
+
37
+ const validateNpmPackageName = require("validate-npm-package-name");
33
38
 
34
39
  let installerEnabled = false;
35
40
  let settings;
36
41
 
37
- const moduleRe = /^(@[^/@]+?[/])?[^/@]+?$/;
38
42
  const slashRe = isWindows ? /\\|[/]/ : /[/]/;
39
43
  const pkgurlRe = /^(https?|git(|\+https?|\+ssh|\+file)):\/\//;
40
44
  const localtgzRe = /^([a-zA-Z]:|\/).+tgz$/;
@@ -152,8 +156,8 @@ async function installModule(module,version,url) {
152
156
  e.code = "invalid_module_url";
153
157
  throw e;
154
158
  }
155
- } else if (moduleRe.test(module)) {
156
- // Simple module name - assume it can be npm installed
159
+ } else if (validateNpmPackageName(module).validForOldPackages) {
160
+ // A valid npm module name
157
161
  if (version) {
158
162
  installName += "@"+version;
159
163
  }
@@ -169,9 +173,12 @@ async function installModule(module,version,url) {
169
173
  e.code = "invalid_module_name";
170
174
  throw e;
171
175
  }
176
+
172
177
  if (!installAllAllowed) {
173
178
  let installVersion = version;
174
- if (installVersionRestricted && isRegistryPackage) {
179
+ if (isRegistryPackage) {
180
+ // For an registry module, this will validate the version exists before trying to install it
181
+ // It will throw an error if the version doesn't exist.
175
182
  installVersion = await getModuleVersionFromNPM(module, version);
176
183
  }
177
184
 
@@ -228,9 +235,9 @@ async function installModule(module,version,url) {
228
235
  // - run install
229
236
  if (result !== false) {
230
237
  let extraArgs = triggerPayload.args || [];
231
- let args = ['install', ...extraArgs, installName]
232
- log.trace(npmCommand + JSON.stringify(args));
233
- return exec.run(npmCommand,args,{ cwd: installDir, shell: true }, true)
238
+ let args = [npmCli, 'install', ...extraArgs, '--', installName]
239
+ log.trace(`${process.execPath} ${npmCli} ${JSON.stringify(args)}`);
240
+ return exec.run(process.execPath, args, { cwd: installDir }, true)
234
241
  } else {
235
242
  log.trace("skipping npm install");
236
243
  }
@@ -265,7 +272,7 @@ async function installModule(module,version,url) {
265
272
  log.warn("------------------------------------------");
266
273
  e = new Error(log._("server.install.install-failed")+": "+err.toString());
267
274
  if (err.hook === "postInstall") {
268
- return exec.run(npmCommand,["remove",module],{ cwd: installDir, shell: true }, false).finally(() => {
275
+ return exec.run(process.execPath, [npmCli, "remove", module],{ cwd: installDir }, false).finally(() => {
269
276
  throw e;
270
277
  })
271
278
  }
@@ -370,7 +377,7 @@ async function getModuleVersionFromNPM(module, version) {
370
377
 
371
378
 
372
379
  return new Promise((resolve, reject) => {
373
- child_process.execFile(`${npmCommand} info --json ${installName}`, { shell: true },function(err,stdout,stderr) {
380
+ child_process.execFile(process.execPath, [npmCli, 'info', '--json', '--', installName], function(err,stdout,stderr) {
374
381
  try {
375
382
  if (!stdout) {
376
383
  log.warn(log._("server.install.install-failed-not-found",{name:module}));
@@ -381,6 +388,7 @@ async function getModuleVersionFromNPM(module, version) {
381
388
  }
382
389
  const response = JSON.parse(stdout);
383
390
  if (response.error) {
391
+ console.log(response)
384
392
  if (response.error.code === "E404") {
385
393
  log.warn(log._("server.install.install-failed-not-found",{name:module}));
386
394
  e = new Error("Module not found");
@@ -495,9 +503,13 @@ async function getTarballModuleInfo(tarball) {
495
503
  }
496
504
 
497
505
  function uninstallModule(module) {
506
+ // This function is called when the admin api is called to remove a module.
507
+ // A check in node.js#removeModule verifies the module being removed is already in the registry
508
+ // as a user module. As such, we can have confidence that the `module` passed here is
509
+ // a valid and recognised module name.
498
510
  activePromise = activePromise.then(() => {
499
511
  return new Promise((resolve,reject) => {
500
- if (/[\s;]/.test(module)) {
512
+ if (/[.\s;]/.test(module)) {
501
513
  reject(new Error(log._("server.install.invalid")));
502
514
  return;
503
515
  }
@@ -527,9 +539,9 @@ function uninstallModule(module) {
527
539
  // - run uninstall
528
540
  if (result !== false) {
529
541
  let extraArgs = triggerPayload.args || [];
530
- let args = ['remove', ...extraArgs, module]
531
- log.trace(npmCommand + JSON.stringify(args));
532
- return exec.run(npmCommand,args,{ cwd: installDir, shell: true }, true)
542
+ let args = [npmCli, 'remove', ...extraArgs, '--', module]
543
+ log.trace(`${process.execPath} ${npmCli} ${JSON.stringify(args)}`);
544
+ return exec.run(process.execPath, args, { cwd: installDir }, true)
533
545
  } else {
534
546
  log.trace("skipping npm uninstall");
535
547
  }
@@ -596,7 +608,7 @@ async function checkPrereq() {
596
608
  installerEnabled = false;
597
609
  } else {
598
610
  return new Promise(resolve => {
599
- child_process.execFile(`${npmCommand} -v`,{ shell: true },function(err,stdout) {
611
+ child_process.execFile(process.execPath, [npmCli, '-v'], function(err,stdout) {
600
612
  if (err) {
601
613
  log.info(log._("server.palette-editor.npm-not-found"));
602
614
  installerEnabled = false;
package/lib/util.js CHANGED
@@ -128,6 +128,7 @@ function createNodeApi(node) {
128
128
  }
129
129
  return i18n._.apply(null,args);
130
130
  }
131
+ red.nodes.linkcallTargets = runtime.nodes.linkcallTargets;
131
132
  return red;
132
133
  }
133
134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/registry",
3
- "version": "5.0.0-beta.5",
3
+ "version": "5.0.0-beta.6",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./lib/index.js",
6
6
  "repository": {
@@ -16,11 +16,13 @@
16
16
  }
17
17
  ],
18
18
  "dependencies": {
19
- "@node-red/util": "5.0.0-beta.5",
19
+ "@node-red/util": "5.0.0-beta.6",
20
20
  "clone": "2.1.2",
21
21
  "fs-extra": "11.3.0",
22
+ "npm": "11.13.0",
22
23
  "semver": "7.7.4",
23
24
  "tar": "7.5.12",
24
- "uglify-js": "3.19.3"
25
+ "uglify-js": "3.19.3",
26
+ "validate-npm-package-name": "7.0.2"
25
27
  }
26
28
  }