VSCode: how to set shell/args for automatically detected npm scripts - node.js

I'm trying to start NPM scripts from VSCode with a custom shell (I want the NPM command to be directly prefixed by wsl.exe --, e.g. wsl.exe -- npm start). I've found a way to make it work but it requires me to set my task type to "shell" and set my shell config like so:
"version": "2.0.0",
"options": {
"shell": { <-- Shell config that I need
"executable": "wsl.exe",
"args": [
"--"
]
},
},
"tasks": [
{
"type": "shell", <-- Sample task I want to execute
"command": "npm start",
"label": "...",
"detail": "...",
},
But VSCode automatic tasks detection ("NPM Scripts" section of the sidebar) uses tasks with the type set as "npm" instead of "shell". This is the config VSCode uses for such automatic tasks:
{
"type": "npm", <-- NPM task that I want, but for which the shell config won't apply
"script": "start",
"problemMatcher": [],
"label": "npm: start",
"detail": "ng serve --proxy-config proxy.conf.json"
}
And this type of tasks do not use the shell config from the first example above (it uses wsl.exe -e <npm command> instead, which can't work in my environment) Is there a way to set a terminal/shell config for this specific kind of tasks?
To reformulate: can I set a shell executable and args for tasks of type "npm" (if so, how?) or I am forced to use tasks of type "shell" and give up on using VSCode automatic tasks detection (which are of the "npm" type)?

Related

Launch config for yarn in VSCode?

I'm trying to add a launch config to VSCode for local debugging. Our command line is
yarn dev (which in package.json is
"dev": "ENV_FILE=./config/.env.dev ts-node -r tsconfig-paths/register ./src/app.ts",
and runs fine)
I've added this launch config in VSCode:
{
"name": "Launch via yarn",
"outFiles": [
"${workspaceFolder}/dist/**/*.js",
"!**/node_modules/**"
],
"runtimeExecutable": "yarn",
"runtimeArgs": ["dev"],
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"type": "node"
},
and it just exits with this in the debug console:
/usr/local/bin/yarn dev
Process exited with code 1
(it also errored out before when I had another process already running, so it couldn't listen on the port. But that's not the case now. And when that was failing, also no real output [while yarn dev correctly told me it couldn't listen on the port])
It's weird that there's no output at all.
I suspect I'm missing something very obvious. (Relatively new to both node and VSCode)

What could be affecting my Node.JS environment that does not allow me to debug my JS with babel-node?

I have a Node JS server written with ES6 features and use Babel to transpile the code for production. The code itself complies and works fine. I am also able to run my "dev" server and test it locally with this command:
npm run dev
which runs this command inside my package.json:
"dev": "nodemon --exec babel-node ./src/server.js"
Pretty standard so far.
I am having issues with debugging my code so I can use breakpoints. Here's the launch script in my VS Code launch.json file:
{
"name": "Debug",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/src/server.js",
"stopOnEntry": false,
"sourceMaps": true,
"args": [],
"preLaunchTask": null,
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
"runtimeArgs": ["--no-lazy"],
"env": {
"NODE_ENV": "development"
},
"skipFiles": [
"${workspaceFolder}/node_modules/**/*.js",
"<node_internals>/**/*.js"
]
}
And my .babelrc file:
{
"presets": [
[
"#babel/env",
{
"targets": {
"node": "current"
}
}
]
],
"env": {
"development": {
"sourceMaps": "inline",
"retainLines": true
}
},
"comments": true,
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-object-rest-spread"
]
}
When I try to enter debug mode I get this execption thrown right away:
Exception has occurred: Error: Cannot find module 'kexec'
Require stack:
- F:\Dev\Web Development\****\dev\server\node_modules\#babel\node\lib\babel-node.js
- F:\Dev\Web Development\****\dev\server\node_modules\#babel\node\bin\babel-node.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:956:15)
at Function.Module._load (node:internal/modules/cjs/loader:804:27)
at Module.require (node:internal/modules/cjs/loader:1028:19)
at require (node:internal/modules/cjs/helpers:102:18)
at F:\Dev\Web Development\****\dev\server\node_modules\#babel\node\lib\babel-node.js:65:68
at processTicksAndRejections (node:internal/process/task_queues:96:5)
This is where is gets really odd. I pulled the same sourcecode to my laptop and debugging worked just fine. I also spun up a sandbox virtual machine on my Windows 10, did a clean install of Node + VS Code on it, and it worked perfectly there too.
There's something in my current environment that is causing this issue and I cannot figure it out. I've been trying to solve this issue for a few days now with no success.
Here are the steps I have already taken:
Upgrade and downgrade versions of Node + NPM and retry using
different versions
Delete node_modules and reinstall with "npm install" (and using npm ci)
Completely uninstall Node and do a fresh install
Removed user and system environemnt variables before the fresh install
Manually delete all NPM caches from %AppData% folder
I also want to point out that when I used a different launch script that is attached to a process ID, I was able to debug the code, but I am trying to streamline this process instead of having to choose the process each time.
This method does work:
npm run dev to start the dev server, which runs this code:
"dev": "nodemon --exec babel-node ./src/server.js"
I then run the debugger and attach it to the running process. Here's the launch script for that:
{
"name": "Attach by Process ID",
"processId": "${command:PickProcess}",
"request": "attach",
"skipFiles": ["<node_internals>/**"],
"type": "node"
}
If kexec is used by Babel, isn't it already supposed to be installed as a dependecy? I couldn't find it anywhere in my modules folder though.
I also tried installing kexec separately but was receiving a lot of node-gyp errors which I tried fixing by reinstalling all of Node build tools using multiple different methods. None of these actions also fixed the issue.
Any ideas or support would tremendously help at this point.

Debugging in VSCode with a npm script

In my package.json I have some scripts defined that look like this:
"scripts": {
"build": "tsc -p tsconfig.json",
"run": "node --experimental-specifier-resolution=node .",
"start": "npm run build && npm run run"
}
For now I just used npm run start from the terminal to compile and run everything but I want to use breakpoints now and would like to switch to the VSCode debugging.
I don't know what the launch.json configuration should look like to run scripts.
My project structure looks something like this:
.
├── package.json
├── src/
│ └── start.ts
└── dist/
└── start.js
What I think my best attempt so far was:
{
"name": "Launch via NPM",
"request": "launch",
"type": "node",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"start"
],
},
Which sadly gives me the following error:
Exception has occurred: Error: ENOENT: no such file or directory, stat '{cwd}\git.COM'
Replacing "runtimeArgs": ["run","start"], with "command": "npm run start", gives me the same error.
Using a NPM script
You could create an additional script in your package.json to launch node with the instruction to wait for a debugger to be attached. IMHO, this is not ideal and I would avoid it but it's sometimes necessary (for example when node is launched by some shell script):
"scripts": {
"debug": "npm run build && node --experimental-specifier-resolution=node --inspect-brk ."
}
Then you would need a configuration in your launch.json to attach the debugger to the waiting node process:
{
"name": "Attach",
"type": "node",
"request": "attach",
"skipFiles": ["<node_internals>/**"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
Launching node directly
Another possibility is to launch node in your launch.json with the appropriate arguments. There is a little code duplication with your package.json but that's how I do it myself.
Note that if you want to debug directly your TS files, you have to generate the source maps and indicate the location of the generated JS files.
Here is how it would look like:
{
"name": "Debug",
"type": "node",
"request": "launch",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/src/start.ts",
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"runtimeArgs": [
"--experimental-specifier-resolution=node"
]
}
To ensure your TS code is built, I would run TSC in watch mode in another terminal window:
tsc -p tsconfig.json --watch

VSCode Task to run various node commands

I have a monorepo where I wish to create a script for starting up a specific project locally.
The project is completely Node.js based.
For me to set up this project locally for development, I need to run the following commands in this order:
Start up the docker images
cd docker/dockerForTests
docker-compose up -d
Start up the Web Auth server
cd src/project/webAuthentication
setenvs projectAuthentication && npm start
Start up the API
cd src/project/api
setenvs projectAPI && npm start
Start up the web client
cd src/project/web
setenvs projectWeb && npm start
I usually start each section up in a new terminal window, within VSCode, for ease of use.
To automate this process, I found out about VSCode Tasks.
Although it appears they are designed for 'building' or 'watching' tasks, I thought that I could modify the behavior to run the above commands for me.
Here was my attempt:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"runner": "terminal",
"version": "2.0.0",
"tasks": [
{
"label": "Start Docker",
"dependsOrder": "sequence",
"type": "shell",
"command": "cd docker/dockerForTests && docker-compose up -d",
},
{
"label": "Start Web Auth",
"dependsOrder": "sequence",
"type": "process",
"command": "cd src/project/webAuthentication && setenvs projectAuthentiction && npm start"
},
{
"label": "Start Up Local Development Environment",
"presentation": {
"echo": true,
"reveal": "always",
"focus": true,
"panel": "new",
"showReuseMessage": false,
"clear": true
},
"dependsOn": [
"Start Docker",
"Start Web Auth"
],
"problemMatcher": []
}
]
}
The first command works fine, but I wanted it to be like the integrated terminal, where it hangs for input once the command has finished running.
Secondly, the second task does not work as it's not a Node command.
I would like it to work like the regular, bash input.
How can I automate my above workflow? Is it even possible?
At least for points 2, 3 and 4 concurrently works fine, and it should work fine for point 1 as well. With following scripts in scripts section of package.json in your root directory you should be able to launch your dev env with just one command
"start-docker": "cd docker/dockerForTests && docker-compose up -d",
"start-auth": "cd src/project/webAuthentication && setenvs projectAuthentication && npm start",
"start-api": "cd src/project/api && setenvs projectAPI && npm start",
"start-client": "cd src/project/web && setenvs projectWeb && npm start",
"start-dev": "concurrently \"npm run start-docker\" \"npm run start-auth\" \"npm run start-api\" \"npm run start-client\""
This doesn't use VSCode task, but would simplify your life anyway.
You should be able to add the necessary scripts to the root package.json's scripts section. Once you do that, you should see them as VS Code tasks, thanks to VS Code's automatic task detection.
See https://code.visualstudio.com/docs/editor/tasks#_task-autodetection for details.

Visual Code Run Build Task npm

I'm using Visual Studio Code 1.13.0 on Windows 10.
I have the following build script in my package.json:
{
//omitted other props
"scripts": {
"build": "webpack"
}
}
I've installed webpack with npm install --global webpack, so it's installed globally.
The webpack.config.js is irrelevant for my question.
When I run npm run build in the terminal, everything works fine. But when I run the Visual Code Tasks: Run Build Task (ctrl+shift+b or ctrl+shift+p > Run Build Task), then I'm getting the following message in the output window:
'"npm run build"' is not recognized as an internal or external
command, operable program or batch file.
Why? (using npm version: 3.10.10)
You should create tasks.json file and specify build task with npm task runner as described here ctrl+shift+p > Configure Task Runner. In your case task.json file should looks something like that
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"command": "npm",
"isShellCommand": true,
"showOutput": "always",
"suppressTaskName": true,
"tasks": [
{
"isBuildCommand": true,
"taskName": "build",
"args": ["run", "build"]
}
]
}
tasks.json can be used for running multiple different tasks. This is #oleg-m's answer updated for version 2 of tasks.json:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type":"npm",
"script": "build",
"group": "build"
}
]
}

Resources