node js cli STDOUT STDERR output exec and spawn commands - npm

I am looking for a clear answer on how the stdout and stderr work when developing a npm cli module.
I would like to print out everything exactly as it is when I run command with child_process.spawn.
I managed to output the git clone command with the --progress options. Now I want to output the npm install command but it is printing only the final string.
Would be nice to have a clear answer on how this work in general and what are the best practices.
This works:
import * as cp from 'child_process';
const child = cp.spawn('git', ['clone', 'ssh://myrepo...', '--progress']);
child.stdout.setEncoding('utf8');
child.stdout.on('data', (chunk) => {
process.stdout.write(`${chunk}`);
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', (chunk) => {
process.stdout.write(`${chunk}`);
});
// BTW why git is outputing in STDERR and not in STDOUT?
However this doesn't work
const child = cp.spawn('npm', ['i', 'mymodule']);
Is there a way to make this work for each command?

You can leave off the event handlers and encoding settings and tell spawn() to pass stdio through to the parent process.
const child = cp.spawn('npm', ['i', 'mymodule'], {stdio: 'inherit'});
Both of your commands work for me as long as the listeners are added as in your first example. Your second example only stops working for me if I leave out the event handlers. It would be interesting to know what platform you are running on, what versions of node and npm you are using, and a complete not-working example that can be cut and paste into a file for testing. (Also, what is the name of the file? Are you using .mjs extension or something else to make import work? Is this file in a module loaded elsewhere or in the base level script?)

Related

VSCode Extension User Input Passward

I am trying to develop a VSCode Extension that requires user passward to run a command on the terminal. I have tried this but it throws an irrelevant error.
const readline = require('readline');
const reader = readline.createInterface({
input: process.stdin,
output: process.stdout
});
reader.question("Enter: ", passward=>{
reader.close();
});
Clearly, I am placing it wrong or something else because it runs fine in an individual node js file. I am placing it inside of registercommand
If by run a command in the Terminal you mean that some command should be displayed/added in VS Code terminal, then you should look at the Terminal API in VS Code.
There is a sample in https://github.com/microsoft/vscode-extension-samples/tree/main/terminal-sample, and it will probably help you better understand how to integrate with VS Code terminal.
Hope this helps

How to debug neovim lsp custom command

I am attempting to get the volar vue language server to work in place of vetur for neovim's native lsp.
Using both lspconfig and lspinstall I was able to create a working custom install for sumneko_lua (unrelated but had to manually build due to some issues with the built-in :LspInstall lua). Below is that code duplicated and modified for an attempt at using this new vue server:
local vue_config = require'lspinstall/util'.extract_config('vuels')
vue_config.default_config.cmd = {'node', './node_modules/vscode-vue-languageservice/out/index.js', '--stdio'}
require'lspinstall/servers'.newvue = vim.tbl_extend('error', vue_config, {
install_script = [[
! test -f package.json && npm init -y --scope=lspinstall || true
npm install vscode-vue-languageservice#latest
]],
uninstall_script = nil
})
Running :LspInstall newvue installs properly, however :LspInfo shows this language server is attached to the buffer (of a .vue file) but not active. I believe the issue is with this path: ./node_modules/vscode-vue-languageservice/out/index.js. It exists, but may not be the correct entry point? The default vue ls simply has vls as the command because it provides a binary. Am I missing something in this package? I have yet to come across another language server without a single binary to pick out.
Thanks!
Can you try an absolute path to the out.js file? In my pretty elaborate config for a custom Volar install I'm using something just /home/myuser/dev/volar/packages/server/out/index.js (where the volar folder is just the whole volar cloned github repo). My full config is here
I don't think you can use relative paths like you did. I know you're assuming that the "./node_modules" means "workspace directory" but it's hard to tell in which directory nvim-lspconfig opens up those executables.
I have yet to come across another language server without a single binary to pick out.
Volar also provides a binary, it's volar-server (after running npm i -g #volar/server), it's just with a custom install (ie. alongside the real volar) you can't use it, because I assume you want to use your local install with custom code.
As for more indepth debugging/logging, you can check ~/.cache/nvim/lsp.log to see why the language server dies in detail.

How to auto save compiled vue files when running npm run serve

With vue.js when setting up a project using vue CLI i can run
$ npm run serve
to compile the files and start a port at localhost:8080
My question is what can i do so that the generated that got rendered in the page be also saved to a directory in my development machine.
Just like auto-saving and modifying so that i can be able to use the file on another project which depends on the generated files all during development
Are you sure it's not already creating a bundle somewhere? In some kind of build or dist folder?
Inside the webpack config you can check what value is used for output.
I don't know if an easier solution exists. But what i would suggest is :
Set writeToDisk option true. This will make sure your bundle written in to disk. Link
Then add an after-emit hook to the webpack pipeline:
const exec = require('child_process').exec; // use exec to run shell command
module.exports = {
...
plugins: [
...
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('CopyOutputPlugin', (compilation) => {
exec('command to copy output folder to desired folder');
});
}
}
]
};
child_process documentation.

How to change a dependency version in npm

I'm actually trying to use gulp-handlebars but I need to change handlebars version in the gulp-handlebars package. I can't find a way to do that with a command line, and I'm new to all of this stuff, so I'm asking for clear help, what files do I have to change ?
I assume that copy/paste of my good version of Handlebars in the gulp-handlebars folder wouldn't be enough (and I actually tried that).
Thanks.
It looks like gulp-handlebars is incredibly simple. It should be fairly simple to use handlebars and vinyl-map without relying on a plugin, something like:
In the terminal:
$ npm remove gulp-handlebars
$ npm install --save-dev handlebars#version-you-want vinyl-map gulp-rename
In your gulpfile.js:
var handlebars = require('handlebars'),
rename = require('gulp-rename'),
map = require('vinyl-map');
// ... in your task ...
return gulp.src(...)
.pipe(map(function(contents) {
return handlebars.precompile(contents.toString() /*, options */);
})
.pipe(rename({ extname: '.js' }))
.pipe(gulp.dest(...));
I haven't test this, but it should get you going in the right direction.

Passing cli parameters to casperjs through grunt task and npm test

I'm running tests with npm test - that actually runs a grunt task grunt casperjs:
casperjs:{
options:{},
files:
['./test_index.js',
'./test_map_regression.js',
'./test_index_get_gush.js'] /
},
using the grunt-casperjs-plugin in order to automate testing with slimerjs along with phantomjs, both running under casperjs in Travis-ci.
In order to do that, I need to pass the engine as a variable from the command line. something like:
casperjs --engine=slimerjs test_suite.js
Question: I can't find a way to pass the options from grunt cli (and I assume npm command line options would delegate to grunt. correctly?) to the files array.
I tried to add:
var engine = grunt.option('engine') || 'phantomjs';
engine = '--engine='+engine;
and then in the file array do:
files:['./test_index.js '+engine,
'./test_map_regression.js '+enging,
'./test_index_get_gush.js '+engine]
but seems that file array has to get real file names without the added args.
I'll be glad for any ideas on how to solve this through.
I haven't tested this, but looking at the grunt-casperjs source, it looks as though you would want to pass the engine as an option.
So, something like this should work:
casperjs:{
options: {
'engine': 'slimerjs'
},
files: [
'./test_index.js',
'./test_map_regression.js',
'./test_index_get_gush.js'
]
}