Syntax (windows and linux) for multiple commands using Node cross-env - node.js

I'm taking a look at a project that has this line in it's package.json to run Karma tests
"scripts": {
"test": "NODE_ENV=test karma start karma.conf.js",
This doesn't work in Windows when I try "npm test".
I gather this is because this is a *nix syntax. And, in fact, if I change it to
"scripts": {
"test": "set NODE_ENV=test && karma start karma.conf.js",
the tests start when I run npm test.
Looking around, the optimal solution appears to be to use the cross-env package and rewrite it like
"scripts": {
"test": "cross-env NODE_ENV=test && karma start karma.conf.js",
So I get the cross-env will take care of the "set NODE_ENV" part to work on multiple OSes, but it's the "&&" part I'm questioning.
Do I leave the "&&" between the commands when using cross-env? Will that work in windows and linux?

Your cross-env example won't work, it should just be:
"scripts": {
"test": "cross-env NODE_ENV=test karma start karma.conf.js",
without the &&. The command to run comes immediately after you're done setting the variables.
I found your question by searching for how to set multiple variables with cross-env and also how to run multiple scripts/commands with cross-env. So to address the "multiple commands" part of your question:
Given these 2 test scripts:
a.js
console.log('a', process.env.TEST_VAR, process.env.TEST_VAR_2);
b.js
console.log('b', process.env.TEST_VAR, process.env.TEST_VAR_2);
You'll find if you have an && in the script in your package.json the subsequent scripts don't receive the variables. For example:
"scripts": {
"check": "cross-env TEST_VAR=hello TEST_VAR_2=world node a.js && node b.js",
Running npm run check gives:
a hello world
b undefined undefined
You can solve this by having an extra script which runs the multiple commands and running that with cross-env:
"scripts": {
"check": "cross-env TEST_VAR=hello TEST_VAR_2=world npm run check-real",
"check-real": "node a.js && node b.js",
Now npm run check gives:
a hello world
b hello world

Related

Concatenating command line arguments and flags in NPM package.json scripts

I am looking for a way to do something like this:
package.json
[...]
"scripts": {
"test": "cd ./apps/my-awesome-app && npx cypress run",
"test:watch": "npm run test && --headed",
[...]
so then at the command line, running
npm run test:watch
will result in the following commands being executed:
cd ./apps/my-awesome-app
npx cypress run --headed
However, this is not working as expected. Is there a way to achieve this without repeating the whole "test"-string?

`package.json` sequential start script only execute one of the script

I have the following scripts property in package.json:
"scripts": {
"start": "webpack -w && nodemon server.js",
"watch:server": "nodemon server.js",
"watch:build": "webpack -w",
},
When I run npm run start it only starts the webpack -w command but not the nodemon server.js command. I thought having && will run the scripts sequentially but it is definitely not the case for me. I have seen many people chaining execution with && and it works fine.
Why is mine not working?
If webpack -w is not finishing successfully, your second command nodemon server.js won't run. Using a single & should allow the second one to run even if the first one fails.

package.json: what is the difference between & and &&?

Title pretty much says it all, but I'd also like to know if these commands work or behave differently depending upon the OS.
example1:
"scripts": {
"build": "babel -d serverbuild ./server",
"exe": "node ./serverbuild/index.js",
"start": "npm run build && npm run exe"
}
example2:
"scripts": {
"build": "babel -d serverbuild ./server",
"exe": "node ./serverbuild/index.js",
"start": "npm run build & npm run exe"
}
Given these examples portions of a package.json, what would be the difference between npm run start?
When using &&, the first command will run, and if it does not error, the second command will run. It's like a logical AND.
Using &, however, will run a command in the background. So in your second package.json, npm run build will start running in the background and then npm run exe will run as well regardless of what happens to the first command.

'ts-node' is not recognized as an internal or external command, operable program or batch file

I'm getting error in my Vs Code terminal and command prompt that 'ts-node' is not recognized as an internal or external command, operable program or batch file. while i'm trying the start command in the terminal npm run dev and i have added my package.json file also.
{
"name": "tsnode",
"version": "1.0.0",
"description": "ts-node experiment.",
"scripts": {
"dev": "nodemon --exec 'ts-node --cache-directory .tscache' ./server.ts",
"start": "ts-node --fast ./server.ts"
},
"author": "Mugesh",
"license": "ISC",
"dependencies": {
"#types/body-parser": "^1.16.3",
"#types/chalk": "^0.4.31",
"#types/express": "^4.0.35",
"#types/node": "^7.0.18",
"body-parser": "^1.17.1",
"chalk": "^1.1.3",
"express": "^4.15.2",
"nodemon": "^1.11.0",
"ts-node": "^3.0.4",
"typescript": "^2.3.4"
}
}
You need to install ts-node as global
npm install -g ts-node
More information
https://github.com/TypeStrong/ts-node
I wouldn't recommend relying on globally installed ts-node in your own module as some of the answers here suggest.
If you do that then anyone who installs your module would need to install ts-node globally as well (just a usual npm install would not be enough) and then you will have a problem if two modules need things like ts-node globally installed but with different versions etc.
To avoid that, all your dependencies should be defined in your package.json and installed locally in node_modules.
There is a little-known command npx that is used to run binaries from modules that are installed locally in node_modules.
For example, see what happens when I install (locally) ts-node and typescript:
rsp#mn-r:~/node/test/ts-test-1$ npm i ts-node typescript
npm WARN ts-test-1#0.0.0 No description
npm WARN ts-test-1#0.0.0 No repository field.
+ ts-node#6.0.3
+ typescript#2.8.3
added 19 packages from 44 contributors in 2.157s
[+] no known vulnerabilities found [19 packages audited]
and then I try to run ts-node:
rsp#mn-r:~/node/test/ts-test-1$ ts-node -v
-bash: /Users/rsp/opt/node/bin/ts-node: No such file or directory
I can run it with npx:
127!rsp#mn-r:~/node/test/ts-test-1$ npx ts-node -v
ts-node v6.0.3
node v10.1.0
typescript v2.8.3
or I could give the path explicitly:
rsp#mn-r:~/node/test/ts-test-1$ ./node_modules/.bin/ts-node -v
ts-node v6.0.3
node v10.1.0
typescript v2.8.3
In any case, I don't need to install anything globally.
I just encountered a similar issue: on Mac OS --exec ts-node works, on Windows it doesn't.
My workaround is to create a nodemon.json like this:
{
"watch": "src/**/*.ts",
"execMap": {
"ts": "ts-node"
}
}
and change the package.json scripts section to
"scripts": {
"start": "nodemon src/index.ts"
},
The only solution that worked for me:
"start": "nodemon --exec npx ts-node ./index.ts",
I ran into the same problem and found that it works by using double quotes instead of single.
"dev": "nodemon --exec \"ts-node\" --cache-directory .tscache ./server.ts"
P.S. This is 1 year after the problem. Not sure if package versions are a factor. Will confirm if needed.
If you work under Windows you can't use single quote in the json file. That is why you have to replace all single quote symbols(') by the double quote symbols(").
But between two double quotes(") you have to use escaped double quote(").
For the current case you have to change the row in the file package.json:
"dev": "nodemon --exec 'ts-node --cache-directory .tscache' ./server.ts",
into the row:
"dev": "nodemon --exec \"ts-node --cache-directory .tscache\" ./server.ts",
Nodemon is for watching and rerunning node processes when files change. The local ts-node installed in the node_modules directory is not recognized in the scope of the --exec argument. To get around this, some people have recommended installing ts-node globally. As a user pointed out, that's not a good solution because it relies on packages external to your project and makes the ts-node in our node_modules pointless.
Edit:
With newer versions of nodemon, you can simplify this even further (note: you still need ts-node installed as a devDependency).
"start": "nodemon src/index.ts"
Previous:
To fix your solution, prefix ts-node with the npx helper, which will use your local node_module executables.
package.json, inside the scripts block:
"start": "nodemon --watch './src/**/*' -e ts --exec 'npx ts-node src/index.ts'"
An alternative approach could be to use the typescript watcher with the existing node command and the concurrently package.
"start": "concurrently \"tsc --watch\" \"node ./dist/index.js\""
Same principle. One package watches for changes (nodemon & tsc) and restarts the second process (the node/ts-node server).
Edit 11/17/2021:
I returned this post to use it as a reference for setting up a prototype build and found the nodemon approach above was no longer working, it was now throwing the error:
''npx' is not recognized as an internal or external command,
operable program or batch file.
I found a fix was to convert all single quotes to escaped double quotes.
"start": "nodemon --watch \"./src/**/*\" -e ts --exec \"npx ts-node src/index.ts\""
Guess something changed since I my original post. Hope that helps!
For me deleting node_modules and installing it again using npm i was enough.
I had the similar problem, but I have resolved by replacing
"dev": "nodemon --exec 'ts-node --cache-directory .tscache' ./server.ts",
to
"dev": "nodemon --exec ts-node --cache-directory .tscache ./server.ts",
Just remove the single quote(') and install ts-node globally
I had a similar problem while using nodemon:
I had nodemon installed globally, AND ts-node only installed locally.
Solution:
I installed ts-node globally (still keeping the local dependency).
I fixed the issue by removing single quorts around ts-node. as per below
"dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"
updated as
"dev": "nodemon --watch 'src/**/*.ts' --exec ts-node src/index.ts"
please note. my environment is windows 10 and npm version6.14.4
Like suggested in some answers, you should install ts-node locally and not globally. npx makes it easy to use CLI tools and other executables hosted on the registry as explained here. Hence, can be used to run ts-node on your terminal and even scripts from your package.json file. For example;
Take this to be my package.json file
{
...
"scripts": {
"start": "npx nodemon path/to/file"
}
}
Now running npm run start would not give any more issues.
You can try the following command
"dev": "nodemon --watch './**/*.ts' --exec \"ts-node\" src/index.ts"
This worked for me .
If your ts-node isn't working, as an alternative you can do the following:
1) Install nodemon locally --> npm i nodemon
2) In your package.json 'scripts' add the following:
"scripts": {
"start": "nodemon index.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
3) Now run npm start (this will automatically run node for you, but this WILL NOT COMPILE TS )
4) Open a new tab in the terminal/command line, cd the folder your working in and run tsc index.tsc --watch
This will compile your typescript. The only downside is you will just have to have both tabs open, one for running node automatically and the other for compiling automatically, but this works.
I was having the same issue on windows. I found the solution for my issue was resolved when I corrected some misplaced '
Originally:
"scripts": {
"dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
Fixed:
"scripts": {
"dev": "nodemon --watch 'src/**/*.ts' --exec \"ts-node\" src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
The difference in case it isn't clear is that I no longer wrap ts-node in '
* EDIT *
I changed this based on the answer from #RoutesMaps.com above. This solved my problem as well as removing the ' but #RoutesMaps.com actually explains the issue resolution
I ran this command after npm install ts-node.
This fixed my problem:
npm install -D tslib #types/node
yarn add -D ts-node
"scripts": {
"start": "ts-node src/index.ts"
}
'yarn start' now works
Found the answer.
Without installing ts-node globally, just create inside your project nodemon.json file and put it there :
{
"execMap": {
"ts": "node --loader ts-node/esm"
}
}
So now, you can keep type:"module" in your package.json and module:"ESNEXT(or smth that supports ES Modules)" in your tsconfig.json. However, you are going to get constant warning from nodemon that it's, I mean loader type, experimental feature but it's not critical.
In your package.json, in dev command for example just run nodemon path/filename.ts
If you are using a mac these are the steps I came up with in order to fix this in the terminal.
Install globaly and use the returned file path with the symlink ‘ts-node’ and move this file into /usr/local/bin
Install locally without saving to package.json
copy folder in /node_modules into /usr/local/lib/node_modules/
Make sure the file is executable by opening /ts-node/dist and using the command chmod +x bin.js
run npm i in ts-node folder
Make sure that dist folder still exsists, if not copy it back over.
Test running ts-node in terminal, if it does not work it will return an error of which module needs to be moved over to ../
After ts-node runs be sure to delete the folder /usr/local/lib/node_modules/ts-node/node_modules
I was having the same issue. I found the solution for my issue was resolved when i do simply run this command first "npm run build" and than try it nodemon and also add in package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc",
"dev": "ts-node ./lib/server.ts",
"start": "nodemon ./dist/server.js",
"prod": "npm run build && npm run start"}
If you are using code-runner in vs-code then edit setting.json file
"typescript": "tsc $fileName && node $fileNameWithoutExt.js "
Write the the script like this inside your package.json file
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rimraf ./build && tsc",
"start": "node build/index.js",
"tsc": "tsc",
"watch-node": "nodemon build/index.js",
"postinstall": "npm run tsc"
},
Then, npm run build
and finally npm run start
I encountered the same error when trying to run nodemon from a Git Bash but it seems to be working just fine when running nodemon from PowerShell. So, you should consider giving some other terminals a chance.
Me helped this command
npm i -D typescript
More specifically written there https://nodejs.dev/learn/nodejs-with-typescript
Please use TSC --init, instead of TS --init
this error can occur if you have one version of ts-node installed in your project and another version globally.
To solve the problem - install the same version of the package
Just had this same problem and came up with a hybrid solution, using npx to execute but via nodemon config (rather than package.json).
nodemon.json...
{
"watch": ["src"],
"ext": "ts",
"exec": "npx ts-node ./src/server.ts"
}
Actually if you install nodemon as globally then install ts-node also globally. If you install nodemon as -D (dev dependency) then install ts-node as dev dependency. It will work.
A bit late to the party, but my issue was that I had set the NODE_ENV=Production environment variable on my CI. When NODE_ENV is set the dev dependencies(where the ts-node was listed) won't be installed.
Removing NODE_ENV fixed the issue.
I removed it from dev dependencies and added it to dependencies. That solved the problem for my case.

How do I execute typescript watch and running server at the same time?

I was developing my project in nodejs. I found if I need to code and test api, I will run two console, one is to execute typescript watch, another is to execute server.
I think it's so troublesome. I find other developers on github have written scripts in package.json. It's easy to call any commands. It attracts how to write the scripts and simply my development workflow.
In short, the comand of typescript watch is tsc -w and the comand of running server is node app.js. My idea is merge the commands as tsc -w & node app.js but I can't work the two commands at the same time. How do I do? Thanks.
My idea is merge the commands as tsc -w & node app.js but I can't work the two commands at the same time. How do I do
You have a few options. Simplest is to use ts-node-dev : https://github.com/whitecolor/ts-node-dev
Option 1
Step 1
install concurrently, use npm, pnpm or yarn
pnpm i concurrently -D
Step 2
create a script with this command
"scripts": {
"run": "tsc && concurrently \"tsc -w\" \"nodemon dist/app.js\"",
}
Option 2
without install anything (mac or Linux)
"scripts": {
"run": "tsc -w & nodemon dist/app.js",
}
run tsc first so that your directory has something at the time of running node
And with that you will have running your Typescript application 🚀
Another option can be to use nodemon:
tsc -w & nodemon app.js
Since Typescript 3.4 the compilation is faster because you can use the incremental compiler option and they keep improving (including interesting changes for large projects in 3.8).
Update:
I also moved to use concurrently as HerberthObregon says in his answer
TLDR, If you like nodemon this is a straight forward way to get file watch, compilation and execution:
nodemon --ext ts --exec 'tsc && node dist/index.js'
Optionally replace tsc with babel for faster compilation.
Here is a more complete example, in package.json (with source maps):
"scripts": {
"develop": "nodemon --ext ts --exec 'yarn build --incremental && yarn serve'",
"build": "tsc",
"serve": "node --require source-map-support/register dist/index.js",
...
},
Install source-map-support as a dependency if you want, ahem... source map support! Otherwise, remove --require source-map-support/register from the serve script above.
tsconfig.json
{
"compilerOptions": {
...
"sourceMap": true,
"outDir": "dist",
}
}
Building on herberthObregon's answer
Step 1: Install packages
npm install concurrently typescript nodemon --save-dev
Step 2: Create these scripts in package.json
"scripts": {
"build": "tsc",
"build:watch": "tsc -w",
"dev": "npm run build && concurrently \"npm run build:watch\" \"npm run serve:watch\"",
"serve": "node dist/index.js",
"serve:watch": "nodemon dist/index.js"
},
build runs a standard typescript build
build:watch runs typescript build in watch mode
serve serves up your node project (assuming your tsconfig outputs to dest/index/js)
serve:watch uses nodemon to restart the node server whenever the js output changes
dev puts them all together
Just going to throw my hat in here, here's a solution using ts-node-dev and concurrently, similar to the one provided by #HerberthObregon but using ts-node-dev instead of nodemon:
"scripts": {
"start": "npm run build && concurrently \"npm run build:watch\" \"npm run dev\"",
"dev": "tsnd --respawn src/main.ts",
"build": "tsc -p tsconfig.release.json",
"build:watch": "tsc -w -p tsconfig.release.json"
}
Bonus: If you need help with your figuring out tscand your tsconfig.json, I use the sensible defaults from this node typescript starter.
Here's a solution that works for me
1. Install ts-node and nodemon as dev dependencies
2. Create a script : "dev" : "nodemon app.ts"

Resources