How to chain multiple commands in npm package.json scripts - javascript

I am trying to create a script in my package.json file that will launch my nodemon app, then trigger a gulp sass watch
Currently, I can do this by running a npm launch which starts nodemon, then in a separate terminal window I can run gulp watch to trigger the sass watch from my gulp file.
I would like to create a single script command in package.json that will do both of these- is that possible?
package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js",
"launch": "nodemon app.js && gulp watch"
},
gulpfile.js
const { src, dest, watch } = require("gulp");
const sass = require('gulp-sass')(require('node-sass'));
function generateCSS(cb) {
src('./sass/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(dest('public/css'));
cb();
}
function watchFiles(cb) {
watch('sass/**/**.scss', generateCSS);
}
exports.css = generateCSS;
exports.watch = watchFiles;
edit: please see my answer below for what worked for me, inspired by the answer from #cmgchess

You should be able to use the npm-run-all package and its run-p command to execute multiple scripts side-by side:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js",
"watch": "gulp watch",
"launch": "run-p start watch"
},
Then you can just do:
npm launch

Just use the &&
package.json
"build": "npm run base && npm run utilities:global && npm run utilities:unstyled && npm run utilities:styled && npm run components && npm run merge:unstyled && npm run merge:styled && npm run rtl && npm run prejss && npm run themes && npm run full",

per #cmgchess answer in the comments, it turns out using a double ampersand runs the command sequentially. however, there is also the option to use a single ampersand, which will run them in parallel. In this case, this is what I needed:
"launch": "nodemon app.js & gulp watch"
edit: ok the first time I ran the launch it worked fine. however, subsequent launches crashed. I have it working again now over multiple launches, and what I had to do additionally is switch the order of the commands:
"launchreverse": "gulp watch & nodemon app.js"

Related

Accessing the script of package.json of a npm package from our project package.json file

I created a tool and registered it on npmjs.com named Yattex. It script looks something like this
`
"scripts": {
"clean:reports": "rm -R -f cypress/reports && mkdir cypress/reports && mkdir cypress/reports/mochareports ",
"pretest": "npm run clean:reports",
"scripts": "cypress run",
"combine-reports": "mochawesome-merge cypress/reports/mocha/*.json > cypress/reports/mochareports/report.json",
"generate-report": "marge cypress/reports/mochareports/report.json -f report -o cypress/reports/mochareports -- inline",
"posttest": "npm run combine-reports && npm run generate-report",
"yattex-tool": "node yattex-tool",
"decorator": "node yattex-tool/test-decorators",
"test": "npm run decorator && npm run scripts || npm run posttest || npm run yattex-tool"
},
`
Now, in another project i installed the package and now i dont know what to write in scrips(test) to run the above test command which is in the node_modules/yattex/package.json file
I tried yattex and node node_modules/yattex/package.json
But it doesn't work. I'm a newbie and i cant find any solution...
If you add a property
"workspaces": ["./node_modules/yattex"]
to the package.json file in your other project, then npm test --workspaces will execute the tests both in your other project and in the yattex project (which is a "workspace" as explained on the npm help run page).
If you want to run only the tests for yattex, use npm test --workspace=./node_modules/yattex.

node packge.json scripts - add command to existing script

I'd like to add a command to the "start" script so when I do npm start, first thing that will run is npm install.
My package.json looks as follows:
.
.
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "DEBUG=my-app node src/index.js",
"dev": "nodemon src/index.js"
},
.
.
.
I thought about adding npm install inside the start script:
"start": "npm install DEBUG=my-app node src/index.js",
But this doesn't work so I'd like to get a suggestion, wether if it's even possible..
I think you only use the && conector. like:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "npm install && DEBUG=my-app node src/index.js",
"dev": "nodemon src/index.js"
}
Andy yes, my app should be deployed once with a single command.
This is a quite a heavy/slow start, installing all modules before starting the app.
That means if I change the code somewhwere in my node server, stop the process and run it again, a full install is gonna happen. I realize that you have a dev script with nodemon, but still.
Another case: If your app crashes on the live server and you need to start it up again then a full install will happen. What happens if a module has gone up a patch or a minor version. That means you will start up a project with different dependencies.
If you're doing this in the ci/cd then a pipeline is usually split up:
Install - npm ci
Build/compile - for example if you have typescript (not in your case)
Run all tests
Remove the devDependencies with npm prune
Start up the process
What you would maybe do is have a script called "pipeline" or something, and then call that.
"pipeline": npm ci && npm run build && npm test && npm prune && npm start
This script would then be called in your pipeline code.

How to know on Client in react is env prod or staging

How to know in react app on client, does current env is prod or staging?
On Backend / node js we have process.env.STAGE_NAME
But that now work on client.
This is package.json.
How I get that info on Client?
"scripts": {
"postinstall": "cd ./localDb && sls dynamodb install && cd ../",
"buildServer": "tsc -b ./server/tsconfig.json",
"buildClient": "next build ./client",
"build": "npm run buildServer && npm run buildClient",
"build:dev": "npm run buildServer && NODE_ENV=development npm run buildClient",
"dev": "node --inspect server/build/index.js",
"start": "NODE_ENV=production node server/build/index.js",
"testClient": "nyc --reporter=html --reporter=text mocha --timeout 15000 --reporter mochawesome --exit",
"testServer": "nyc --reporter=html --reporter=text mocha --timeout 15000 --reporter mochawesome --exit server/build/tests/*.js",
"lintServer": "tslint 'server/**/*.ts' --quiet --project server/tsconfig.json",
"lintClient": "eslint '**/*.{js,jsx}' --quiet",
"lint": "npm run lintClient && npm run lintServer",
"format": "prettier --write '**/*.{js,jsx,css,scss,ts}'",
"test": "npm run testClient && NODE_ENV=testing npm run testServer",
"local:db": "cd ./localDb && sls dynamodb start && dynamodb-admin"
},
You can do this,
"scripts": {
"build": "npm run buildServer && npm run buildClient",
"build:dev": "npm run buildServer && NODE_ENV=development npm run buildClient",
"build:stage": "npm run buildServer && NODE_ENV=staging npm run buildClient",
},
Now you can know the environment from process.env.NODE_ENV.
If you have created the app using create-react-app I would recommend using .env file. Check the link for further read, Link
It depends on how did you run the react app and what did you define it in package.json
on depend on your package.json and NODE_ENV= parameter:
Start app for test env : npm test
Start app for prod env : npm start

Using nodemon and --inspect with serverless

I am writing a lambda service and hate having to stop and start the server after every change.
I do have this running together with chrome --inspect working correctly:
"start": "node --inspect-brk $(which serverless) invoke local -f getGoldenDeomondotcom"
I then used:
"start": "nodemon --exec \"node --inspect-brk $(which serverless) invoke local -f getGoldenDeomondotcom\""
to allow me to use nodemon with --inspect, however the messages don't pipe through to chrome.
Any ideas how I could use them together?
Make sure you use js or replace js in the code below with your language ext e.g py,ts
in your package.json
"scripts": {
"start:dev": "nodemon -e js --exec \"sls offline\""
},
From github ... (https://github.com/akupila)
nodemon --exec "serverless serve start"
I'm using this in package.json during dev:
"scripts": {
"start": "nodemon --exec \"serverless serve start\""
}
This allows me to just run npm start. Whenever any file in the project changes nodemon will restart serve.
I'm using serverless-offline and serverless-dynamodb-local, I just added
"start": "nodemon --exec \"sls offline start\"" to scripts

Npm postinstall only on development

I have npm module with following package.json
{
"name": "my-app",
"version": "0.0.0",
"scripts": {
"prepublish": "bower install",
"build": "gulp"
},
"dependencies": {
"express": "~4.0.0",
"body-parser": "~1.0.1"
},
"devDependencies": {
"gulp": "~3.6.0",
"bower": "~1.3.2"
}
}
When I deploy my app to production, I don't want install devDependecies, so, I run npm install --production. But in this case, prepublish script is called, but it doesn't need to, because I use CDN links in production.
How to call postinstall script only after npm install but not after npm install --production?
Newer npm (& Yarn) versions include support for the prepare script that is run after each install run but only in development mode. Also, the prepublish is deprecated. This should be enough:
{
scripts: {
"prepare": "bower install"
}
}
Docs: https://docs.npmjs.com/misc/scripts
I think you cannot choose what scripts are run based on the --production argument. What you can do, however, is supply a script which tests the NODE_ENV variable and only runs bower install if it's not "production".
If you are always in a unix-y environment, you can do it like this:
{
scripts: {
"prepublish": "[ \"$NODE_ENV\" = production ] && exit 0; bower install"
}
}
This only works if you're on a unix-like environment:
NPM sets an environment variable to "true" when install is run with --production. To only run the postinstall script if npm install was not run with --production, use the following code.
"postinstall": "if [ -z \"$npm_config_production\" ]; then node_modules/gulp/bin/gulp.js first-run; fi",
Solution that is less dependent on unix nature of your shell:
"scripts": {
"postinstall": "node -e \"process.env.NODE_ENV != 'production' && process.exit(1)\" || echo do dev stuff"
},
I work with windows, osx and linux so I use a NON environment specific solution to solve this problem:
In the postinstall handler i execute a js script that checks process.env.NODE_ENV variable and does the work.
in my specific case I have to execute a gulp task only in development env:
part of package.json
"scripts": {
"postinstall": "node postinstall"
}
all postinstall.js script
if (process.env.NODE_ENV === 'development') {
const gulp = require('./gulpfile');
gulp.start('taskname');
}
last row of gulpfile.js
module.exports = gulp;
it's important to export gulp from the gulpfile.js because all tasks are in that specific gulp instance.
I have a more general problem - where I want to skip running the postinstall script on local (direct) installs - like when I'm developing the package and run yarn add --dev my-new-dependency.
This is what I came up with. It works with both npm and yarn.
postinstall.js:
const env = process.env;
if (
// if INIT_CWD (yarn/npm install invocation path) and PWD
// are the same, then local (dev) install/add is taking place
env.INIT_CWD === env.PWD ||
// local (dev) yarn install may have been run
// from a project subfolder
env.INIT_CWD.indexOf(env.PWD) === 0
) {
console.info('Skipping `postinstall` script on local installs');
}
else {
// do post-installation things
// ...
}
package.json:
"script": {
"postinstall": "node postinstall.js",
...
Landed here because I had the same issue. Ended up with a solution that tests for the existence of a package under node_modules that I know should only be available in development.
{
"scripts": {
"postinstall": "bash -c '[ -d ./node_modules/#types ] && lerna run prepare || echo No postinstall without type info'"
}
}
This works fine for me conceptually, as the prepare scripts here called by lerna are mainly to ts-to-js compilations.
I'm using if-env module. It's less verbose.
PS: I didn't test it on windows yet.
Install with:
npm i if-env
than in package.json scripts:
"postinstall-production": "echo \"production, skipping...\"",
"postinstall-dev": "echo \"doing dev exclusive stuff\"",
"postinstall": "if-env NODE_ENV=production && npm run postinstall-production || npm run postinstall-dev"

Categories