running bash script with node, containing functions in script - node.js

Hi I am trying to run a bash script from the package.json in node.
(I know I could just use node instead of bash, but I already have written a bunch of code in bash and don't want to migrate immediately.) (Note I am on MacOS).
Inside the script I have various bash functions.
I have tried loading with various commands (code snippet of package.json):
{
"scripts": {
"start": "sh ./loadScripts.sh",
"serve": "bash ./loadScripts.sh",
"serve2": "source ./loadScripts.sh",
"serve3": "./loadScripts.sh",
},
}
However even though all of these load the script, when I try to use a function inside the script, say I try to run myFunction in the terminal after, then it says command not found.
However if I load the script directly in the terminal by typing
source ./loadScripts.sh it seems to work fine and I can use the functions I have defined in the script.
Why is this happening and how do I fix it?

Related

Inconsistencies between node's `spawn` and terminal

I'm trying to run a script from node, and I'm seeing different behaviour compared to if I run it from the terminal and I don't understand why.
I'm trying to do something a little bit out there, in that to save people typing pnpm {scriptName} --filter {packageName} I created a little script that they could run instead. It basically takes scriptName and lists all the available packages they can select from, and then trigger spawns a new process calling that command. Something like:
spawn("pnpm", ["--filter " + packageName, scriptName], { stdio: "inherit" });
Example:
In my particular case, I'm trying to test a script that ends up generating a pnpm --filter #ig/main test:debug.
I'm struggling a little though, in that if I invoke that via a terminal it works fine (test:debug is defined both in .\package.json and .\apps\main\package.json). However if I invoke it via the spawn command in node, then for some reason it invoking the test:debug script in the root, rather than just in apps/main. Does anyone know what that might be the case?
Turns out this was down to the current working directory not being set correctly when using spawn.

Using glob in Yarn/NPM script

I'm using a script to run multiple files with Node.js using a glob pattern to capture the files:
node build/**/*.spec.js
This seems to work fine, but when I put the same command in the scripts object as follows
"scripts": {
"test": "node build/**/*.spec.js"
}
and try to run it with yarn test or npm run test I get the following error:
Error: Cannot find module '/path/to/project/build/**/*.spec.js'
indicating that it's treating the glob pattern as a literal filename.
How can I achieve the glob behaviour in a Yarn/NPM script?
A couple of things to note here:
The behaviour of node build/**/*.js depends on your shell.
In zsh (the current default on macOS), it does what you expect; expanding the glob to all matching files and passing them to Node.
In bash and sh, it tries to run the literal file build/**/*.js with Node, which gives the "Cannot find module" error in your post.
The default shell used by npm run-script is, per the docs:
'/bin/sh' on POSIX systems
Even if you're using zsh, when you run the test script it uses sh. You can configure this with the script-shell option, e.g.:
in .npmrc (which you can update with npm config set script-shell=/bin/zsh); or
inline (by running npm --script-shell=/bin/zsh test).
However you get it running, note that only one of the matched files actually gets executed; the paths to the other two are passed as command line arguments. With three files foo.spec.js, bar.spec.js and baz.spec.js containing the following (adjusted to log each file's own name) in build/:
console.log(process.argv);
console.log("foo");
running the globbed version gives:
$ node build/**/*.spec.js
[
'<path/to>/bin/node',
'<path/to>/build/bar.spec.js',
'build/baz.spec.js',
'build/foo.spec.js'
]
bar

node.js executables not working on windows

I'm attempting to make package run via executable, but it's not executing on windows. Not sure what's wrong, and helpdocs haven't supplied much help.
Whenever I try to run it with the below snippet, I get a "Windows Script Host" error GUI.
"bin": {
"kaga": "bin/index.js"
}
Whenever I use this, I get a terminal error (included below)
"bin": {
"kaga": "./bin/"
}
"C:\Users\Kagetane\AppData\Roaming\npm\\node_modules\kaga\bin"
'"C:\Users\Kagetane\AppData\Roaming\npm\\node_modules\kaga\bin"' is not recognized as an internal or external command, operable program or batch file.
Wait, never mind, I got it. All I needed was a shebang line in bin/index.js
#!/usr/bin/env node

node.js attach REPL to script

How do I start a node.js script and still be able to execute commands into the terminal ? I am looking for a node.js REPL that is also there for my custom script, so that I can inspect/log the state of my program for instance.
This is something similar to this JVM question, but for node.js.
I have tried node -i server.js without results. Do I need to have custom code in my script or is it feasible without that ? I saw this post, but it requires custom code, which I'd like to avoid.
Also, bonus points for reattaching a node script launched by an init script (I can see it in the process list : node -i server.js).
You can start a repl loop from within your program
http://nodejs.org/api/repl.html
Does the other way round work for you?
Start the REPL and then load the script and then execute your commands. Use load to load your script.
Inside REPL, try
.load server.js

Node: Move the current directory of the interactive shell

I'm writing a little CLI tool for Node.js. There are some situations where I'd like to run modify the current directory of the shell that runs my program:
some/location$ myProg moveToSomewhere
some/other/location$
child_process can't help here, since its commands run in a different shell.
Is there a way to do this?

Resources