]>
Commit | Line | Data |
---|---|---|
1 | module PursLoader.Loader | |
2 | ( Effects() | |
3 | , Effects_() | |
4 | , loader | |
5 | , loaderFn | |
6 | ) where | |
7 | ||
8 | import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (++), (<<<), bind, const, id, pure, unit, void) | |
9 | ||
10 | import Control.Bind (join) | |
11 | import Control.Monad.Eff (Eff(), foreachE) | |
12 | import Control.Monad.Eff.Console (CONSOLE()) | |
13 | import Control.Monad.Eff.Exception (EXCEPTION(), Error(), error, message) | |
14 | ||
15 | import Data.Array ((!!)) | |
16 | import Data.Either (Either(..), either) | |
17 | import Data.Function (Fn2(), mkFn2) | |
18 | import Data.Maybe (maybe) | |
19 | import Data.Nullable (toMaybe) | |
20 | import Data.String.Regex (Regex(), match, noFlags, regex) | |
21 | ||
22 | import Node.Encoding (Encoding(UTF8)) | |
23 | import Node.Process (stderr) | |
24 | import Node.Stream (writeString) | |
25 | ||
26 | import Unsafe.Coerce (unsafeCoerce) | |
27 | ||
28 | import PursLoader.LoaderRef | |
29 | ( AsyncCallback() | |
30 | , LoaderRef() | |
31 | , Loader() | |
32 | , async | |
33 | , cacheable | |
34 | , addDependency | |
35 | , resourcePath | |
36 | ) | |
37 | ||
38 | import PursLoader.Debug (debug) | |
39 | import PursLoader.Path (dirname, joinPath, relative) | |
40 | import PursLoader.Plugin as Plugin | |
41 | ||
42 | type Effects eff = (console :: CONSOLE, err :: EXCEPTION | eff) | |
43 | ||
44 | type Effects_ eff = Effects (loader :: Loader | eff) | |
45 | ||
46 | loader :: forall eff. LoaderRef -> String -> Eff (Effects_ eff) Unit | |
47 | loader ref source = do | |
48 | callback <- async ref | |
49 | ||
50 | cacheable ref | |
51 | ||
52 | debug "Invoke PureScript plugin compilation" | |
53 | ||
54 | pluginContext.compile (compile callback) | |
55 | where | |
56 | pluginContext :: Plugin.Context (Effects_ eff) | |
57 | pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext | |
58 | ||
59 | compile :: AsyncCallback (Effects eff) -> Plugin.Compile (Effects_ eff) | |
60 | compile callback error' graph output = do | |
61 | either (const $ pure unit) (\a -> debug ("Adding PureScript dependency " ++ a)) name | |
62 | ||
63 | addDependency ref (resourcePath ref) | |
64 | ||
65 | void $ writeString stderr UTF8 output (pure unit) | |
66 | ||
67 | maybe (pure unit) (\a -> void $ writeString stderr UTF8 (message a) (pure unit)) (toMaybe error') | |
68 | ||
69 | either (const $ callback (pure fixedError) "") id | |
70 | (handle <$> name <*> dependencies <*> exports) | |
71 | where | |
72 | fixedError :: Error | |
73 | fixedError = error "PureScript compilation has failed." | |
74 | ||
75 | handle :: String -> Array String -> String -> Eff (Effects_ eff) Unit | |
76 | handle name' deps res = do | |
77 | debug ("Adding PureScript dependencies for " ++ name') | |
78 | foreachE deps (addDependency ref) | |
79 | debug "Generated loader result" | |
80 | debug res | |
81 | callback (const fixedError <$> toMaybe error') res | |
82 | ||
83 | exports :: Either Error String | |
84 | exports = | |
85 | if pluginContext.options.bundle | |
86 | then bundleExport <$> name | |
87 | else moduleExport <<< modulePath <$> name | |
88 | where | |
89 | bundleExport :: String -> String | |
90 | bundleExport name' = "module.exports = require('" ++ path ++ "')['" ++ name' ++ "'];" | |
91 | where | |
92 | path :: String | |
93 | path = relative resourceDir pluginContext.options.bundleOutput | |
94 | ||
95 | moduleExport :: String -> String | |
96 | moduleExport path = "module.exports = require('" ++ path ++ "');" | |
97 | ||
98 | modulePath :: String -> String | |
99 | modulePath = relative resourceDir <<< joinPath pluginContext.options.output | |
100 | ||
101 | resourceDir :: String | |
102 | resourceDir = dirname (resourcePath ref) | |
103 | ||
104 | dependencies :: Either Error (Array String) | |
105 | dependencies = Plugin.dependenciesOf graph (resourcePath ref) | |
106 | ||
107 | name :: Either Error String | |
108 | name = | |
109 | maybe (Left $ error "Failed to parse module name") Right | |
110 | (join $ match re source >>= \as -> as !! 1) | |
111 | where | |
112 | re :: Regex | |
113 | re = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } | |
114 | ||
115 | loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects_ eff) Unit) | |
116 | loaderFn = mkFn2 loader |