Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a flag to include a user defined node_modules location. #1116

Closed
jarrodhroberson opened this issue Mar 2, 2025 · 5 comments · Fixed by #1117
Closed

Add a flag to include a user defined node_modules location. #1116

jarrodhroberson opened this issue Mar 2, 2025 · 5 comments · Fixed by #1117

Comments

@jarrodhroberson
Copy link

jarrodhroberson commented Mar 2, 2025

I know about Issue 595

This may or may not be a duplicate. I honestly am not familiar enough with node to know all the details about how it works internally because I do not use node except as a "user".

Motivation:

I want to write scripts for doing scripty things regardless of OS and shell environment. ZX seems to be just the thing to unify hundreds/thousands of bash/shell, python, perl, ruby, groovy, you name it scripts into one consistent language and runtime.

The problem is node_modules. I can not sell a solution that requires to install dependencies in every working dir before running a script.

Second Solution:

The second solution I came up with is to create a wrapper script that just makes sure that a sym link to npm root -g is in my current working directory.

It then spawns a process to run the actual zx script I want to run and after it is done, it removes the sym link.

#!/usr/bin/env zx
await $`ln -sf ${(await $`npm root -g`)} node_modules`;
const childProcess = await $`${process.argv[3]} ${process.argv.slice(4)}`;
if (childProcess.stdout) {
    console.log(childProcess.stdout.trim());
}
if (childProcess.stderr) {
    console.error(childProcess.stderr.trim());
}
await $`rm -f node_modules`;

This is hacky, but then again, it works, until the output of a script gets large and you have to move to streaming the child process stdout and stderr and things get messy again.

Now I have to have a third thing installed and versioned and maintained. node, zx and my wrapper to execute the scripts.

go run is looking pretty good again. ;-P

First Solution:

Single file wrapper solution; have every script wrap itself.

I did successfully figure out how to do the same thing within the zx script and trigger it to rerun itself, and clean up behind itself, but it was even more hacky, and it still has the issues with stdout and stderr. So, wrapper solution attempted.

It was a complete mess once I got it working so I am not including it here for brevity.

Third Solution?

I am trying to stay within the ZX environment, using bash wrapper instead of ZX wrapper would be way less lines of code, but same level of hackishness and would break the "one language" benefit enough to just Go, it compiles and runs as fast as spinning up node and running a script does in almost every case I have micro benchmarked.

That said, JavaScript is an easier sell to a larger audience.

If there is no way that the ZX team is interested in including something to support running ZX scripts from anywhere and resolving import to a non-local working directory node_modules directory, can I at least get some guidance on doing it myself?

Thanks for reading this far and for comprehension. I mean if you read this far you care.

I am digging through this repo source, and other repos that have added "extras" to ZX for convenience. But I am not a node main, and definitely not a TS main so, it is going very slowly.

If I fork the project can I even add support for this? If so where would I start to look at inserting it?

What I would really want to be able do is add something to the shebang and be done with it.

#!/usr/bin/env -S zx --use-global-modules

maybe make the default an environment variable that could be set;

I know NODE_PATH is bad for valid reasons, and would not work because of some esmodule voodoo limitation that I know enough about to know I do not need to know any more.

Maybe be able to say --use-global-modules=~/node_modules to allow the user to specify some other directory where they maintain a read-only set of version locked dependencies on a script by script basis.

I guess, there needs to be a way to wedge something in between zx and node to get the node_modules directory in there.

@antonmedv
Copy link
Collaborator

I think using a zx as a binary executable will be easiest solution.

@antongolub
Copy link
Collaborator

@jarrodhroberson,

--prefer-local flag can be used now for node_modules linking. Try [email protected].

@jarrodhroberson
Copy link
Author

@jarrodhroberson,

--prefer-local flag can be used now for node_modules linking. Try [email protected].

wow, that was fast and greatly appreciated.

I can not wait to try it out, now I can sell the idea of migrating all our "dev ops" scripts to ZX/JS.

@antongolub
Copy link
Collaborator

Here you go: https://github.com/google/zx/releases/tag/8.4.0

@jarrodhroberson
Copy link
Author

Here you go: https://github.com/google/zx/releases/tag/8.4.0

ZX is a real jewel in the open source toolbox functionality wise.

This is some S Tier support! Makes it even moreso!

I am going to take the time to learn the code base so I might can help maintain in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants