From 460393439a8dd7d94fe02a2013e96c9146282bf1 Mon Sep 17 00:00:00 2001 From: eric thul Date: Wed, 24 Feb 2016 22:53:40 -0500 Subject: Adds dependencies of modules process by the loader. The module file path and dependency graph information is provided by the purescript-webpack-plugin. Resolves #37 --- src/PursLoader/Loader.purs | 92 +++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 34 deletions(-) (limited to 'src/PursLoader/Loader.purs') diff --git a/src/PursLoader/Loader.purs b/src/PursLoader/Loader.purs index affce53..f78153f 100644 --- a/src/PursLoader/Loader.purs +++ b/src/PursLoader/Loader.purs @@ -4,25 +4,27 @@ module PursLoader.Loader , loaderFn ) where -import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (<<<), (++), bind, const) +import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (++), bind, const, id, pure, unit) +import Control.Apply ((*>)) import Control.Bind (join) -import Control.Monad.Eff (Eff()) +import Control.Monad.Eff (Eff(), foreachE) import Control.Monad.Eff.Exception (Error(), error) import Data.Array ((!!)) +import Data.Bifunctor (lmap) +import Data.Either (Either(..), either) +import Data.Foreign.Class (read) import Data.Function (Fn2(), mkFn2) 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.Nullable (toMaybe) import Data.String.Regex (Regex(), match, noFlags, regex) import Unsafe.Coerce (unsafeCoerce) import PursLoader.LoaderRef - ( LoaderRef() + ( AsyncCallback() + , LoaderRef() , Loader() , async , cacheable @@ -33,46 +35,68 @@ import PursLoader.LoaderRef ) import PursLoader.LoaderUtil (parseQuery) -import PursLoader.Options (runOptions) +import PursLoader.Options (Options(..)) import PursLoader.Path (dirname, relative) +import PursLoader.Plugin as Plugin type Effects eff = (loader :: Loader | eff) -type PurescriptWebpackPluginContext eff = { compile :: (Foreign -> Eff (Effects eff) Unit) -> Eff (Effects eff) Unit } - loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit loader ref source = do callback <- async ref cacheable ref - let parsed = parseQuery $ query ref - - options = either (const Nothing) (Just <<< runOptions) (read parsed) - - moduleName = join $ match moduleRegex source >>= \as -> as !! 1 - - resourceDir = dirname (resourcePath ref) - - modulePath = (\opts -> relative resourceDir opts.bundleOutput) <$> options - - result = (\path name -> "module.exports = require('" ++ path ++ "')['" ++ name ++ "'];") <$> modulePath <*> moduleName - - clearDependencies ref - - addDependency ref (resourcePath ref) - - pluginContext.compile (\err -> maybe (callback (Just $ error "Failed to run loader") "") - (callback (compileError err)) result) + pluginContext.compile (compile callback) where - moduleRegex :: Regex - moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } - - pluginContext :: PurescriptWebpackPluginContext eff + pluginContext :: Plugin.Context (Effects eff) pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext - compileError :: Foreign -> Maybe Error - compileError value = either (const $ Just (error "Failed to compile")) ((<$>) error) (runNull <$> read value) + compile :: AsyncCallback eff -> Plugin.Compile (Effects eff) + compile callback error' { srcMap, ffiMap, graph } = do + clearDependencies ref + + addDependency ref (resourcePath ref) + + either (\err -> callback (Just err) "") id + (handle <$> name <*> dependencies <*> exports) + where + handle :: String -> Array String -> String -> Eff (Effects eff) Unit + handle name' deps res = do + addTransitive name' + foreachE deps addTransitive + callback (toMaybe error') res + + exports :: Either Error String + exports = (\a b -> "module.exports = require('" ++ a ++ "')['" ++ b ++ "'];") <$> path <*> name + + dependencies :: Either Error (Array String) + dependencies = name >>= Plugin.dependenciesOf graph + + addTransitive :: String -> Eff (Effects eff) Unit + addTransitive dep = addDep (Plugin.get srcMap dep) *> addDep (Plugin.get ffiMap dep) + where + addDep :: Maybe String -> Eff (Effects eff) Unit + addDep = maybe (pure unit) (addDependency ref) + + name :: Either Error String + name = + maybe (Left $ error "Failed to parse module name") Right + (join $ match re source >>= \as -> as !! 1) + where + re :: Regex + re = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } + + path :: Either Error String + path = (\(Options opts) -> relative resourceDir opts.bundleOutput) <$> options + where + options :: Either Error Options + options = + lmap (const $ error "Failed to parse loader query") + (read $ parseQuery (query ref)) + + resourceDir :: String + resourceDir = dirname (resourcePath ref) loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) loaderFn = mkFn2 loader -- cgit v1.2.3