diff options
Diffstat (limited to 'src/PursLoader/Loader.purs')
-rw-r--r-- | src/PursLoader/Loader.purs | 133 |
1 files changed, 46 insertions, 87 deletions
diff --git a/src/PursLoader/Loader.purs b/src/PursLoader/Loader.purs index 205d3eb..affce53 100644 --- a/src/PursLoader/Loader.purs +++ b/src/PursLoader/Loader.purs | |||
@@ -4,116 +4,75 @@ module PursLoader.Loader | |||
4 | , loaderFn | 4 | , loaderFn |
5 | ) where | 5 | ) where |
6 | 6 | ||
7 | import Prelude (Unit(), ($), (<>), (>>=), (<$>), (++), bind, flip, id, pure, return, unit, show) | 7 | import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (<<<), (++), bind, const) |
8 | 8 | ||
9 | import Control.Monad.Aff (Aff(), runAff) | 9 | import Control.Bind (join) |
10 | import Control.Monad.Eff (Eff()) | 10 | import Control.Monad.Eff (Eff()) |
11 | import Control.Monad.Eff.Class (liftEff) | 11 | import Control.Monad.Eff.Exception (Error(), error) |
12 | import Control.Monad.Eff.Exception (throwException, error, EXCEPTION()) | ||
13 | 12 | ||
14 | import Data.Array ((!!), concat) | 13 | import Data.Array ((!!)) |
15 | import Data.Function (Fn2(), mkFn2) | 14 | import Data.Function (Fn2(), mkFn2) |
16 | import Data.Maybe (Maybe(..), fromMaybe, maybe) | 15 | import Data.Maybe (Maybe(..), maybe) |
17 | import Data.Either (Either(..)) | 16 | import Data.Either (either) |
18 | import Data.String (joinWith) | 17 | import Data.Foreign (Foreign()) |
19 | import Data.String.Regex (match, noFlags, regex, test) | ||
20 | import Data.Traversable (sequence) | ||
21 | import Data.Foreign (F()) | ||
22 | import Data.Foreign.Class (read) | 18 | import Data.Foreign.Class (read) |
19 | import Data.Foreign.Null (runNull) | ||
20 | import Data.String.Regex (Regex(), match, noFlags, regex) | ||
21 | |||
22 | import Unsafe.Coerce (unsafeCoerce) | ||
23 | |||
24 | import PursLoader.LoaderRef | ||
25 | ( LoaderRef() | ||
26 | , Loader() | ||
27 | , async | ||
28 | , cacheable | ||
29 | , query | ||
30 | , clearDependencies | ||
31 | , addDependency | ||
32 | , resourcePath | ||
33 | ) | ||
23 | 34 | ||
24 | import PursLoader.ChildProcess (ChildProcess(), spawn) | ||
25 | import PursLoader.FS (FS(), writeFileUtf8, findFileUtf8) | ||
26 | import PursLoader.Glob (Glob(), globAll) | ||
27 | import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query, clearDependencies, addDependency, resourcePath) | ||
28 | import PursLoader.LoaderUtil (parseQuery) | 35 | import PursLoader.LoaderUtil (parseQuery) |
29 | import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions, Options(), output) | 36 | import PursLoader.Options (runOptions) |
37 | import PursLoader.Path (dirname, relative) | ||
30 | 38 | ||
31 | type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader, err :: EXCEPTION | eff) | 39 | type Effects eff = (loader :: Loader | eff) |
32 | 40 | ||
33 | moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } | 41 | type PurescriptWebpackPluginContext eff = { compile :: (Foreign -> Eff (Effects eff) Unit) -> Eff (Effects eff) Unit } |
34 | 42 | ||
35 | foreignRegex = regex "(?:^|\\n)\\s*foreign import\\s+" noFlags { ignoreCase = true } | 43 | loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit |
36 | 44 | loader ref source = do | |
37 | pscCommand = "psc" | 45 | callback <- async ref |
38 | |||
39 | psciCommand = "psci" | ||
40 | |||
41 | psciFilename = ".psci" | ||
42 | |||
43 | (!!!) = flip (!!) | ||
44 | |||
45 | foreign import cwd :: String | ||
46 | |||
47 | foreign import relative :: String -> String -> String | ||
48 | |||
49 | foreign import resolve :: String -> String | ||
50 | |||
51 | foreign import dirname :: String -> String | ||
52 | |||
53 | foreign import joinPath :: String -> String -> String | ||
54 | |||
55 | mkPsci :: Array (Array String) -> Array (Array String) -> String | ||
56 | mkPsci srcs ffis = joinWith "\n" ((loadModule <$> concat srcs) <> (loadForeign <$> concat ffis)) | ||
57 | where | ||
58 | loadModule :: String -> String | ||
59 | loadModule a = ":m " ++ relative cwd a | ||
60 | |||
61 | loadForeign :: String -> String | ||
62 | loadForeign a = ":f " ++ relative cwd a | ||
63 | |||
64 | findFFI :: forall eff. Array (Array String) -> String -> Aff (fs :: FS | eff) (Maybe String) | ||
65 | findFFI ffiss name = findFileUtf8 re (concat ffiss) | ||
66 | where | ||
67 | re = regex ("(?:^|\\n)//\\s*module\\s*" ++ name ++ "\\s*\\n") noFlags | ||
68 | 46 | ||
69 | loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String) | 47 | cacheable ref |
70 | loader' ref source = do | ||
71 | liftEff $ cacheable ref | ||
72 | 48 | ||
73 | let parsed = parseQuery $ query ref | 49 | let parsed = parseQuery $ query ref |
74 | srcs = fromMaybe [] (loaderSrcOption parsed) | ||
75 | ffis = fromMaybe [] (loaderFFIOption parsed) | ||
76 | 50 | ||
77 | case read parsed :: F Options of | 51 | options = either (const Nothing) (Just <<< runOptions) (read parsed) |
78 | Left e -> liftEff (throwException (error (show e))) | ||
79 | Right opts -> do | ||
80 | let pscOpts = pscOptions opts | ||
81 | 52 | ||
82 | srcss <- globAll srcs | 53 | moduleName = join $ match moduleRegex source >>= \as -> as !! 1 |
83 | ffiss <- globAll ffis | ||
84 | 54 | ||
85 | let psciFile = mkPsci srcss ffiss | 55 | resourceDir = dirname (resourcePath ref) |
86 | 56 | ||
87 | writeFileUtf8 psciFilename psciFile | 57 | modulePath = (\opts -> relative resourceDir opts.bundleOutput) <$> options |
88 | 58 | ||
89 | let moduleName = match moduleRegex source >>= (!!!) 1 >>= id | 59 | result = (\path name -> "module.exports = require('" ++ path ++ "')['" ++ name ++ "'];") <$> modulePath <*> moduleName |
90 | hasForeign = test foreignRegex source | ||
91 | outputDir = resolve (output opts) | ||
92 | resourceDir = dirname (resourcePath ref) | ||
93 | result = (\a -> "module.exports = require('" ++ relative resourceDir (joinPath outputDir a) ++ "');") <$> moduleName | ||
94 | 60 | ||
95 | liftEff do | 61 | clearDependencies ref |
96 | clearDependencies ref | ||
97 | addDependency ref (resourcePath ref) | ||
98 | sequence $ (\src -> addDependency ref (resolve src)) <$> concat srcss | ||
99 | 62 | ||
100 | foreignPath <- if hasForeign | 63 | addDependency ref (resourcePath ref) |
101 | then fromMaybe (pure Nothing) (findFFI ffiss <$> moduleName) | ||
102 | else pure Nothing | ||
103 | 64 | ||
104 | fromMaybe (pure unit) ((\path -> liftEff (addDependency ref path)) <$> foreignPath) | 65 | pluginContext.compile (\err -> maybe (callback (Just $ error "Failed to run loader") "") |
105 | 66 | (callback (compileError err)) result) | |
106 | spawn pscCommand (srcs <> pscOpts) | 67 | where |
68 | moduleRegex :: Regex | ||
69 | moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } | ||
107 | 70 | ||
108 | return result | 71 | pluginContext :: PurescriptWebpackPluginContext eff |
72 | pluginContext = (unsafeCoerce ref).purescriptWebpackPluginContext | ||
109 | 73 | ||
110 | loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit | 74 | compileError :: Foreign -> Maybe Error |
111 | loader ref source = do | 75 | compileError value = either (const $ Just (error "Failed to compile")) ((<$>) error) (runNull <$> read value) |
112 | callback <- async ref | ||
113 | runAff (\e -> callback (Just e) "") | ||
114 | (maybe (callback (Just (error "Loader has failed to run")) "") | ||
115 | (callback Nothing)) | ||
116 | (loader' ref source) | ||
117 | 76 | ||
118 | loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) | 77 | loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) |
119 | loaderFn = mkFn2 loader | 78 | loaderFn = mkFn2 loader |