At the moment, purs bundle accepts as input a list of JS files, but it can only accept JS files which are from a compiler's output directory. It needs to handles regular JS output modules and FFI modules differently, so in order to decide which kind of module it has received, it looks at the file path; anything called index.js is treated as a regular output module and anything called foreign.js is treated as an FFI module. If a file is called something other than index.js or foreign.js, we throw an error.
Since purs bundle only works with JS files which are from a compiler's output directory, I would like to modify its CLI so that instead it only needs to accept an output directory rather than a list of files. That way, we avoid having to leak details of the format of the compiler output directory to the extent that we do now. It also better communicates that purs bundle is specifically for PureScript compiler output and not any old collection of JS files. This in turn makes it easier to justify having purs bundle inspect externs files when it is asked to generate code to call main, to make sure that the module designated as the main module does in fact export main and that main has an appropriate type.
We previously discussed typechecking main during bundling in #2086 and decided that it would be better for external tools to do this. After reflecting on this more recently though I've changed my mind: currently pulp is forced to poke around inside externs files to achieve this, and I think this is a worse state of affairs because the externs files are not part of the compiler's public API.
Here's a concrete proposal:
- Modify
purs bundle so that the first argument is a PureScript compiler output directory. For the sake of backwards compatibility, if we receive more than one argument on the command line, infer the location of the output directory by finding the common prefix of all the files provided. In this case, we should also print a warning that the old CLI (i.e. providing a list of JS files) is deprecated.
- If we have been requested to generate code to call
main, use the externs files to check that the designated main module exports main, and that the type of main matches Effect a before producing JS output. Note that this will not be quite the same as a regular "do these types unify" check, because e.g. main :: Partial => Effect Unit or main :: MonadEffect m => m Unit should both be rejected, because their runtime representation won't conform to what we need: namely, a nullary function which performs the effects of main when invoked.
- Add an option or options to
purs bundle to allow using types other than Effect for this check, or for disabling the check entirely. Pulp currently does this with --check-main-type TYPE option which allows you to provide a type to use instead of Effect, and a --skip-main-check flag which allows you to disable the check entirely; unless anyone has any objections I'd suggest using the same scheme here.
If we agree that this is a good idea we should probably implement these two things separately; I just opened one issue because I thought it would make sense to discuss them together.
At the moment,
purs bundleaccepts as input a list of JS files, but it can only accept JS files which are from a compiler's output directory. It needs to handles regular JS output modules and FFI modules differently, so in order to decide which kind of module it has received, it looks at the file path; anything calledindex.jsis treated as a regular output module and anything calledforeign.jsis treated as an FFI module. If a file is called something other thanindex.jsorforeign.js, we throw an error.Since
purs bundleonly works with JS files which are from a compiler's output directory, I would like to modify its CLI so that instead it only needs to accept an output directory rather than a list of files. That way, we avoid having to leak details of the format of the compiler output directory to the extent that we do now. It also better communicates thatpurs bundleis specifically for PureScript compiler output and not any old collection of JS files. This in turn makes it easier to justify havingpurs bundleinspect externs files when it is asked to generate code to callmain, to make sure that the module designated as the main module does in fact exportmainand thatmainhas an appropriate type.We previously discussed typechecking
mainduring bundling in #2086 and decided that it would be better for external tools to do this. After reflecting on this more recently though I've changed my mind: currentlypulpis forced to poke around inside externs files to achieve this, and I think this is a worse state of affairs because the externs files are not part of the compiler's public API.Here's a concrete proposal:
purs bundleso that the first argument is a PureScript compiler output directory. For the sake of backwards compatibility, if we receive more than one argument on the command line, infer the location of the output directory by finding the common prefix of all the files provided. In this case, we should also print a warning that the old CLI (i.e. providing a list of JS files) is deprecated.main, use the externs files to check that the designated main module exportsmain, and that the type ofmainmatchesEffect abefore producing JS output. Note that this will not be quite the same as a regular "do these types unify" check, because e.g.main :: Partial => Effect Unitormain :: MonadEffect m => m Unitshould both be rejected, because their runtime representation won't conform to what we need: namely, a nullary function which performs the effects ofmainwhen invoked.purs bundleto allow using types other thanEffectfor this check, or for disabling the check entirely. Pulp currently does this with--check-main-type TYPEoption which allows you to provide a type to use instead ofEffect, and a--skip-main-checkflag which allows you to disable the check entirely; unless anyone has any objections I'd suggest using the same scheme here.If we agree that this is a good idea we should probably implement these two things separately; I just opened one issue because I thought it would make sense to discuss them together.