]>
Commit | Line | Data |
---|---|---|
1 | module PursLoader.Loader | |
2 | ( Effects() | |
3 | , loader | |
4 | , loaderFn | |
5 | ) where | |
6 | ||
7 | import Control.Monad.Aff (Aff(), runAff) | |
8 | import Control.Monad.Eff (Eff()) | |
9 | import Control.Monad.Eff.Class (liftEff) | |
10 | import Control.Monad.Eff.Exception (error) | |
11 | ||
12 | import Data.Array ((!!), concat) | |
13 | import Data.Function (Fn2(), mkFn2) | |
14 | import Data.Maybe (Maybe(..), fromMaybe, maybe) | |
15 | import Data.String (joinWith) | |
16 | import Data.String.Regex (match, noFlags, regex) | |
17 | ||
18 | import PursLoader.ChildProcess (ChildProcess(), spawn) | |
19 | import PursLoader.FS (FS(), writeFileUtf8) | |
20 | import PursLoader.Glob (Glob(), globAll) | |
21 | import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query) | |
22 | import PursLoader.LoaderUtil (parseQuery) | |
23 | import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions) | |
24 | ||
25 | type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader | eff) | |
26 | ||
27 | moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } | |
28 | ||
29 | pscCommand = "psc" | |
30 | ||
31 | psciCommand = "psci" | |
32 | ||
33 | psciFilename = ".psci" | |
34 | ||
35 | (!!!) = flip (!!) | |
36 | ||
37 | foreign import cwd "var cwd = process.cwd();" :: String | |
38 | ||
39 | foreign import relative """ | |
40 | function relative(from) { | |
41 | return function(to){ | |
42 | var path = require('path'); | |
43 | return path.relative(from, to); | |
44 | }; | |
45 | } | |
46 | """ :: String -> String -> String | |
47 | ||
48 | mkPsci :: [[String]] -> [[String]] -> String | |
49 | mkPsci srcs ffis = joinWith "\n" ((loadModule <$> concat srcs) <> (loadForeign <$> concat ffis)) | |
50 | where | |
51 | loadModule :: String -> String | |
52 | loadModule a = ":m " ++ relative cwd a | |
53 | ||
54 | loadForeign :: String -> String | |
55 | loadForeign a = ":f " ++ relative cwd a | |
56 | ||
57 | loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String) | |
58 | loader' ref source = do | |
59 | liftEff $ cacheable ref | |
60 | ||
61 | let parsed = parseQuery $ query ref | |
62 | srcs = fromMaybe [] (loaderSrcOption parsed) | |
63 | ffis = fromMaybe [] (loaderFFIOption parsed) | |
64 | opts = pscOptions parsed | |
65 | ||
66 | spawn pscCommand (srcs <> opts) | |
67 | ||
68 | srcss <- globAll srcs | |
69 | ffiss <- globAll ffis | |
70 | ||
71 | let psciFile = mkPsci srcss ffiss | |
72 | ||
73 | writeFileUtf8 psciFilename psciFile | |
74 | ||
75 | let moduleName = match moduleRegex source >>= (!!!) 1 | |
76 | result = (\a -> "module.exports = require('" ++ a ++ "');") <$> moduleName | |
77 | ||
78 | return result | |
79 | ||
80 | loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit | |
81 | loader ref source = do | |
82 | callback <- async ref | |
83 | runAff (\e -> callback (Just e) "") | |
84 | (maybe (callback (Just (error "Loader has failed to run")) "") | |
85 | (callback Nothing)) | |
86 | (loader' ref source) | |
87 | ||
88 | loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) | |
89 | loaderFn = mkFn2 loader |