aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/PursLoader/Loader.purs
diff options
context:
space:
mode:
Diffstat (limited to 'src/PursLoader/Loader.purs')
-rw-r--r--src/PursLoader/Loader.purs92
1 files changed, 58 insertions, 34 deletions
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
4 , loaderFn 4 , loaderFn
5 ) where 5 ) where
6 6
7import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (<<<), (++), bind, const) 7import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (++), bind, const, id, pure, unit)
8 8
9import Control.Apply ((*>))
9import Control.Bind (join) 10import Control.Bind (join)
10import Control.Monad.Eff (Eff()) 11import Control.Monad.Eff (Eff(), foreachE)
11import Control.Monad.Eff.Exception (Error(), error) 12import Control.Monad.Eff.Exception (Error(), error)
12 13
13import Data.Array ((!!)) 14import Data.Array ((!!))
15import Data.Bifunctor (lmap)
16import Data.Either (Either(..), either)
17import Data.Foreign.Class (read)
14import Data.Function (Fn2(), mkFn2) 18import Data.Function (Fn2(), mkFn2)
15import Data.Maybe (Maybe(..), maybe) 19import Data.Maybe (Maybe(..), maybe)
16import Data.Either (either) 20import Data.Nullable (toMaybe)
17import Data.Foreign (Foreign())
18import Data.Foreign.Class (read)
19import Data.Foreign.Null (runNull)
20import Data.String.Regex (Regex(), match, noFlags, regex) 21import Data.String.Regex (Regex(), match, noFlags, regex)
21 22
22import Unsafe.Coerce (unsafeCoerce) 23import Unsafe.Coerce (unsafeCoerce)
23 24
24import PursLoader.LoaderRef 25import PursLoader.LoaderRef
25 ( LoaderRef() 26 ( AsyncCallback()
27 , LoaderRef()
26 , Loader() 28 , Loader()
27 , async 29 , async
28 , cacheable 30 , cacheable
@@ -33,46 +35,68 @@ import PursLoader.LoaderRef
33 ) 35 )
34 36
35import PursLoader.LoaderUtil (parseQuery) 37import PursLoader.LoaderUtil (parseQuery)
36import PursLoader.Options (runOptions) 38import PursLoader.Options (Options(..))
37import PursLoader.Path (dirname, relative) 39import PursLoader.Path (dirname, relative)
40import PursLoader.Plugin as Plugin
38 41
39type Effects eff = (loader :: Loader | eff) 42type Effects eff = (loader :: Loader | eff)
40 43
41type PurescriptWebpackPluginContext eff = { compile :: (Foreign -> Eff (Effects eff) Unit) -> Eff (Effects eff) Unit }
42
43loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit 44loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit
44loader ref source = do 45loader ref source = do
45 callback <- async ref 46 callback <- async ref
46 47
47 cacheable ref 48 cacheable ref
48 49
49 let parsed = parseQuery $ query ref 50 pluginContext.compile (compile callback)
50
51 options = either (const Nothing) (Just <<< runOptions) (read parsed)
52
53 moduleName = join $ match moduleRegex source >>= \as -> as !! 1
54
55 resourceDir = dirname (resourcePath ref)
56
57 modulePath = (\opts -> relative resourceDir opts.bundleOutput) <$> options
58
59 result = (\path name -> "module.exports = require('" ++ path ++ "')['" ++ name ++ "'];") <$> modulePath <*> moduleName
60
61 clearDependencies ref
62
63 addDependency ref (resourcePath ref)
64
65 pluginContext.compile (\err -> maybe (callback (Just $ error "Failed to run loader") "")
66 (callback (compileError err)) result)
67 where 51 where
68 moduleRegex :: Regex 52 pluginContext :: Plugin.Context (Effects eff)
69 moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true }
70
71 pluginContext :: PurescriptWebpackPluginContext eff
72 pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext 53 pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext
73 54
74 compileError :: Foreign -> Maybe Error 55 compile :: AsyncCallback eff -> Plugin.Compile (Effects eff)
75 compileError value = either (const $ Just (error "Failed to compile")) ((<$>) error) (runNull <$> read value) 56 compile callback error' { srcMap, ffiMap, graph } = do
57 clearDependencies ref
58
59 addDependency ref (resourcePath ref)
60
61 either (\err -> callback (Just err) "") id
62 (handle <$> name <*> dependencies <*> exports)
63 where
64 handle :: String -> Array String -> String -> Eff (Effects eff) Unit
65 handle name' deps res = do
66 addTransitive name'
67 foreachE deps addTransitive
68 callback (toMaybe error') res
69
70 exports :: Either Error String
71 exports = (\a b -> "module.exports = require('" ++ a ++ "')['" ++ b ++ "'];") <$> path <*> name
72
73 dependencies :: Either Error (Array String)
74 dependencies = name >>= Plugin.dependenciesOf graph
75
76 addTransitive :: String -> Eff (Effects eff) Unit
77 addTransitive dep = addDep (Plugin.get srcMap dep) *> addDep (Plugin.get ffiMap dep)
78 where
79 addDep :: Maybe String -> Eff (Effects eff) Unit
80 addDep = maybe (pure unit) (addDependency ref)
81
82 name :: Either Error String
83 name =
84 maybe (Left $ error "Failed to parse module name") Right
85 (join $ match re source >>= \as -> as !! 1)
86 where
87 re :: Regex
88 re = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true }
89
90 path :: Either Error String
91 path = (\(Options opts) -> relative resourceDir opts.bundleOutput) <$> options
92 where
93 options :: Either Error Options
94 options =
95 lmap (const $ error "Failed to parse loader query")
96 (read $ parseQuery (query ref))
97
98 resourceDir :: String
99 resourceDir = dirname (resourcePath ref)
76 100
77loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) 101loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit)
78loaderFn = mkFn2 loader 102loaderFn = mkFn2 loader