aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/PursLoader/Loader.purs
diff options
context:
space:
mode:
Diffstat (limited to 'src/PursLoader/Loader.purs')
-rw-r--r--src/PursLoader/Loader.purs133
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
7import Prelude (Unit(), ($), (<>), (>>=), (<$>), (++), bind, flip, id, pure, return, unit, show) 7import Prelude (Unit(), ($), (>>=), (<$>), (<*>), (<<<), (++), bind, const)
8 8
9import Control.Monad.Aff (Aff(), runAff) 9import Control.Bind (join)
10import Control.Monad.Eff (Eff()) 10import Control.Monad.Eff (Eff())
11import Control.Monad.Eff.Class (liftEff) 11import Control.Monad.Eff.Exception (Error(), error)
12import Control.Monad.Eff.Exception (throwException, error, EXCEPTION())
13 12
14import Data.Array ((!!), concat) 13import Data.Array ((!!))
15import Data.Function (Fn2(), mkFn2) 14import Data.Function (Fn2(), mkFn2)
16import Data.Maybe (Maybe(..), fromMaybe, maybe) 15import Data.Maybe (Maybe(..), maybe)
17import Data.Either (Either(..)) 16import Data.Either (either)
18import Data.String (joinWith) 17import Data.Foreign (Foreign())
19import Data.String.Regex (match, noFlags, regex, test)
20import Data.Traversable (sequence)
21import Data.Foreign (F())
22import Data.Foreign.Class (read) 18import Data.Foreign.Class (read)
19import Data.Foreign.Null (runNull)
20import Data.String.Regex (Regex(), match, noFlags, regex)
21
22import Unsafe.Coerce (unsafeCoerce)
23
24import PursLoader.LoaderRef
25 ( LoaderRef()
26 , Loader()
27 , async
28 , cacheable
29 , query
30 , clearDependencies
31 , addDependency
32 , resourcePath
33 )
23 34
24import PursLoader.ChildProcess (ChildProcess(), spawn)
25import PursLoader.FS (FS(), writeFileUtf8, findFileUtf8)
26import PursLoader.Glob (Glob(), globAll)
27import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query, clearDependencies, addDependency, resourcePath)
28import PursLoader.LoaderUtil (parseQuery) 35import PursLoader.LoaderUtil (parseQuery)
29import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions, Options(), output) 36import PursLoader.Options (runOptions)
37import PursLoader.Path (dirname, relative)
30 38
31type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader, err :: EXCEPTION | eff) 39type Effects eff = (loader :: Loader | eff)
32 40
33moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } 41type PurescriptWebpackPluginContext eff = { compile :: (Foreign -> Eff (Effects eff) Unit) -> Eff (Effects eff) Unit }
34 42
35foreignRegex = regex "(?:^|\\n)\\s*foreign import\\s+" noFlags { ignoreCase = true } 43loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit
36 44loader ref source = do
37pscCommand = "psc" 45 callback <- async ref
38
39psciCommand = "psci"
40
41psciFilename = ".psci"
42
43(!!!) = flip (!!)
44
45foreign import cwd :: String
46
47foreign import relative :: String -> String -> String
48
49foreign import resolve :: String -> String
50
51foreign import dirname :: String -> String
52
53foreign import joinPath :: String -> String -> String
54
55mkPsci :: Array (Array String) -> Array (Array String) -> String
56mkPsci 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
64findFFI :: forall eff. Array (Array String) -> String -> Aff (fs :: FS | eff) (Maybe String)
65findFFI ffiss name = findFileUtf8 re (concat ffiss)
66 where
67 re = regex ("(?:^|\\n)//\\s*module\\s*" ++ name ++ "\\s*\\n") noFlags
68 46
69loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String) 47 cacheable ref
70loader' 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
110loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit 74 compileError :: Foreign -> Maybe Error
111loader 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
118loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) 77loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit)
119loaderFn = mkFn2 loader 78loaderFn = mkFn2 loader