How to pass a JSON string as argument in a package.json script entry? - node.js

For a Puppeteer test I want to execute UI tests with a package.json script:
"scripts": {
"test:ui": "cucumber-js --require-module ts-node/register --require test/step_definitions/**/*.ts --require test/support/**/*.ts --world-parameters {\"instanceUrl\":\"https://testserver.example.com\"}",
},
The --world-parameters argument should be passed as JSON. How do I escape the " characters?

So I've read they need to be escaped twice.
--world-parameters {\\\"instanceUrl\\\": \\\"https:\\\/\\\/testserver.example.com\\\"}
https://github.com/cucumber/cucumber-js/issues/1045

Related

-print printing out string via npm but actually evaluating through powershell

The following script is defined in my package.json:
"abc": "node -p 'p=require(\"./package\");p.main=\"lib\";p.scripts=p.devDependencies=undefined;JSON.stringify(p,null,2)'",
If I run 'npm run-script abc' I end up with a package.json with the string
'p=require(\"./package\");p.main=\"lib\";p.scripts=p.devDependencies=undefined;JSON.stringify(p,null,2)'
If I run the command:
node -p 'p=require(\"./package\");p.main=\"lib\";p.scripts=p.devDependencies=undefined;JSON.stringify(p,null,2)'
Directly in powershell I actually get the json output I'm looking for.
Not sure why the difference? I tried using -e/-eval as well to no avail, it seems to think that it just prints out the script?
Change your npm script to the following instead:
"abc": "node -p \"p=require('./package');p.main='lib';p.scripts=p.devDependencies=undefined;JSON.stringify(p,null,2)\"",
Your npm script will now run succesfully via Powershell, Command Prompt (cmd.exe), Linux, and MacOS.
Changes are as follows:
The node/js code has been wrapped in JSON escaped double quotes \"...\" instead of single quotes.
The actual node/js code itself utilizes single quotes '...' instead of JSON escaped double quotes \"...\" because using escaped double quotes in JavaScript is invalid syntax.
"abc": "node -p \"p=require('./package');p.main='lib';p.scripts=p.devDependencies=undefined;JSON.stringify(p,null,2)\"",
^^ ^ ^ ^ ^ ^^
It's a quoting issue.
The problem is that running npm run-script abc is not interpreted in powershell (which properly supports both single and double quotes), but in cmd.
You can either:
Replace single quotes with double quotes, and use proper escaping (although the result may be a bit ugly):
"abc": "node -p \"p=require(\\\"./package\\\");p.main=\\\"lib\\\";p.scripts=p.devDependencies=undefined;JSON.stringify(p,null,2)\""
Use single quotes inside the javascript code and double qoutes to surround the script
"abc": "node -p \"p=require('./package');p.main='lib';p.scripts=p.devDependencies=undefined;JSON.stringify(p,null,2)\""

Why does npm start ignore escaped backticks from argument?

I have a super simple index.js file that outputs the first argument it receives:
// Args 0 & 1 are /usr/bin/node and path to file
console.log(process.argv[2]);
When I run the following:
node index.js test``backticks
the output is testbackticks, and as expected, the backticks are ignored.
Calling this again, with escaping this time:
node index.js test\`\`backticks
the output is test``backticks.
My package.json has a start script like so:
"start": "node ./index.js"
Calling npm start -- test``backticks will result in them being ignored, just like with the node.js call.
However, calling this with escaping:
npm start -- test\`\`backticks
Also results in the same output, which is simply:
testbackticks
With the backticks ignored as well.
Escaping npm start with double or single quotes worked fine, it is just the backticks that are ignored.
Why does calling npm start and node produces different results and how come backticks can't be escaped in npm start ?
Lastly, how can I, if possible, pass a string with backticks as an argument to npm start ?

Get stdout from NPM Script into a variable

I have this node script that parse a .YAML and output a field named version
node node/getAssetsVersion.js
=> "2.1.2"
I'm trying to get that stdout into a varible and use it in a NPM Script
This is what I'm trying to do in my package.json:
"scripts": {
"build": "cross-env VERSION=\"$(node node/getAssetsVersion.js)\" \"node-sass --include-path scss src/main.scss dist/$VERSION/main.css\""
}
Thanks!
Instead of this:
VERSION=\"$(node node/getAssetsVersion.js)\"
you may need to use:
VERSION=\"$(node node/getAssetsVersion.js | cut -d'\"' -f2)\"
if the output of your program is this as you wrote in the question:
=> "2.1.2"
If it's just this:
"2.1.2"
then the above will still work but you can use a simpler command:
VERSION=$(node node/getAssetsVersion.js)
with no quotes.
But in the later part the $VERSION will likely not get substituted as you expect.
Since you tagged you question with bash I would recommend writing a Bash script:
#!/bin/bash
VERSION=$(node node/getAssetsVersion.js | cut -d'\"' -f2)
node-sass --include-path scss src/main.scss dist/$VERSION/main.css
or:
#!/bin/bash
VERSION=$(node node/getAssetsVersion.js)
node-sass --include-path scss src/main.scss dist/$VERSION/main.css
depending on what is the output of getAssetsVersion.js and put this in package.json:
"scripts": {
"build": "bash your-bash-script-name"
}
I would avoid any quotes that are escaped more than once.

Colored logging in terminal with NPM run script

I'm trying to setup a project exclusively with NPM as a build system (no Gulp or Grunt) so I'm a bit of a beginner, but so far it's working pretty nicely except for this little road block.
The scripts section of my package.json looks something like that :
"scripts": {
"clean:task": "rimraf dist/*",
"clean:notify": "notify --t 'Cleaning done.' --m 'dist/ has been cleaned successfully.",
"clean": "npm run clean:task -s && npm run clean:notify -s",
"serve": "browser-sync start --p 'xxx.dev/app' --host 'xxx.dev' --port '3000' --open 'external' --f 'app'",
"styles:task": "node-sass --output-style nested -o app/assets/css app/assets/css",
"styles:notify": "notify --t 'Styles compilation' --m 'Styles have been compiled successfully'",
"styles:build": "npm run styles:task && npm run autoprefixer",
"imagemin": "imagemin app/assets/img dist/img -p",
"scripts:lint": "jshint --reporter=node_modules/jshint-stylish app/assets/js/scripts.js"
}
I have notifications to announce successful tasks, but ideally I'd like some nice colored messages directly in the terminal. I know this can be done with Gulp via colored logging but I can't fin any NPM package that has a CLI that would be able to do that.
Any ideas ? Is it even possible ?
Thanks for your help.
Individual scripts defined in package.json can output a message to Mac's Terminal in color by following a syntax that boils down to echo + ANSI color reference + some text although you can get more complicated than this, as well.
Step 1: Define your scripts
"scripts": {
"greeting": "echo \"\\033[32mHello World\"",
"notification": "echo \"\\033[33mThe Server Has Started\"",
"timestamp": "echo \"\\033[31m--------\";date \"+%H:%M:%S\n--------\n\" && echo \"\\033[00m\""
{
Step 2: Run your scripts
npm run greeting
npm run notification
npm run timestamp
Some things to note
Escaping is inherently a part of this. A comment by James Lim on StackOverflow mentions the use of -e which apparently ensures that echo honors escaping slashes. I found this was necessary when running the command directly in Terminal but unnecessary when firing it as part of npm run <script>.
The ANSI code that sets the color is made up of eight characters that always begin with a backslash, like this \033[32m. Also, notice that the text I am outputting in my scripts above begins immediately after the last character in the ANSI code– this is so the message will be flush left in the Terminal.
In the timestamp script above, the semicolon separates the echo and date commands but maintains the same color we set at the beginning. In fact, this color will affect everything defined in this script and, in my case, even changed the color of a message output by a separate script that immediately followed this one. For this reason, I included another echo that simply resets the color to the Terminal's default color (in this case, black).
For reference, I could have used && in place of the semicolon and achieved the same results. If you do not already know the difference between these two operators, see this post.

sh: syntax error near unexpected token `}'

I feel like a real moron posting a syntax error question but I really don't know how to fix this one
I'm trying to setup a build process in my node package.json file with the following script
"scripts": {
"build": "NODE_ENV=production { echo '// mypkg-x.y.z'; browserify -r ./client/main.js:mypkg | uglifyjs -cm; } > dist/mypkg.min.js"
}
which runs the following in sh
NODE_ENV=production { echo '// mypkg-0.0.0'; browserify -r ./client/main.js:mypkg | uglifyjs -cm; } > dist/mypkg.min.js
sh error outupt
sh: -c: line 0: syntax error near unexpected token `}'
When I run the command in bash it works just fine, but nodejs uses sh :{
End Goal
I am browserifying some javascript code and I want to prefix the bundled output with the package's name/version
// mypkg-x.y.z
<bundle output here>
Add a semicolon after you set NODE_ENV:
"build": "NODE_ENV=production; { echo '// mypkg-x.y.z'; browserify -r ./client/main.js:mypkg | uglifyjs -cm; } > dist/mypkg.min.js"
#Ray's answer worked great, I just wanted to post an alternate solution to the same problem
// this works too !
{ echo '// mypkg-0.0.0'; NODE_ENV=production browserify -r ./client/main.js:mypkg | uglifyjs -cm; } > dist/mypkg.min.js
To highlight the difference, all I did was move the NODE_ENV=production bit to just before the browserify bit. In this case, no semicolon is needed.
This is actually a little specific to my use case too, as the environment variable is only needed for that part of the build process.

Resources