spago icon indicating copy to clipboard operation
spago copied to clipboard

Spago does not emit an error when bundling an app's main module that does not have a `main` function

Open JordanMartinez opened this issue 5 years ago • 18 comments

Steps to reproduce:

mkdir explore-bundle-no-main
cd explore-bundle-no-main
spago init
# edit the `src/Main.purs` file to remove the "main" function
spago bundle -m Main -t dist/main.js

Spago doesn't fail with an error that Main.purs does not have a function called main. Thus, the output of the bundle is this:

// Generated by purs bundle 0.12.5
var PS = {};
PS["Main"].main();

One won't realize that the source of their issue is the compiled output until after exploring a few things more.

I only came across this because I used the wrong module name in the spago bundle command.

JordanMartinez avatar May 03 '19 23:05 JordanMartinez

Good catch! This is interesting because spago bundle just shells out to purs bundle, which is happy to generate that malformed js.

Pulp however implements this check, and fails with a nice error message:

$ pulp build -m Main -t dist/main.js
* Building project in /Users/fabrizio/code/explore-bundle-no-main
* Build successful.
* Bundling JavaScript...
* Main cannot be used as an entry point module because it
* does not export a `main` value.
*
* If you need to create a JavaScript bundle without an entry point, use
* the --skip-entry-point flag.
*
* ERROR: Failed entry point check for module Main

Since that looks like a bunch of code, this makes me wonder if it should be instead purs to implement the check instead. We could implement it here, ~but the compiler is a heavy dependency that we've been trying to avoid~ by using the externs files as pulp does

EDIT: it looks like there's an entire PureScript package dedicated to this check: externs-check

f-f avatar May 04 '19 11:05 f-f

Ping @hdgarrood: thoughts on adding this check to purs?

f-f avatar May 04 '19 12:05 f-f

This is something we previously decided is best not done inside purs bundle (since purs bundle only has access to the generated js). See https://github.com/purescript/purescript/issues/2086

hdgarrood avatar May 04 '19 13:05 hdgarrood

@hdgarrood thanks for the context! It makes sense, I'll look into using the externs files for the check 👍

f-f avatar May 04 '19 13:05 f-f

Then again I suppose since purs bundle is unlikely to be run against any JS files which aren’t output from purs compile, perhaps it would make more sense to just point purs bundle at the compiler’s output directory, so that it would have the information it needed to be able to implement this check inside purs.

hdgarrood avatar May 04 '19 13:05 hdgarrood

It is certainly less than ideal that pulp is depending on the externs files format, since these are not part of the compiler’s public API.

hdgarrood avatar May 04 '19 13:05 hdgarrood

Indeed, but if it's necessary to rely on them and other tools (e.g. spago) start doing that too then it could make sense to include them in the public API? (though I'd be more for purs checking on this by itself)

f-f avatar May 04 '19 14:05 f-f

Yeah what I’m suggesting is that we modify purs bundle to have access to externs files as well as the js so that it can do this check.

hdgarrood avatar May 04 '19 15:05 hdgarrood

I created an issue: https://github.com/purescript/purescript/issues/3621

hdgarrood avatar May 05 '19 11:05 hdgarrood

Thank you!

f-f avatar May 05 '19 16:05 f-f

I'm removing the "blocked" label because a good first take at this (i.e. solving 90% of the problem) would be literally grepping the file searching for the string "main ="

f-f avatar Mar 29 '20 21:03 f-f

Assuming this isn't been worked, I'd be interested in picking it up 😄

I've not worked on spago before so wondered if I could be pointed to where I'd do the searching for the string "main ="?

Cmdv avatar Sep 24 '20 08:09 Cmdv

What's an updated repro for this? Or am I being dense in failing to follow the original repro? :smile:

samhh avatar Jun 25 '21 15:06 samhh

@samhh bundle was replaced by bundle-app in the meantime. The updated repro is:

mkdir explore-bundle-no-main
cd explore-bundle-no-main
spago init
echo "module Main where" > src/Main.purs
spago bundle-app
node index.js

The last command fails because there's no main function to be run.

f-f avatar Jun 25 '21 15:06 f-f

@Cmdv I'm so sorry I missed your comment! Every once in a while some notification slips through, apologies. Also feel free to ping me in the future.

The patch should go somewhere in this function, somewhere before line 379, which is where we call the compiler: https://github.com/purescript/spago/blob/8b8f06ab08c5011710bcb8b4f1b575aaff0c2e6b/src/Spago/Build.hs#L376-L381

If we are bundling withMain (which is the only occurrence where we need to worry about this. Actually I'm not sure why this is parametrized, bundle-app should always run WithMain) then we should read the module that we're bundling, and to a text search for main =.

At this point though I'm thinking that it might be easier to fix this in the compiler.

f-f avatar Jun 25 '21 16:06 f-f

This is even easier these days - we'd just need to copy this bit of code

f-f avatar Sep 29 '23 21:09 f-f

I'm so sorry I missed your comment! Every once in a while some notification slips through, apologies.

@f-f well looks like I'm even worse just spotted your reply only took me 2 years 😅

Cmdv avatar Sep 29 '23 21:09 Cmdv

It's alright, this issue has been open for 4y, we'll eventually get to it 😂

f-f avatar Sep 29 '23 21:09 f-f