node.script query for installed packages

Vincent Goudard's icon

Hi,

is there a way to query node.script for installed NPM packages?

I tried to send the command `script npm ls -g` following this post on SO, but this does not seem to work.

Does anyone know how to do that simply (that is, preferably, without parsing node_modules folder files manually) ?

Florian Demmer's icon

Is there a specific need to query globally installed packages? My hunch is that the command failed due to a permission issue given the -g flag?

Vincent Goudard's icon

Hi Florian,

actually I am rather after local packages, though I guess it could be useful to have a way to query global ones too.

Are you saying that the command script npm ls should work ?

I don't see that here, but I may be missing something ... all I have when I send this message is a dict like this:

{
	"args" : [ "ls", "--scripts-prepend-node-path=true" ],
	"status" : "completed"
}
Max Patch
Copy patch and select New From Clipboard in Max.

Florian Demmer's icon

Hi Vincent,

yeah ok I get it. I assumed you were having issues with the -g which would fails bc the Node / NPM binaries do not have the permissions to access the globally installed packages, but as your patch shows, locally this works just fine.

I guess your FR is that npm commands somehow output stdout and stderr, which is currently not exposed to the patch. I'll file that as a FR.

In the meantime - you could write a tiny wrapper script that uses child_process and sets up the necessary communication via max-api into your patch. Should work but depending on what you are trying to achieve it might be overkill? Do you just want to check if a certain package is installed or perform more complex tasks on the dependency tree returned by npm?

Vincent Goudard's icon

Hi Florian,

Thanks, yes indeed, I wished the npm output would be exposed to the patch.

The general idea is to check for required packages and to run npm installonly if necessary on a patcher startup. Ideally, this would include package version checking.

Is there any easier way that I am missing for this purpose?

Florian Demmer's icon

Hi Vincent,

ok makes sense. Would it make sense for you to include that as part of your script, rather than a separate npm task?

If so there are a few options.

  1. You can just try to require or import the package and wrap it with a try/catch however, that won't give you any version information

  2. run npm ls from within your script using child_process which allows you to capture, process the output and decide within the scope of your script what to do.

For the second you could do something like the following. Code is synchronous but can be adapted for async execution:

const { execSync } = require("child_process");

try {
  execSync("npm ls --json", { cwd: __dirname, stdio: ["ignore", "pipe", "ignore"] });
  // npm ls exited with a 0 exit code - should be all ok
} catch (err) {

  // NPM failed with a non-zero exit code - err.status
  // Given the --json flag the stdout of the error is in JSON format
  const output = JSON.parse(err.stdout.toString("utf-8").trim());

  // More info on the output is present in
  // output.problems, which is an array of strings describing the issues
  // output.error.summary which is a summary text of the issues present

  console.error(output.error.summary);
}

As an aside - isnpm ci might be a better match for your requirements where you'd like to ensure that the content of node_modules matches and satisfies what's in the package-lock.json ?