Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio Code - Debug Node JS through TypeScript

I'm currently trying to debug a Node JS application written in TypeScript from Visual Studio Code but I have some issues. I have a situation similar to the one described on this question

|-- .settings
|----- launch.json
|-- bin
|----- app.js
|----- app.js.map
|--src
|----- app.ts
|-- tsconfig.json

Then I have the tsconfig.json file:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "outDir": "bin",
        "rootDir": "src",
        "sourceMap": true
    }
}

The app.ts:

console.log("Hello World!");

The launch.json:

{
    "version": "0.1.0",
    "configurations": [
        {
            "name": "Launch type",
            "type": "node",
            "program": "src/app.ts",
            "stopOnEntry": false,
            "sourceMaps": true,
            "outDir": "bin"
        }
    ]
}

Then I manually compile the project from the command line with

tsc

so I get two files in the bin directory. I set a breakpoint on app.ts and finally run the solution with F5, the application starts and stops at the right line but on the JS file instead the TS one: why???

Am I doing something wrong or trying to achieve the impossible?

Thank you very much for your help! :)

EDIT

I've just shared my project on GitHub in order to make things easier! Take a look if you can! :)

like image 304
Brutus Avatar asked Feb 08 '23 16:02

Brutus


1 Answers

It is absolutely possible.

The most likely reason is that the node.js cannot locate corresponding ts files using generated map.js file. You can try to specify "sourceRoot" in tsconfig.json to point to the root of your project:

sourceRoot: "/Users/SomeUser/projects/test"

Personally I prefer to use gulp for this purpose and in my case it would look like this (note - I do not hardcore sourceRoot path here by using node.js global variable '__dirname'):

var ts = require('gulp-typescript');

gulp.task('build.js.dev', function() 
{
    var tsProject = ts.createProject('tsconfig.json');

    var tsResult = tsProject.src()
        .pipe(sourcemaps.init())   
        .pipe(ts(tsProject));  

    return merge([
        //Write definitions 
        //tsResult.dts.pipe(gulp.dest("bin")),
        //Write compiled js
        tsResult.js.pipe(sourcemaps.write("./", { sourceRoot: __dirname })).pipe(gulp.dest("bin"))]);
});

After that examine the generated map.js file. It should contain something like this lines in the beginning:

"sources":["src/app.ts"]

and in the end:

"sourceRoot":"/Users/SomeUser/projects/test"

When combined together they must point to the valid location of your app.ts file. If not - adjust sourceRoot correspondingly.

[EDIT]

Below are the parts of the project identical to yours (without gulp) - that I can debug on my machine.

launch.json:

{
    // Name of configuration; appears in the launch configuration drop down menu.
    "name": "Launch Server",
    // Type of configuration.
    "type": "node",
    // Workspace relative or absolute path to the program.
    "program": "${workspaceRoot}/src/app.ts",
    // Automatically stop program after launch.
    "stopOnEntry": false,
    // Command line arguments passed to the program.
    "args": [],
    // Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
    "cwd": "${workspaceRoot}",
    // Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
    "runtimeExecutable": null,
    // Optional arguments passed to the runtime executable.
    "runtimeArgs": ["--nolazy"],
    // Environment variables passed to the program.
    "env": {
        "NODE_ENV": "development"
    },
    // Use JavaScript source maps (if they exist).
    "sourceMaps": true,
    // If JavaScript source maps are enabled, the generated code is expected in this directory.
    "outDir": "${workspaceRoot}/bin",
    "request": "launch"
}

tsconfig.json:

{ 
    "compilerOptions": { 
        "emitDecoratorMetadata": true, 
        "experimentalDecorators": true,
        "moduleResolution": "node",
        "module": "commonjs", 
        "target": "es6",
        "sourceMap": true,
        "outDir": "bin",
        "declaration": true,
        "noImplicitAny": true
    },
    "exclude": [
        "node_modules",
        "bin",
        ".vscode",
        "typings/browser.d.ts",
        "typings/browser/**"
    ]
} 

And build task in tasks.json:

{
    "version": "0.1.0",

    // The command is tsc. Assumes that tsc has been installed locally using npm install typescript
    "command": "${workspaceRoot}/node_modules/typescript/bin/tsc",

    // The command is a shell script
    "isShellCommand": true,

    // Show the output window only if unrecognized errors occur.
    "showOutput": "silent",

    // args is the HelloWorld program to compile.
    "args": [],

    // use the standard tsc problem matcher to find compile problems
    // in the output.
    "problemMatcher": "$tsc"
}

[EDIT]

I have done the following minor updates to your git repository to be able to debug it locally.

Add package.json in the root folder, and specify there tsc as dependency (I prefer local installations):

{
  "name": "123",
  "namelower": "123",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
  },
  "devDependencies": {
    "typescript": "latest"
  }
}

then go to your git "stackoverflow" root folder and run in command prompt:

npm install

Change in tasks.json "command" line to:

"command": "${workspaceRoot}/node_modules/typescript/bin/tsc",

After doing these steps and building the project I was able to put a breakpoint in app.ts and VSCode stopped on it upon run (F5)

[UPDATE]

Version of tasks.json compatible with windows:

{
    "version": "0.1.0",
    "command": "tsc",

    "showOutput": "always",

    "windows": {
        "command": "node.exe"
    },

    "args": ["${workspaceRoot}\\node_modules\\typescript\\bin\\tsc.js"],

    "problemMatcher": "$tsc"    
}

Hope this helps.

like image 121
Amid Avatar answered Feb 12 '23 08:02

Amid