]>
Commit | Line | Data |
---|---|---|
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 |