VS Code Run extension - no output shown from running program - node.js

Recently I have tried Deno and since it has native TypeScript support, I thought it would be neat to use it as a "typescript runner". For example in Node you would write node server.js and in Deno would be like deno run -A server.ts and all of this in the code runner extension.
In vscode settings.json :
"code-runner.executorMap": {
"javascript": "node",
"typescript": "cd $dir && deno run -A $fileName"
}
Consider the following ts file "index.ts" :
const add = (a: number,b: number):number =>{
console.log(a+b);
return a+b;
}
add(1,2);
Output when running using the extension :
[Running] deno run -A index.ts
[33m3[39m
[Done] exited with code=0 in 0.082 seconds
Output when using the terminal cmd/powershell :
C:\Users\Oliver\Desktop\DenoPJ>deno run -A index.ts
3
Any thoughts about why it works inside the terminal and not inside the extension ?

I tried and could reproduce the problem.
When you change the settings under "Run Code configuration" to "Run in Terminal"
and then run the code again with AltCtrlN,
VSCode will switch to the Terminal window and you should see:
PS C:\Users\jps\source\deno> cd "c:\Users\jps\source\deno\" ; if ($?) { deno run -A index.ts }
3

Try to add flags to command (depends on your actions of application):
deno run --allow-net --allow-read --allow-write --allow-env index.ts

Related

ES6 import module inside node execution script

I'm trying to execute a node script inside package.json which looks like this.
"parse-xlsx": "node ./services/orders-parsing/xlsx-parser executeXlsxParsing ./private/testdata/$FILENAME"
So when I run FILENAME=unfried-xlsx-2.xlsx npm run parse-xlsx for exemple, it executes this:
import XlsxParser from "./executeExcelParsing";
const executeXlsxParsing = () => {
const xlsxParser = new XlsxParser({ fileName: process.argv.slice(2)[1] })
xlsxParser.executeParsing()
}
export default executeXlsxParsing;
But when I do so, I got this error
SyntaxError: Cannot use import statement outside a module
I did try to flag with --input-type but did not work and it outputs the same error than the one above:
"parse-xlsx": "node --input-type=module ./services/orders-parsing/xlsx-parser executeXlsxParsing ./private/testdata/$FILENAME"
For some reason I don't want to use type=module inside my package.json file.
Any workaround to be able to "force" the execution of this script with ES6 imports ?
Did try with latest LTS node 16.17.0 and my "old" version v12.22.1.
Thanks !
node --input-type only tells node how to parse string input you're passing it:
> node --help
Usage: node [options] [ script.js ] [arguments]
node inspect [options] [ script.js | host:port ] [arguments]
Options:
...
--input-type=... set module type for string input
...
However, you're telling it to run the file ./services/orders-parsing/xlsx-parser so that won't work.
Your only option (until Node changes how --input-type works) is to have a package.json with the type property set to module. Thankfully, you canhave lots of package.json files, and node will simply use the one closest to the file it's being asked to run, so you can add a minimal package.json inside your services/orders-parsing dir, and then make sure that's set to "type": "module", and now Node will run in ESM mode when asked to run files in the services/orders-parsing dir.
However, also note that if you want to pass arguments to xlsx-parser, you will need to use:
"parse-xlsx": "node ./services/orders-parsing/xlsx-parser -- executeXlsxParsing ./private/testdata/$FILENAME"
with those explicit -- in there, because:
> node --help
Usage: node [options] [ script.js ] [arguments]
node inspect [options] [ script.js | host:port ] [arguments]
Options:
- script read from stdin (default if no file name is
provided, interactive mode if a tty)
-- indicate the end of node options
If you don't add those -- then everything is considered options for the node executable instead of for whatever script you're running.

$(pwd) doesn't resolve properly when running from npm script

The issue:
$(pdw) does not resolve properly when running as part of npm script.
running a script with param including $(pwd) in the terminal seems to be working fine though. e.g.:
Simplified example:
package.json
{
...
"scripts": {
"test-pwd": "echo $(pwd)"
},
...
}
# this command works correctly
echo $(pwd)
# output: /c/Users/<User>/path/to/repo
# this commad doesn't work
yarn test-pwd
# output: $(pwd)
my actual code:
npx #bazel/bazelisk run //tools/ci:pwd_script_py -- --root-dir=$(pwd)
^ this works fine
But this is my actual setup:
{
...
"scripts": {
"s1": "...",
"s2": "...",
"pwd-script": "npx #bazel/bazelisk run //tools/ci:pwd_script_py -- --root-dir=$(pwd)"
"start:all": "s1 && s2 && pwd-script",
},
...
}
when I run yarn start:all or yarn pwd-script, the scripts break as root-dir evaluates to literal string $(pwd) instead of C:\path\to\repo
Environment:
Win 11
Win Terminal -> Git Bash
node 16.14.1
npm 8.5
This setup seems to be working fine in Linux & OSX environments, but I also need to get it working under Windows env
Also, it is not easily done to move that $(pwd) into the underlying python script as the script is being run in a sandbox.

How to watch and re-run TypeScript on change?

I have a very simple application written in TypeScript:
src/index.ts
import * as http from "http";
const server = http.createServer((request, response) =>
{
response.end("Hello, World");
});
server.listen(3000);
Then my TypeScript configuration:
tsconfig.json
{
"compilerOptions": {
// Output options
"target": "es5",
"lib": [
"es2016"
],
"module": "commonjs",
"outDir": "./build",
}
}
I can build my code using npx tsc and then run it using node ./build/index.js, and upon visiting http://localhost:3000 in a browser I see the message "Hello, World" -- all good so far
Now using npx tsc -w I can watch the files to see if they change and re-compile them when this happens. This command run "forever" (until stopped) so it prevents me from running node ./output/index.js in the same terminal. Using multiple terminal windows or a terminal multiplexer I can pretty trivially run node ./output/index.js, but this file won't get re-run if my code is re-compiled. This means that if I change the string "Hello, World" to "Hello, Steven" I won't see the change until I manually stop my server and restart it
Is there a way to watch my TypeScript files like this and run the output so that the output is stopped and re-run when my code changes?
You could run tsc and nodemon at the same time:
npx tsc -w & npx nodemon build
or use nodemon with ts-node:
npx nodemon -x ts-node -e ts src
# to run even if there are TS errors:
npx nodemon -x 'ts-node --log-error' -e ts src
or just use ts-node-dev:
npx ts-node-dev src

How to disable warnings when node is launched via a (global) shell script

I am building a CLI tool with node, and want to use the fs.promise API. However, when the app is launched, there's always an ExperimentalWarning, which is super annoying and messes up with the interaction prompts. How can I disable this warning/all warnings?
I'm testing this with the latest node v10 lts release on Windows 10.
To use the CLI tool globally, I have added this to my package.json file:
{
//...
"preferGlobal": true,
"bin": { "myapp" : "./index.js" }
//...
}
And have run npm link to link the ./index.js script. Then I am able to run the app globally simply with myapp.
After some research I noticed that there are generally 2 ways to disable the warnings:
set environmental variable NODE_NO_WARNINGS=1
call the script with node --no-warnings ./index.js
Although I was able to disable the warnings with the 2 methods above, there seems to be no way to do that while directly running myapp command.
The shebang I placed in the entrance script ./index.js is:
#!/usr/bin/env node
// my code...
I have also read other discussions on modifying the shebang, but haven't found a universal/cross-platform way to do this - to either pass argument to node itself, or set the env variable.
If I publish this npm package, it would be great if there's a way to make sure the warnings of this single package are disabled in advance, instead of having each individual user tweak their environment themselves. Is there any hidden npm package.json configs that allow this?
Any help would be greatly appreciated!
I am now using a launcher script to spawn a child_process to work around this limitation. Ugly, but it works with npm link, global installs and whatnot.
#!/usr/bin/env node
const { spawnSync } = require("child_process");
const { resolve } = require("path");
// Say our original entrance script is `app.js`
const cmd = "node --no-warnings " + resolve(__dirname, "app.js");
spawnSync(cmd, { stdio: "inherit", shell: true });
As it's kind of like a hack, I won't be using this method next time, and will instead be wrapping the original APIs in a promise manually, sticking to util.promisify, or using the blocking/sync version of the APIs.
I configured my test script like this:
"scripts": {
"test": "tsc && cross-env NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest"
},
Notice the NODE_NO_WARNINGS=1 part. It disables the warnings I was getting from setting NODE_OPTIONS=--experimental-vm-modules
Here's what I'm using to run node with a command line flag:
#!/bin/sh
_=0// "exec" "/usr/bin/env" "node" "--experimental-repl-await" "$0" "$#"
// Your normal Javascript here
The first line tells the shell to use /bin/sh to run the script. The second line is a bit magical. To the shell it's a variable assignment _=0// followed by "exec" ....
Node sees it as a variable assignment followed by a comment - so it's almost a nop apart from the side effect of assigning 0 to _.
The result is that when the shell reaches line 2 it will exec node (via env) with any command line options you need.
New answer: You can also catch emitted warnings in your script and choose which ones to prevent from being logged
const originalEmit = process.emit;
process.emit = function (name, data, ...args) {
if (
name === `warning` &&
typeof data === `object` &&
data.name === `ExperimentalWarning`
//if you want to only stop certain messages, test for the message here:
//&& data.message.includes(`Fetch API`)
) {
return false;
}
return originalEmit.apply(process, arguments);
};
Inspired by this patch to yarn

docker node app always crashes on file change using nodemon

I am using the latest version of docker and the latest node image. I have a gulpfile that starts a nodemon process. I am using the --inspect flag to indicate I want to use the experimental chrome dev tool debugger. But when I make a file change it nodemon picks it up and restarts the process but crashes.
Here is my gulp task:
gulp.task('start:dev', done => {
let started = false;
nodemon({
script: path.join(__dirname, 'index.js'),
ext: 'js json',
nodeArgs: ['--inspect=0.0.0.0:9229'],
watch: path.join(__dirname, 'express'),
legacyWatch: true
})
.on('start', () => {
// to avoid nodemon being started multiple times
if (!started) {
setTimeout(() => done(), 100);
started = true;
}
});
});
And here is the error:
Starting inspector on 0.0.0.0:9229 failed: address already in use
If I change the --inspect flag to be --debug it works like a charm.
I am guessing is that the restart process is too fast for the --inspect to release its port. If I make another file change it does work and restarts normally. Probably since it had time to release the port.
I have tried using a delay on nodemon but I'd rather not. I would like quick restarts. And I have tried using to events, like, restart and exit, to wait for a few seconds and then restart the whole gulp task. But that was temperamental and again I want quick restarts without having to hack together something.
Right now I just switched back to --debug but that is deprecated in the latest V8. They are recommending to use --inspect.
Maybe the only way is to lock down my version of node?
Any suggestions?
There is an open issue addressing this problem.
The easiest workaround I found so far was using "signal": "SIGINT" in my nodemon.json thanks to this comment.
Just kill inspector and start inspector again
here is our team's solution in our package.json.
You had better kill inspector process and then restart inspector
"inspect": "kill-port --port 9229 && node --inspect=0.0.0.0:9229 build/startup.js",
"start_watch_inspect": `nodemon --delay 80ms --watch build/ build/startup.js --exec 'npm run inspect'`
Seems like this is related to:
https://github.com/remy/nodemon/issues/1492
My workaround is to run this before each restart: (in a makefile, gulp file etc...)
lsof -i -n | grep 9229 | awk '{print $2}' | xargs kill
** If put inside a Makefile remember to replace $ with $$ **

Resources