Enderchief / esgleam

`esbuild` for Gleam (no NodeJS/Deno needed)
Apache License 2.0
24 stars 4 forks source link

Why does automatic install force erlang runtime? #7

Open Blond11516 opened 2 months ago

Blond11516 commented 2 months ago

When esgleam installs esbuild automatically, the JS implementation forces the use of the Erlang target.

In the context of a Gleam project that targets only JS this can be really confusing. I found out when my deployment CI failed after trying to execute escript despite me explicitly not installing Erlang because I wasn't supposed to need it.

Esbuild installs fine when running gleam run -m esgleam/install manually, which uses the JS target as prescribed by my project, so I'm not sure why the auto-install flow doesn't let that happen. I also tried removing --target=erlang from the JS implementation and didn't spot any obvious issues after using the auto-install.

Enderchief commented 1 month ago

JavaScript cannot perform requests (ie to download esbuild) without async code. This would mean relying on promises or callbacks. To avoid that and be consistent with both targets, esgleam (when run with --target=js) starts a subprocess which runs gleam run -m esgleam/install --target=erlang.

Initially, it would not use Erlang and instead use JavaScript until there was an issue of people not having Deno installed (which was what esgleam's default JS runtime is set to) while removing javascript.runtime="deno" in gleam.toml would mean one would require NodeJS even if they use Deno only. The compromise that was suggested to me was to use Erlang as the assumption was someone using Gleam would have Erlang installed on their system.

Regardless of my reasoning behind it, thank you for this issue since I have realized this is an oversight in the implementation. In the next version of esgleam the CLI will behave exactly the same but I plan for the programmatic version to have an additional option to opt-out of auto installing. This would mean CI would have to run gleam run -m esgleam/install itself.

Blond11516 commented 1 month ago

there was an issue of people not having Deno installed (which was what esgleam's default JS runtime is set to) while removing javascript.runtime="deno" in gleam.toml would mean one would require NodeJS even if they use Deno only.

I'm not quite sure I understand the issue here. Isn't gleam using the JS runtime set by the user anyway? Or is it pulling the library's runtime when running one of the library's modules?

I plan for the programmatic version to have an additional option to opt-out of auto installing. This would mean CI would have to run gleam run -m esgleam/install itself.

That sounds fine as long as its clearly documented in the readme/quick start.

I'd also suggest trying to detect if an erlang runtime is available on the system before doing the auto-install to exit with a clear error message, or at least print out a warning when auto-installing on the JS runtime (with an option to silence it) to make absolutely sure users are aware of the limitation.

Thanks!

Enderchief commented 1 month ago

I'm not quite sure I understand the issue here. Isn't gleam using the JS runtime set by the user anyway? Or is it pulling the library's runtime when running one of the library's modules?

It's a weird situation, it pulls the library's runtime and also its target, here's an example to better explain it: Bob makes a cli package called wibble and he sets the target to "javascript". Joe creates a new projects and doesn't change any thing in gleam.toml. Then he runs gleam run -m wibble. By default Gleam runs it in JavaScript, even if target is erlang on Joe's gleam.toml. Now Joe wants to use Deno instead of Node so he changes the JavaScript runtime in gleam.toml to "deno". Unfortunately wibble runs using Node since implicitly javascript.runtime is set to "node" in wibble.

I'd also suggest trying to detect if an erlang runtime is available on the system before doing the auto-install to exit with a clear error message, or at least print out a warning when auto-installing on the JS runtime (with an option to silence it) to make absolutely sure users are aware of the limitation.

Great idea. Thank you!

Blond11516 commented 1 month ago

I see, I assumed whatever you run in a project would use the target specified by said project. Feels a little footgun-y to not do that, but I also see how that could be useful in some scenarios.

Anyway, thanks for the explanation! And thanks for writing esgleam too! Apart from this small hiccup the overall experience has been great 😄