]> git.immae.eu Git - github/fretlink/purs-loader.git/blob - src/PursLoader/Loader.purs
Bumping version number to 0.6.0-beta.1
[github/fretlink/purs-loader.git] / src / PursLoader / Loader.purs
1 module PursLoader.Loader
2 ( Effects()
3 , loader
4 , loaderFn
5 ) where
6
7 import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (++), bind, const, id, pure, unit)
8
9 import Control.Apply ((*>))
10 import Control.Bind (join)
11 import Control.Monad.Eff (Eff(), foreachE)
12 import Control.Monad.Eff.Exception (Error(), error)
13
14 import Data.Array ((!!))
15 import Data.Bifunctor (lmap)
16 import Data.Either (Either(..), either)
17 import Data.Foreign.Class (read)
18 import Data.Function (Fn2(), mkFn2)
19 import Data.Maybe (Maybe(..), maybe)
20 import Data.Nullable (toMaybe)
21 import Data.String.Regex (Regex(), match, noFlags, regex)
22
23 import Unsafe.Coerce (unsafeCoerce)
24
25 import PursLoader.LoaderRef
26 ( AsyncCallback()
27 , LoaderRef()
28 , Loader()
29 , async
30 , cacheable
31 , query
32 , clearDependencies
33 , addDependency
34 , resourcePath
35 )
36
37 import PursLoader.Debug (debug)
38 import PursLoader.LoaderUtil (parseQuery)
39 import PursLoader.Options (Options(..))
40 import PursLoader.Path (dirname, relative)
41 import PursLoader.Plugin as Plugin
42
43 type Effects eff = (loader :: Loader | eff)
44
45 loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit
46 loader ref source = do
47 callback <- async ref
48
49 cacheable ref
50
51 debug "Invoke PureScript plugin compilation"
52
53 pluginContext.compile (compile callback)
54 where
55 pluginContext :: Plugin.Context (Effects eff)
56 pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext
57
58 compile :: AsyncCallback eff -> Plugin.Compile (Effects eff)
59 compile callback error' { srcMap, ffiMap, graph } = do
60 clearDependencies ref
61
62 either (const $ pure unit) (\a -> debug ("Adding PureScript dependency " ++ a)) name
63
64 addDependency ref (resourcePath ref)
65
66 either (\err -> callback (Just err) "") id
67 (handle <$> name <*> dependencies <*> exports)
68 where
69 handle :: String -> Array String -> String -> Eff (Effects eff) Unit
70 handle name' deps res = do
71 debug ("Adding PureScript transitive dependencies for " ++ name')
72 addTransitive name'
73 foreachE deps addTransitive
74 callback (toMaybe error') res
75
76 exports :: Either Error String
77 exports = (\a b -> "module.exports = require('" ++ a ++ "')['" ++ b ++ "'];") <$> path <*> name
78
79 dependencies :: Either Error (Array String)
80 dependencies = name >>= Plugin.dependenciesOf graph
81
82 addTransitive :: String -> Eff (Effects eff) Unit
83 addTransitive dep = addDep (Plugin.get srcMap dep) *> addDep (Plugin.get ffiMap dep)
84 where
85 addDep :: Maybe String -> Eff (Effects eff) Unit
86 addDep = maybe (pure unit) (addDependency ref)
87
88 name :: Either Error String
89 name =
90 maybe (Left $ error "Failed to parse module name") Right
91 (join $ match re source >>= \as -> as !! 1)
92 where
93 re :: Regex
94 re = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true }
95
96 path :: Either Error String
97 path = (\(Options opts) -> relative resourceDir opts.bundleOutput) <$> options
98 where
99 options :: Either Error Options
100 options =
101 lmap (const $ error "Failed to parse loader query")
102 (read $ parseQuery (query ref))
103
104 resourceDir :: String
105 resourceDir = dirname (resourcePath ref)
106
107 loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit)
108 loaderFn = mkFn2 loader