From 63d6a244462d050e119bde54a7063bae8a17e987 Mon Sep 17 00:00:00 2001 From: eric thul Date: Fri, 25 Dec 2015 18:41:33 -0500 Subject: [PATCH] Splitting PSC functionality into a separate plugin The loader creates shim modules that reference their corresponding PureScript module that is bundled by the PureScript webpack plugin, which invokes `psc` and `psc-bundle`. Resolves #31 and resolves #32 --- .gitignore | 2 + README.md | 69 +++---------- bower.json | 5 +- docs/PursLoader/ChildProcess.md | 15 --- docs/PursLoader/FS.md | 21 ---- docs/PursLoader/Glob.md | 15 --- docs/PursLoader/Loader.md | 2 +- docs/PursLoader/LoaderRef.md | 8 +- docs/PursLoader/Options.md | 24 +---- docs/PursLoader/Path.md | 27 +++++ package.json | 5 +- src/PursLoader/ChildProcess.js | 40 -------- src/PursLoader/ChildProcess.purs | 23 ----- src/PursLoader/FS.js | 36 ------- src/PursLoader/FS.purs | 38 ------- src/PursLoader/Glob.js | 18 ---- src/PursLoader/Glob.purs | 22 ---- src/PursLoader/Loader.purs | 139 +++++++++----------------- src/PursLoader/LoaderRef.purs | 13 ++- src/PursLoader/Options.purs | 132 ++++-------------------- src/PursLoader/{Loader.js => Path.js} | 11 +- src/PursLoader/Path.purs | 14 +++ 22 files changed, 149 insertions(+), 530 deletions(-) delete mode 100644 docs/PursLoader/ChildProcess.md delete mode 100644 docs/PursLoader/FS.md delete mode 100644 docs/PursLoader/Glob.md create mode 100644 docs/PursLoader/Path.md delete mode 100644 src/PursLoader/ChildProcess.js delete mode 100644 src/PursLoader/ChildProcess.purs delete mode 100644 src/PursLoader/FS.js delete mode 100644 src/PursLoader/FS.purs delete mode 100644 src/PursLoader/Glob.js delete mode 100644 src/PursLoader/Glob.purs rename src/PursLoader/{Loader.js => Path.js} (82%) create mode 100644 src/PursLoader/Path.purs diff --git a/.gitignore b/.gitignore index dd8eead..6c930c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .psci +.pulp-cache npm-debug.log index.json index.js @@ -9,3 +10,4 @@ example/bundle.js example/node_modules/ example/bower_components/ example/output/ +tmp/ diff --git a/README.md b/README.md index bef16af..a459059 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,9 @@ ## Install -Install with [npm](https://npmjs.org/package/purs-loader) +Install with [npm](https://npmjs.org/package/purs-loader). + +This loader works in conjunction with the [PureScript webpack plugin](https://npmjs.org/package/purescript-webpack-plugin). Ensure the plugin is installed and configured accordingly. ``` npm install purs-loader --save-dev @@ -12,64 +14,25 @@ npm install purs-loader --save-dev ## Options -###### `noPrelude` (Boolean) - -Toggles `--no-prelude` that omits the Prelude. - -###### `noTco` (Boolean) - -Toggles `--no-tco` that disables tail-call optimizations. - -###### `noMagicDo` (Boolean) - -Toggles `--no-magic-do` that disables optimizations overloading the do keyword generating efficient code for the `Eff` monad. - -###### `noOpts` (Boolean) - -Toggles `--no-opts` that skips the optimization phase. - -###### `verboseErrors` (Boolean) - -Toggles `--verbose-errors` that displays verbose error messages. - -###### `comments` (Boolean) +###### `pscBundle` (String) -Toggles `--comments` that includes comments in generated code. - -###### `output` (String) - -Sets `--output=` the specifies the output directory, `output` by default. - -###### `noPrefix` (Boolean) - -Toggles `--no-prefix` that does not include the comment header. - -###### `ffi` (String Array) - -Specifies the PureScript FFI files setting `--ffi=`. Glob syntax is supported. This option is specified as `ffi[]=path`. - -###### `src` (String Array) - -Specifies the PureScript source files. Glob syntax is supported. This option is specified as `src[]=path`. +Relative path to the bundled JavaScript file generated by the `PurescriptWebpackPlugin`. The default value is `output/bundle.js`. ## Example ```js // webpack.config.js +'use strict'; -var path = require('path'); - -var srcs = ['src[]=bower_components/purescript-*/src/**/*.purs', 'src[]=src/**/*.purs']; +var PurescriptWebpackPlugin = require('purescript-webpack-plugin'); -var ffis = ['ffi[]=bower_components/purescript-*/src/**/*.js']; +var src = ['bower_components/purescript-*/src/**/*.purs', 'src/**/*.purs']; -var output = 'output'; +var ffi = ['bower_components/purescript-*/src/**/*.js', 'src/**/*FFI.js']; var modulesDirectories = [ 'node_modules', - // The bower component for purescript-prelude is specified here to - // allow JavaScript files to require the 'Prelude' module globally. - 'bower_components/purescript-prelude/src' + 'bower_components' ]; var config @@ -79,12 +42,10 @@ var config , filename: 'bundle.js' } , module: { loaders: [ { test: /\.purs$/ - , loader: 'purs-loader?output=' + output + '&' + srcs.concat(ffis).join('&') + , loader: 'purs-loader' } ] } - , resolve: { modulesDirectories: modulesDirectories - , extensions: ['', '.js', '.purs'] - } - , resolveLoader: { root: path.join(__dirname, 'node_modules') } + , resolve: { modulesDirectories: modulesDirectories } + , plugins: [ new PurescriptWebpackPlugin({src: src, ffi: ffi}) ] } ; @@ -92,7 +53,3 @@ module.exports = config; ``` See the [example](https://github.com/ethul/purs-loader/tree/master/example) directory for a complete example. - -## Notes - -A `.psci` file is generated during each run of the loader. diff --git a/bower.json b/bower.json index aabc633..8b61f6f 100644 --- a/bower.json +++ b/bower.json @@ -1,9 +1,10 @@ { "name": "purs-loader", "private": true, - "devDependencies": { + "dependencies": { "purescript-aff": "^0.13.0", "purescript-strings": "^0.7.0", - "purescript-foreign": "^0.7.0" + "purescript-foreign": "^0.7.0", + "purescript-unsafe-coerce": "~0.1.0" } } diff --git a/docs/PursLoader/ChildProcess.md b/docs/PursLoader/ChildProcess.md deleted file mode 100644 index 7c2e414..0000000 --- a/docs/PursLoader/ChildProcess.md +++ /dev/null @@ -1,15 +0,0 @@ -## Module PursLoader.ChildProcess - -#### `ChildProcess` - -``` purescript -data ChildProcess :: ! -``` - -#### `spawn` - -``` purescript -spawn :: forall eff. String -> Array String -> Aff (cp :: ChildProcess | eff) String -``` - - diff --git a/docs/PursLoader/FS.md b/docs/PursLoader/FS.md deleted file mode 100644 index 811fcbd..0000000 --- a/docs/PursLoader/FS.md +++ /dev/null @@ -1,21 +0,0 @@ -## Module PursLoader.FS - -#### `FS` - -``` purescript -data FS :: ! -``` - -#### `writeFileUtf8` - -``` purescript -writeFileUtf8 :: forall eff. String -> String -> Aff (fs :: FS | eff) Unit -``` - -#### `findFileUtf8` - -``` purescript -findFileUtf8 :: forall eff. Regex -> Array String -> Aff (fs :: FS | eff) (Maybe String) -``` - - diff --git a/docs/PursLoader/Glob.md b/docs/PursLoader/Glob.md deleted file mode 100644 index f7abe78..0000000 --- a/docs/PursLoader/Glob.md +++ /dev/null @@ -1,15 +0,0 @@ -## Module PursLoader.Glob - -#### `Glob` - -``` purescript -data Glob :: ! -``` - -#### `globAll` - -``` purescript -globAll :: forall eff. Array String -> Aff (glob :: Glob | eff) (Array (Array String)) -``` - - diff --git a/docs/PursLoader/Loader.md b/docs/PursLoader/Loader.md index f81c486..bb02470 100644 --- a/docs/PursLoader/Loader.md +++ b/docs/PursLoader/Loader.md @@ -3,7 +3,7 @@ #### `Effects` ``` purescript -type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader, err :: EXCEPTION | eff) +type Effects eff = (loader :: Loader | eff) ``` #### `loader` diff --git a/docs/PursLoader/LoaderRef.md b/docs/PursLoader/LoaderRef.md index 36c1550..60341f7 100644 --- a/docs/PursLoader/LoaderRef.md +++ b/docs/PursLoader/LoaderRef.md @@ -1,5 +1,11 @@ ## Module PursLoader.LoaderRef +#### `AsyncCallback` + +``` purescript +type AsyncCallback eff = Maybe Error -> String -> Eff (loader :: Loader | eff) Unit +``` + #### `LoaderRef` ``` purescript @@ -15,7 +21,7 @@ data Loader :: ! #### `async` ``` purescript -async :: forall eff a. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> a -> Eff (loader :: Loader | eff) Unit) +async :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> String -> Eff (loader :: Loader | eff) Unit) ``` #### `cacheable` diff --git a/docs/PursLoader/Options.md b/docs/PursLoader/Options.md index 4202475..2bfcddd 100644 --- a/docs/PursLoader/Options.md +++ b/docs/PursLoader/Options.md @@ -8,31 +8,13 @@ newtype Options ##### Instances ``` purescript -instance isForeignOptions :: IsForeign Options +IsForeign Options ``` -#### `output` +#### `runOptions` ``` purescript -output :: Options -> String -``` - -#### `pscOptions` - -``` purescript -pscOptions :: Options -> Array String -``` - -#### `loaderSrcOption` - -``` purescript -loaderSrcOption :: Foreign -> Maybe (Array String) -``` - -#### `loaderFFIOption` - -``` purescript -loaderFFIOption :: Foreign -> Maybe (Array String) +runOptions :: Options -> Options_ ``` diff --git a/docs/PursLoader/Path.md b/docs/PursLoader/Path.md new file mode 100644 index 0000000..cc00436 --- /dev/null +++ b/docs/PursLoader/Path.md @@ -0,0 +1,27 @@ +## Module PursLoader.Path + +#### `relative` + +``` purescript +relative :: String -> String -> String +``` + +#### `resolve` + +``` purescript +resolve :: String -> String +``` + +#### `dirname` + +``` purescript +dirname :: String -> String +``` + +#### `joinPath` + +``` purescript +joinPath :: String -> String -> String +``` + + diff --git a/package.json b/package.json index 0080d32..3bcd03f 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,10 @@ }, "scripts": { "build": "npm run-script build:compile && npm run-script build:docs && npm run-script build:package", - "build:compile": "pulp build -o build", + "build:compile": "pulp build -o build --force", "build:docs": "pulp docs", "build:package": "webpack --progress --colors --profile --bail", - "build:watch": "pulp -w build -o build", + "build:watch": "pulp -w build -o build --force", "build:json": "webpack --progress --colors --profile --bail --json > index.json", "prepublish": "npm run-script build" }, @@ -21,7 +21,6 @@ "index.js" ], "devDependencies": { - "pulp": "^4.3.0", "webpack": "^1.8.4" }, "dependencies": { diff --git a/src/PursLoader/ChildProcess.js b/src/PursLoader/ChildProcess.js deleted file mode 100644 index d62aef6..0000000 --- a/src/PursLoader/ChildProcess.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -// module PursLoader.ChildProcess - -var child_process = require('child_process'); - -var chalk = require('chalk'); - -function spawnFn(command, args, errback, callback) { - return function(){ - var process = child_process.spawn(command, args); - - var stdout = new Buffer(0); - - var stderr = new Buffer(0); - - process.stdout.on('data', function(data){ - stdout = Buffer.concat([stdout, new Buffer(data)]); - }); - - process.stderr.on('data', function(data){ - stderr = Buffer.concat([stderr, new Buffer(data)]); - }); - - process.on('close', function(code){ - var output = stdout.toString('utf-8'); - - var error = stderr.toString('utf-8'); - - if (error.length > 0) { - console.error('\n' + chalk.red('*') + ' ' + error); - } - - if (code !== 0) errback(new Error('Process terminated with code ' + code))(); - else callback(output)(); - }); - }; -} - -exports.spawnFn = spawnFn; diff --git a/src/PursLoader/ChildProcess.purs b/src/PursLoader/ChildProcess.purs deleted file mode 100644 index 3bd960b..0000000 --- a/src/PursLoader/ChildProcess.purs +++ /dev/null @@ -1,23 +0,0 @@ -module PursLoader.ChildProcess - ( ChildProcess() - , spawn - ) where - -import Prelude (Unit(), ($)) - -import Control.Monad.Aff (Aff(), makeAff) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Exception (Error()) - -import Data.Function - -foreign import data ChildProcess :: ! - -spawn :: forall eff. String -> Array String -> Aff (cp :: ChildProcess | eff) String -spawn command args = makeAff $ runFn4 spawnFn command args - -foreign import spawnFn :: forall eff. Fn4 String - (Array String) - (Error -> Eff (cp :: ChildProcess | eff) Unit) - (String -> Eff (cp :: ChildProcess | eff) Unit) - (Eff (cp :: ChildProcess | eff) Unit) diff --git a/src/PursLoader/FS.js b/src/PursLoader/FS.js deleted file mode 100644 index 1a7f5b0..0000000 --- a/src/PursLoader/FS.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -// module PursLoader.FS - -var fs = require('fs'); - -var async = require('async'); - -function writeFileUtf8Fn(filepath, contents, errback, callback) { - return function(){ - fs.writeFile(filepath, contents, function(error){ - if (error) errback(error)(); - else callback()(); - }); - }; -} - -function findFileUtf8Fn(nothing, just, regex, filepaths, errback, callback) { - return function(){ - function findFile(filepath, callback) { - fs.readFile(filepath, {encoding: 'utf-8'}, function(error, result){ - if (error) callback(false); - else callback(regex.test(result)); - }); - } - - async.detect(filepaths, findFile, function(result){ - if (!result) callback(nothing)(); - else callback(just(result))(); - }); - }; -} - -exports.writeFileUtf8Fn = writeFileUtf8Fn; - -exports.findFileUtf8Fn = findFileUtf8Fn; diff --git a/src/PursLoader/FS.purs b/src/PursLoader/FS.purs deleted file mode 100644 index 969e3d0..0000000 --- a/src/PursLoader/FS.purs +++ /dev/null @@ -1,38 +0,0 @@ -module PursLoader.FS - ( FS() - , writeFileUtf8 - , findFileUtf8 - ) where - -import Prelude (Unit(), ($)) - -import Control.Monad.Aff (Aff(), makeAff) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Exception (Error()) - -import Data.Maybe (Maybe(..)) -import Data.String.Regex (Regex()) - -import Data.Function - -foreign import data FS :: ! - -writeFileUtf8 :: forall eff. String -> String -> Aff (fs :: FS | eff) Unit -writeFileUtf8 filepath contents = makeAff $ runFn4 writeFileUtf8Fn filepath contents - -foreign import writeFileUtf8Fn :: forall eff. Fn4 String - String - (Error -> Eff (fs :: FS | eff) Unit) - (Unit -> Eff (fs :: FS | eff) Unit) - (Eff (fs :: FS | eff) Unit) - -findFileUtf8 :: forall eff. Regex -> Array String -> Aff (fs :: FS | eff) (Maybe String) -findFileUtf8 regexp filepaths = makeAff $ runFn6 findFileUtf8Fn Nothing Just regexp filepaths - -foreign import findFileUtf8Fn :: forall eff. Fn6 (Maybe String) - (String -> Maybe String) - Regex - (Array String) - (Error -> Eff (fs :: FS | eff) Unit) - (Maybe String -> Eff (fs :: FS | eff) Unit) - (Eff (fs :: FS | eff) Unit) diff --git a/src/PursLoader/Glob.js b/src/PursLoader/Glob.js deleted file mode 100644 index 960ae9a..0000000 --- a/src/PursLoader/Glob.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -// module PursLoader.Glob - -var glob = require('glob'); - -var async = require('async'); - -function globAllFn(patterns, errback, callback) { - return function(){ - async.map(patterns, glob, function(error, result){ - if (error) errback(new Error(error))(); - else callback(result)(); - }); - }; -} - -exports.globAllFn = globAllFn; diff --git a/src/PursLoader/Glob.purs b/src/PursLoader/Glob.purs deleted file mode 100644 index 45eeb56..0000000 --- a/src/PursLoader/Glob.purs +++ /dev/null @@ -1,22 +0,0 @@ -module PursLoader.Glob - ( Glob() - , globAll - ) where - -import Prelude (Unit(), ($)) - -import Control.Monad.Aff (Aff(), makeAff) -import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Exception (Error()) - -import Data.Function - -foreign import data Glob :: ! - -globAll :: forall eff. Array String -> Aff (glob :: Glob | eff) (Array (Array String)) -globAll patterns = makeAff $ runFn3 globAllFn patterns - -foreign import globAllFn :: forall eff. Fn3 (Array String) - (Error -> Eff (glob :: Glob | eff) Unit) - ((Array (Array String)) -> Eff (glob :: Glob | eff) Unit) - (Eff (glob :: Glob | eff) Unit) diff --git a/src/PursLoader/Loader.purs b/src/PursLoader/Loader.purs index a91667c..0cd077d 100644 --- a/src/PursLoader/Loader.purs +++ b/src/PursLoader/Loader.purs @@ -4,122 +4,75 @@ module PursLoader.Loader , loaderFn ) where -import Prelude (Unit(), ($), (<>), (>>=), (<$>), (++), bind, flip, id, pure, return, unit, show) +import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (<<<), (++), bind, const) -import Control.Monad.Aff (Aff(), runAff) +import Control.Bind (join) import Control.Monad.Eff (Eff()) -import Control.Monad.Eff.Class (liftEff) -import Control.Monad.Eff.Exception (throwException, error, EXCEPTION()) +import Control.Monad.Eff.Exception (Error(), error) -import Data.Array ((!!), concat) +import Data.Array ((!!)) import Data.Function (Fn2(), mkFn2) -import Data.Maybe (Maybe(..), fromMaybe, maybe) -import Data.Either (Either(..)) -import Data.String (joinWith) -import Data.String.Regex (Regex(), match, noFlags, regex, test) -import Data.Traversable (sequence) -import Data.Foreign (F()) +import Data.Maybe (Maybe(..), maybe) +import Data.Either (either) +import Data.Foreign (Foreign()) import Data.Foreign.Class (read) +import Data.Foreign.Null (runNull) +import Data.String.Regex (Regex(), match, noFlags, regex) + +import Unsafe.Coerce (unsafeCoerce) + +import PursLoader.LoaderRef + ( LoaderRef() + , Loader() + , async + , cacheable + , query + , clearDependencies + , addDependency + , resourcePath + ) -import PursLoader.ChildProcess (ChildProcess(), spawn) -import PursLoader.FS (FS(), writeFileUtf8, findFileUtf8) -import PursLoader.Glob (Glob(), globAll) -import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query, clearDependencies, addDependency, resourcePath) import PursLoader.LoaderUtil (parseQuery) -import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions, Options(), output) +import PursLoader.Options (runOptions) +import PursLoader.Path (dirname, relative) -type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader, err :: EXCEPTION | eff) +type Effects eff = (loader :: Loader | eff) -moduleRegex :: Regex -moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } +type PurescriptWebpackPluginContext eff = { compile :: (Foreign -> Eff (Effects eff) Unit) -> Eff (Effects eff) Unit } -foreignRegex :: Regex -foreignRegex = regex "(?:^|\\n)\\s*foreign import\\s+" noFlags { ignoreCase = true } - -pscCommand :: String -pscCommand = "psc" - -psciCommand :: String -psciCommand = "psci" - -psciFilename :: String -psciFilename = ".psci" - -(!!!) :: forall a. Int -> Array a -> Maybe a -(!!!) = flip (!!) - -foreign import cwd :: String - -foreign import relative :: String -> String -> String - -foreign import resolve :: String -> String - -foreign import dirname :: String -> String - -foreign import joinPath :: String -> String -> String - -mkPsci :: Array (Array String) -> Array (Array String) -> String -mkPsci srcs ffis = joinWith "\n" ((loadModule <$> concat srcs) <> (loadForeign <$> concat ffis)) - where - loadModule :: String -> String - loadModule a = ":m " ++ relative cwd a - - loadForeign :: String -> String - loadForeign a = ":f " ++ relative cwd a - -findFFI :: forall eff. Array (Array String) -> String -> Aff (fs :: FS | eff) (Maybe String) -findFFI ffiss name = findFileUtf8 re (concat ffiss) - where - re = regex ("(?:^|\\n)//\\s*module\\s*" ++ name ++ "\\s*\\n") noFlags +loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit +loader ref source = do + callback <- async ref -loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String) -loader' ref source = do - liftEff $ cacheable ref + cacheable ref let parsed = parseQuery $ query ref - srcs = fromMaybe [] (loaderSrcOption parsed) - ffis = fromMaybe [] (loaderFFIOption parsed) - case read parsed :: F Options of - Left e -> liftEff (throwException (error (show e))) - Right opts -> do - let pscOpts = pscOptions opts + options = either (const Nothing) (Just <<< runOptions) (read parsed) - srcss <- globAll srcs - ffiss <- globAll ffis + moduleName = join $ match moduleRegex source >>= \as -> as !! 1 - let psciFile = mkPsci srcss ffiss + resourceDir = dirname (resourcePath ref) - writeFileUtf8 psciFilename psciFile + modulePath = (\opts -> relative resourceDir opts.pscBundle) <$> options - let moduleName = match moduleRegex source >>= (!!!) 1 >>= id - hasForeign = test foreignRegex source - outputDir = resolve (output opts) - resourceDir = dirname (resourcePath ref) - result = (\a -> "module.exports = require('" ++ relative resourceDir (joinPath outputDir a) ++ "');") <$> moduleName + result = (\path name -> "module.exports = require('" ++ path ++ "')['" ++ name ++ "'];") <$> modulePath <*> moduleName - liftEff do - clearDependencies ref - addDependency ref (resourcePath ref) - sequence $ (\src -> addDependency ref (resolve src)) <$> concat srcss + clearDependencies ref - foreignPath <- if hasForeign - then fromMaybe (pure Nothing) (findFFI ffiss <$> moduleName) - else pure Nothing + addDependency ref (resourcePath ref) - fromMaybe (pure unit) ((\path -> liftEff (addDependency ref path)) <$> foreignPath) - - spawn pscCommand (srcs <> pscOpts) + pluginContext.compile (\err -> maybe (callback (Just $ error "Failed to run loader") "") + (callback (compileError err)) result) + where + moduleRegex :: Regex + moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } - return result + pluginContext :: PurescriptWebpackPluginContext eff + pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext -loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit -loader ref source = do - callback <- async ref - runAff (\e -> callback (Just e) "") - (maybe (callback (Just (error "Loader has failed to run")) "") - (callback Nothing)) - (loader' ref source) + compileError :: Foreign -> Maybe Error + compileError value = either (const $ Just (error "Failed to compile")) ((<$>) error) (runNull <$> read value) loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) loaderFn = mkFn2 loader diff --git a/src/PursLoader/LoaderRef.purs b/src/PursLoader/LoaderRef.purs index 33c4f7e..87d6006 100644 --- a/src/PursLoader/LoaderRef.purs +++ b/src/PursLoader/LoaderRef.purs @@ -1,6 +1,7 @@ module PursLoader.LoaderRef ( LoaderRef() , Loader() + , AsyncCallback() , async , cacheable , query @@ -17,16 +18,18 @@ import Control.Monad.Eff.Exception (Error()) import Data.Function (Fn3(), runFn3) import Data.Maybe (Maybe(), fromMaybe, isJust) +type AsyncCallback eff = Maybe Error -> String -> Eff (loader :: Loader | eff) Unit + data LoaderRef foreign import data Loader :: ! -foreign import asyncFn :: forall eff a. Fn3 (Maybe Error -> Boolean) - (Error -> Maybe Error -> Error) - LoaderRef - (Eff (loader :: Loader | eff) (Maybe Error -> a -> Eff (loader :: Loader | eff) Unit)) +foreign import asyncFn :: forall eff. Fn3 (Maybe Error -> Boolean) + (Error -> Maybe Error -> Error) + LoaderRef + (Eff (loader :: Loader | eff) (AsyncCallback eff)) -async :: forall eff a. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> a -> Eff (loader :: Loader | eff) Unit) +async :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> String -> Eff (loader :: Loader | eff) Unit) async ref = runFn3 asyncFn isJust fromMaybe ref foreign import cacheable :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit diff --git a/src/PursLoader/Options.purs b/src/PursLoader/Options.purs index 3657d1a..132096c 100644 --- a/src/PursLoader/Options.purs +++ b/src/PursLoader/Options.purs @@ -1,122 +1,30 @@ module PursLoader.Options - ( pscOptions - , loaderSrcOption - , loaderFFIOption - , Options() - , output + ( Options() + , runOptions ) where -import Prelude ((<>), (<$>), (<<<), (++), (<*>), ($), const, id) +import Prelude ((<$>), (<<<), id) -import Data.Array (concat) -import Data.Either (either) +import Data.Foreign.Class (IsForeign, readProp) +import Data.Foreign.NullOrUndefined (runNullOrUndefined) +import Data.Maybe (maybe) -import Data.Foreign (Foreign()) -import Data.Foreign.Class (IsForeign, read, readProp) -import Data.Foreign.NullOrUndefined (NullOrUndefined(..), runNullOrUndefined) +import PursLoader.Path (joinPath) -import Data.Maybe (Maybe(..), maybe, fromMaybe) +newtype Options = Options { pscBundle :: String } -noPreludeOpt :: String -noPreludeOpt = "no-prelude" +type Options_ = { pscBundle :: String } -noOptsOpt :: String -noOptsOpt = "no-opts" - -noMagicDoOpt :: String -noMagicDoOpt = "no-magic-do" - -noTcoOpt :: String -noTcoOpt = "no-tco" - -verboseErrorsOpt :: String -verboseErrorsOpt = "verbose-errors" - -outputOpt :: String -outputOpt = "output" - -commentsOpt :: String -commentsOpt = "comments" - -noPrefixOpt :: String -noPrefixOpt = "no-prefix" - -requirePathOpt :: String -requirePathOpt = "require-path" - -srcOpt :: String -srcOpt = "src" - -ffiOpt :: String -ffiOpt = "ffi" - -newtype Options - = Options { noPrelude :: NullOrUndefined Boolean - , noOpts :: NullOrUndefined Boolean - , noMagicDo :: NullOrUndefined Boolean - , noTco :: NullOrUndefined Boolean - , verboseErrors :: NullOrUndefined Boolean - , comments :: NullOrUndefined Boolean - , output :: String - , noPrefix :: NullOrUndefined Boolean - , requirePath :: String - , src :: NullOrUndefined (Array String) - , ffi :: NullOrUndefined (Array String) - } - -output :: Options -> String -output (Options o) = o.output +runOptions :: Options -> Options_ +runOptions (Options options) = options instance isForeignOptions :: IsForeign Options where - read obj = Options <$> ({ noPrelude: _ - , noOpts: _ - , noMagicDo: _ - , noTco: _ - , verboseErrors: _ - , comments: _ - , output: _ - , noPrefix: _ - , requirePath: "../" - , src: _ - , ffi: _ - } <$> readProp noPreludeOpt obj - <*> readProp noOptsOpt obj - <*> readProp noMagicDoOpt obj - <*> readProp noTcoOpt obj - <*> readProp verboseErrorsOpt obj - <*> readProp commentsOpt obj - <*> (maybe "output" id <<< runNullOrUndefined <$> readProp outputOpt obj) - <*> readProp noPrefixOpt obj - <*> readProp srcOpt obj - <*> readProp ffiOpt obj) - -class LoaderOption a where - opt :: String -> NullOrUndefined a -> Array String - -instance booleanLoaderOption :: LoaderOption Boolean where - opt key val = maybe [] (\a -> if a then ["--" ++ key] else []) (runNullOrUndefined val) - -instance stringLoaderOption :: LoaderOption String where - opt key val = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) (runNullOrUndefined val) - -instance arrayLoaderOption :: (LoaderOption a) => LoaderOption (Array a) where - opt key val = concat (opt key <$> (NullOrUndefined <<< Just) - <$> (fromMaybe [] (runNullOrUndefined val))) - -pscOptions :: Options -> Array String -pscOptions (Options a) = opt noPreludeOpt a.noPrelude <> - opt noOptsOpt a.noOpts <> - opt noMagicDoOpt a.noMagicDo <> - opt noTcoOpt a.noTco <> - opt verboseErrorsOpt a.verboseErrors <> - opt commentsOpt a.comments <> - opt outputOpt (NullOrUndefined $ Just a.output) <> - opt noPrefixOpt a.noPrefix <> - opt requirePathOpt (NullOrUndefined $ Just a.requirePath) <> - opt ffiOpt a.ffi - -loaderSrcOption :: Foreign -> Maybe (Array String) -loaderSrcOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.src) (read query) - -loaderFFIOption :: Foreign -> Maybe (Array String) -loaderFFIOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.ffi) (read query) + read obj = + Options <$> ({ pscBundle: _ } + <$> (maybe pscBundleDefault id <<< runNullOrUndefined <$> readProp pscBundle obj)) + where + pscBundle :: String + pscBundle = "pscBundle" + + pscBundleDefault :: String + pscBundleDefault = joinPath "output" "bundle.js" diff --git a/src/PursLoader/Loader.js b/src/PursLoader/Path.js similarity index 82% rename from src/PursLoader/Loader.js rename to src/PursLoader/Path.js index 45e9c2f..878f256 100644 --- a/src/PursLoader/Loader.js +++ b/src/PursLoader/Path.js @@ -1,27 +1,22 @@ 'use strict' -// module PursLoader.Loader +// module PursLoader.Path var path = require('path'); -var cwd = process.cwd(); - function relative(from) { return function(to){ return path.relative(from, to); }; } +exports.relative = relative; + function joinPath(a) { return function(b) { return path.join(a, b); }; } - -exports.cwd = cwd; - -exports.relative = relative; - exports.joinPath = joinPath; exports.resolve = path.resolve; diff --git a/src/PursLoader/Path.purs b/src/PursLoader/Path.purs new file mode 100644 index 0000000..98cad5a --- /dev/null +++ b/src/PursLoader/Path.purs @@ -0,0 +1,14 @@ +module PursLoader.Path + ( relative + , resolve + , dirname + , joinPath + ) where + +foreign import relative :: String -> String -> String + +foreign import resolve :: String -> String + +foreign import dirname :: String -> String + +foreign import joinPath :: String -> String -> String -- 2.41.0