```
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.
"webpack": "^1.8.4"
},
"dependencies": {
+ "async": "^1.3.0",
"glob": "^5.0.3",
"loader-utils": "^0.2.6"
}
--- /dev/null
+module PursLoader.FS
+ ( FS()
+ , writeFileUtf8
+ ) where
+
+import Control.Monad.Aff (Aff(), makeAff)
+import Control.Monad.Eff (Eff())
+import Control.Monad.Eff.Exception (Error())
+
+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 """
+function writeFileUtf8Fn(filepath, contents, errback, callback) {
+ return function(){
+ var fs = require('fs');
+
+ fs.writeFile(filepath, contents, function(error){
+ if (error) errback(error)();
+ else callback()();
+ });
+ };
+}
+""" :: forall eff. Fn4 String
+ String
+ (Error -> Eff (fs :: FS | eff) Unit)
+ (Unit -> Eff (fs :: FS | eff) Unit)
+ (Eff (fs :: FS | eff) Unit)
--- /dev/null
+module PursLoader.Glob
+ ( Glob()
+ , globAll
+ ) where
+
+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. [String] -> Aff (glob :: Glob | eff) [[String]]
+globAll patterns = makeAff $ runFn3 globAllFn patterns
+
+foreign import globAllFn """
+function globAllFn(patterns, errback, callback) {
+ return function(){
+ var glob = require('glob');
+
+ var async = require('async');
+
+ async.map(patterns, glob, function(error, result){
+ if (error) errback(new Error(error))();
+ else callback(result)();
+ });
+ };
+}
+""" :: forall eff. Fn3 [String]
+ (Error -> Eff (glob :: Glob | eff) Unit)
+ ([[String]] -> Eff (glob :: Glob | eff) Unit)
+ (Eff (glob :: Glob | eff) Unit)
import Control.Monad.Eff.Class (liftEff)
import Control.Monad.Eff.Exception (error)
-import Data.Array ((!!))
+import Data.Array ((!!), concat)
import Data.Function (Fn2(), mkFn2)
import Data.Maybe (Maybe(..), fromMaybe, maybe)
+import Data.String (joinWith)
import Data.String.Regex (match, noFlags, regex)
import PursLoader.ChildProcess (ChildProcess(), spawn)
+import PursLoader.FS (FS(), writeFileUtf8)
+import PursLoader.Glob (Glob(), globAll)
import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query)
-import PursLoader.LoaderUtil (getRemainingRequest, parseQuery)
-import PursLoader.Options (loaderSrcOption, pscOptions)
+import PursLoader.LoaderUtil (parseQuery)
+import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions)
-type Effects eff = (loader :: Loader, cp :: ChildProcess | eff)
+type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader | eff)
moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true }
pscCommand = "psc"
+psciCommand = "psci"
+
+psciFilename = ".psci"
+
(!!!) = flip (!!)
+foreign import cwd "var cwd = process.cwd();" :: String
+
+foreign import relative """
+function relative(from) {
+ return function(to){
+ var path = require('path');
+ return path.relative(from, to);
+ };
+}
+""" :: String -> String -> String
+
+mkPsci :: [[String]] -> [[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
+
loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String)
loader' ref source = do
liftEff $ cacheable ref
- let request = getRemainingRequest ref
- parsed = parseQuery $ query ref
+ let parsed = parseQuery $ query ref
srcs = fromMaybe [] (loaderSrcOption parsed)
+ ffis = fromMaybe [] (loaderFFIOption parsed)
opts = pscOptions parsed
- moduleName = match moduleRegex source >>= (!!!) 1
- result = (\a -> "module.exports = require('" ++ a ++ "');") <$> moduleName
spawn pscCommand (srcs <> opts)
+
+ srcss <- globAll srcs
+ ffiss <- globAll ffis
+
+ let psciFile = mkPsci srcss ffiss
+
+ writeFileUtf8 psciFilename psciFile
+
+ let moduleName = match moduleRegex source >>= (!!!) 1
+ result = (\a -> "module.exports = require('" ++ a ++ "');") <$> moduleName
+
return result
loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit
module PursLoader.LoaderUtil
- ( getRemainingRequest
- , parseQuery
+ ( parseQuery
) where
import Data.Foreign (Foreign())
import PursLoader.LoaderRef (LoaderRef())
-foreign import getRemainingRequest """
-function getRemainingRequest(ref){
- var loaderUtils = require('loader-utils');
- return loaderUtils.getRemainingRequest(ref);
-}""" :: LoaderRef -> String
-
foreign import parseQuery """
function parseQuery(query){
var loaderUtils = require('loader-utils');
module PursLoader.Options
( pscOptions
, loaderSrcOption
+ , loaderFFIOption
) where
import Data.Array (concat)
loaderSrcOption :: Foreign -> Maybe [String]
loaderSrcOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.src) (read query)
+
+loaderFFIOption :: Foreign -> Maybe [String]
+loaderFFIOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.ffi) (read query)
var webpack = require('webpack');
+var packageJson = require('./package.json');
+
var noErrorsPlugin = webpack.NoErrorsPlugin;
var dedupePlugin = webpack.optimize.DedupePlugin;
= { cache: true
, target: 'node'
, entry: { index: './entry' }
- , externals: { 'glob': 'commonjs glob'
- , 'loader-utils': 'commonjs loader-utils'
- }
+ , externals: Object.keys(packageJson.dependencies).reduce(function(b, a){
+ b[a] = 'commonjs ' + a;
+ return b;
+ }, {})
, output: { path: __dirname
, filename: '[name].js'
, libraryTarget: 'commonjs2'