Correct way to use yarn/npm from node script - node.js

Inside my script I want to use some functionality from yarn/npm
Like get results of yarn info packageName. I could spawn command and get output, but I believe there should be more correct way to do that.
Can't find any documentation about usage of yarn as package. Any ideas?

NPM and Yarn were designed as CLI tools. It's possible to load them with require but since executable script does a lot of work on options processing, this isn't practical.
The most straightforward and predictable way is to run them with child_process spawn or exec. There are npm-programmatic and yarn-programmatic third-party packages that do this internally. Since their APIs don't necessarily cover 100% of CLI functionality, it may still be beneficial to run commands directly.
There are open issues for NPM and Yarn regarding programmatic use.

Related

Is there a way to use custom arguments for npm install when deploying in Clever Clouds?

I'm working on a NextJS application which is deployed through Clever Clouds.
One of the newer dependency require the argument --legacy-peer-deps to be passed with npm install.
When deploying to Clever Cloud, the log only shows the command npm install --no-progress, and then fail because of this dependency.
I have tried putting the command in custom environment variable : CC_NODE_BUILD_TOOL or CC_CUSTOM_BUILD_TOOL but the deployment fail the same way.
I have tried putting it in the scripts.install, but this cause the install to recursively call itself each time it is finished.
Is there really no way to circumvent this ? Is there a way to pass the "strict-peer-deps" of npm to false ?
You can use a HOOK to run this command after the automatic install step, you can find the list of available hooks here: https://www.clever-cloud.com/doc/develop/build-hooks/.
I advise you to use the CC_POST_BUILD_HOOK environment variable to do this.

What happens under the hood when you call `npm run` to run a NPM script?

I would like to know more about how NPM scripts work.
For example:
package.json
"scripts": {
"build": "set NODE_ENV=production&& webpack --config webpack.config.js",
}
When I execute npm run build:
What happens? I know a Node process will be initiated somewhere and webpack binary file will be called, right? But what are the steps before that? Does that depend whether I'm on Windows, Linux, PowerShell or Git bash? How does that process relate to the OS and the CMD/CLI that is being used?
The npm source code helpfully has the whole run-script functionality separated into its own module and repository so you can review the source code if the documentation does not answer your questions.
Speaking of your questions:
I know a Node process will be initiated somewhere and webpack binary file will be called, right?
The webpack executable will be run. And since webpack is a Node.js script, it will be run with node.
If, however, your "build" value consisted of shell/CLI commands, those commands would be run. Node.js is not necessarily invoked.
But what are the steps before that?
The "steps before that" include certain lifecycle scripts that might also be defined. In particular, if there is a "prebuild" script, it will run before the "build" script.
Does that depend whether I'm on Windows, Linux, PowerShell or Git bash? How does that process relate to the OS and the CMD/CLI that is being used?
npm (and node) make efforts to make Windows and Linux experiences comparable. Differences occur for sure, but without more details, I'm not sure I'd want to speculate about what specifics might be of interest to you beyond that.
Powershell and GitBash: Again, npm will make efforts to smooth out differences, but I'm sure they come up. One thing to be aware of is that your PATH (and other environment variables) might be set differently and that may affect behavior. (It may especially impact which version of node gets executed, if you have more than one version installed.)
I am not a Windows expert, but I have seen a lot of npm scripts that assume a UNIX-like environment. So, if given the choice and all else being equal (which it never is), a bash-like environment is probably going to be a bit smoother.
The answer I was looking for was something like this:
When you call npm run, npm will initiate a shell to run those instructions.
And which shell npm will use is defined in your npm settings.
You can see your npm config by running:
>>> npm config ls
In the example above, npm will run the script on git-bash.
You can change the npm shell by calling:
npm config set script-shell "C:\\Program Files\\git\\bin\\bash.exe"

Can I assume `node` is always in the $PATH setup by NPM?

So I have have been using NPM as a simple build tool for a few years where I can assume that every CLI tool installed through package.json is available in the PATH, as NPM adds the ./node_modules/.bin path to it.
But as I was about to write a small Node script to do some house cleanup chores I got a bit wary if NPM actually has the node executable in the PATH it gives to users. This might seems stupid, as all the scripts in ./node_modules/.bin rely on node being there for the wrapper scripts on Unix to be able to find it, but I thought there might be some magic going on in Windows. Perhaps they use some other magic of their own. Or something. Does not matter, really, I just want to be able to assert:
Is the node executable always on the PATH given to npm scripts by NPM? On all platforms? And is it always the same Node as NPM runs on?
This might seem too basic to almost be asked, but better safe than sorry.
Note: not a definitive answer, but too lengthy for a comment
If you look at the documentation on default values that are set up for scripts:
npm will default some script values based on package contents.
"start": "node server.js":
If there is a server.js file in the root of your package, then npm
will default the start command to node server.js.
Although this isn't a definitive answer to your question, npm uses node as a default in case there's no npm start defined. This is a clear indicator npm relies on node to be present under all circumstances.
On Windows, you can safely make the assumption that npm requires node to be in the PATH, or in the same folder as npm. This is from npm.cmd (the script that is called when you type npm):
SET "NODE_EXE=%~dp0\node.exe"
IF NOT EXIST "%NODE_EXE%" (
SET "NODE_EXE=node"
)

Starting Meteor dev from NPM scripts causes CPU spike

Picking up on a suggestion I read, I thought I would try starting my Meteor processes in dev mode from npm scripts in package.json files, since I have some verbose startup settings. I'm aware that I can use a bash script or the like but npm run whatever seemed like a nice clean solution.
Unfortunately doing this causes huge CPU spikes that render my system unusable. For example, running meteor -p 6001 and meteor -p 7001 yields two node processes utilizing 0.3% CPU each. But running npm run appA and npm run appB where the scripts point to the same commands above yields a first node process utilizing over 70% of CPU, and a second process over 100%.
Apparently this is not doing what I thought it was doing. It's not mission-critical but I'd love to learn what's going on under the hood or, even better, a fix. I'm running node version 5.4.1 and Meteor version 1.2.1 (which utilizes node version 0.10.40).
Can someone explain what's causing this?
Exactly same thing happened here, glad to find out that this is because of npm script, I was thinking that I'm due to deep profiling my app to find what's wrong.
Would love an explanation and a fix too.

how can I debug a node app that is started via the command line (cli) like forever or supervisor?

I'm familiar with debugging my own node apps (usually with node-inspector). Today I'd like to debug someone else's program. I'm trying to track down an issue with supervisor. So naturally I just add a --debug (or debug-brk) to the command call, but it passes that to the code that it is supervising.
I've tried adding debugger lines to the js file for supervisor but that didn't work (probably because no debugger was attached at that time). There's a bit of a race here -- I need to start the debugger and attach it to the supervisor process after it starts but before it processes its arguments from the command line.
What I really want to do here is stop supervisor and debug it before it processes its command line arguments. How can I do this?
I had the same problem while developing my hexo blog. The documentation isn't all that complete yet so I find myself needing to reverse engineer at times.
The basic idea is that in Node.js even your cli apps are simply normal node apps that you are exposing to the OS command line interface. On Unix systems you are using this line:
#!/usr/bin/env node
To allow the environment to execute the script.
Many cli based node apps try to insist that you install them globally with the -g option.
npm install -g node-inspector
I personally prefer to have as much control of my development environment as I can get, so I prefer to break some conventions and check my node_modules in to source control along with installing everything I can locally by dropping the -g.
npm install node-inspector
Now you don't have to do this in order to make this work, I'm just describing this setup because it relates to your question. When I run node-inspector I can't simply use:
node-inspector
Instead I must explicitly invoke it from within my project. I do this by executing the symlink in my node_modules/.bin folder:
node_modules/.bin/node-inspector
Now I'm running node-inspector just like you.
Next all I need to do is start the cli process in debug and optionally pass params to it:
node --debug-brk node_modules/.bin/hexo generate
Note I am explicitly calling the symlink here and not simply:
node --debug-brk hexo generate
If I tried the line above I would get an error: "Error: Cannot find module".
I hope this helps.

Resources