aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authoreric thul <thul.eric@gmail.com>2015-07-05 10:13:47 -0400
committereric thul <thul.eric@gmail.com>2015-07-06 23:53:01 -0400
commit1983893bf09a5c2ea1946e156be5da170075af7e (patch)
treef99bda0c0ff3c50356d8ab152336ba461c292494 /src
parent4558c6cf7879207166b1cc013e2e8112f558bb1d (diff)
downloadpurs-loader-1983893bf09a5c2ea1946e156be5da170075af7e.tar.gz
purs-loader-1983893bf09a5c2ea1946e156be5da170075af7e.tar.zst
purs-loader-1983893bf09a5c2ea1946e156be5da170075af7e.zip
Updating for PureScript 0.7
Resolves #14
Diffstat (limited to 'src')
-rw-r--r--src/FS.purs45
-rw-r--r--src/Glob.purs31
-rw-r--r--src/Loader.purs102
-rw-r--r--src/LoaderRef.purs25
-rw-r--r--src/OS.purs3
-rw-r--r--src/Options.purs46
-rw-r--r--src/Path.purs36
7 files changed, 42 insertions, 246 deletions
diff --git a/src/FS.purs b/src/FS.purs
deleted file mode 100644
index 68fe2f9..0000000
--- a/src/FS.purs
+++ /dev/null
@@ -1,45 +0,0 @@
1module PursLoader.FS
2 ( FS()
3 , readFileUtf8
4 , readFileUtf8Sync
5 ) where
6
7import Control.Monad.Aff (Aff(), makeAff)
8import Control.Monad.Eff (Eff())
9import Control.Monad.Eff.Exception (Error())
10
11import Data.Function
12
13foreign import data FS :: !
14
15readFileUtf8 :: forall eff. String -> Aff (fs :: FS | eff) String
16readFileUtf8 filepath = makeAff $ runFn3 readFileUtf8Fn filepath
17
18readFileUtf8Sync :: forall eff. String -> Eff (fs :: FS | eff) String
19readFileUtf8Sync filepath = readFileUtf8SyncFn filepath
20
21foreign import readFileUtf8Fn """
22function readFileUtf8Fn(filepath, errback, callback) {
23 return function(){
24 var fs = require('fs');
25
26 fs.readFile(filepath, 'utf-8', function(e, data){
27 if (e) errback(e)();
28 else callback(data)();
29 });
30 };
31}
32""" :: forall eff. Fn3 String
33 (Error -> Eff (fs :: FS | eff) Unit)
34 (String -> Eff (fs :: FS | eff) Unit)
35 (Eff (fs :: FS | eff) Unit)
36
37foreign import readFileUtf8SyncFn """
38function readFileUtf8SyncFn(filepath) {
39 return function(){
40 var fs = require('fs');
41
42 return fs.readFileSync(filepath, {encoding: 'utf-8'});
43 };
44}
45""" :: forall eff. String -> (Eff (fs :: FS | eff) String)
diff --git a/src/Glob.purs b/src/Glob.purs
deleted file mode 100644
index 7bc9212..0000000
--- a/src/Glob.purs
+++ /dev/null
@@ -1,31 +0,0 @@
1module PursLoader.Glob
2 ( Glob()
3 , glob
4 ) where
5
6import Control.Monad.Aff (Aff(), makeAff)
7import Control.Monad.Eff (Eff())
8import Control.Monad.Eff.Exception (Error())
9
10import Data.Function
11
12foreign import data Glob :: !
13
14glob :: forall eff. String -> Aff (glob :: Glob | eff) [String]
15glob pattern = makeAff $ runFn3 globFn pattern
16
17foreign import globFn """
18function globFn(pattern, errback, callback) {
19 return function(){
20 var glob = require('glob');
21
22 glob(pattern, function(e, data){
23 if (e) errback(e)();
24 else callback(data)();
25 });
26 };
27}
28""" :: forall eff. Fn3 String
29 (Error -> Eff (glob :: Glob | eff) Unit)
30 ([String] -> Eff (glob :: Glob | eff) Unit)
31 (Eff (glob :: Glob | eff) Unit)
diff --git a/src/Loader.purs b/src/Loader.purs
index fedc424..0235da9 100644
--- a/src/Loader.purs
+++ b/src/Loader.purs
@@ -1,5 +1,5 @@
1module PursLoader.Loader 1module PursLoader.Loader
2 ( LoaderEff() 2 ( Effects()
3 , loader 3 , loader
4 , loaderFn 4 , loaderFn
5 ) where 5 ) where
@@ -9,113 +9,45 @@ import Control.Monad.Eff (Eff())
9import Control.Monad.Eff.Class (liftEff) 9import Control.Monad.Eff.Class (liftEff)
10import Control.Monad.Eff.Exception (error) 10import Control.Monad.Eff.Exception (error)
11 11
12import Data.Array ((!!), catMaybes, concat, filter, null) 12import Data.Array ((!!))
13import Data.Foldable (foldl)
14import Data.Function (Fn2(), mkFn2) 13import Data.Function (Fn2(), mkFn2)
15import Data.Maybe (Maybe(..), fromMaybe, maybe) 14import Data.Maybe (Maybe(..), fromMaybe, maybe)
16import Data.Set (Set(), empty, insert, member, toList, unions) 15import Data.String.Regex (match, noFlags, regex)
17import Data.String (joinWith, split)
18import Data.String.Regex (Regex(), match, noFlags, regex)
19import Data.StrMap (StrMap(), fromList, lookup)
20import Data.Traversable (sequence)
21import Data.Tuple.Nested (tuple2)
22 16
23import PursLoader.ChildProcess (ChildProcess(), spawn) 17import PursLoader.ChildProcess (ChildProcess(), spawn)
24import PursLoader.FS (FS(), readFileUtf8, readFileUtf8Sync) 18import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query)
25import PursLoader.Glob (Glob(), glob)
26import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, clearDependencies, addDependency, query, resourcePath)
27import PursLoader.LoaderUtil (getRemainingRequest, parseQuery) 19import PursLoader.LoaderUtil (getRemainingRequest, parseQuery)
28import PursLoader.OS (eol) 20import PursLoader.Options (loaderSrcOption, pscOptions)
29import PursLoader.Options (loaderSrcOption, pscMakeOptions, pscMakeDefaultOutput, pscMakeOutputOption)
30import PursLoader.Path (dirname, join, relative, resolve)
31 21
32foreign import cwd "var cwd = process.cwd();" :: String 22type Effects eff = (loader :: Loader, cp :: ChildProcess | eff)
33 23
34moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } 24moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true }
35 25
36importRegex = regex "^\\s*import\\s+(?:qualified\\s+)?([\\w\\.]+)" noFlags { ignoreCase = true } 26pscCommand = "psc"
37
38bowerPattern = join [ "bower_components", "purescript-*", "src" ]
39
40pscMakeCommand = "psc-make"
41
42indexFilename = "index.js"
43 27
44(!!!) = flip (!!) 28(!!!) = flip (!!)
45 29
46pursPattern :: [String] -> String 30loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String)
47pursPattern srcs = join [ "{" ++ joinWith "," ([ bowerPattern ] <> srcs) ++ "}"
48 , "**"
49 , "*.purs"
50 ]
51
52type GraphModule = { file :: String, imports :: [String] }
53
54type Graph = StrMap GraphModule
55
56mkGraph :: forall eff. [String] -> Eff (fs :: FS | eff) Graph
57mkGraph files = (fromList <<< catMaybes) <$> sequence (parse <$> files)
58 where parse file = do source <- readFileUtf8Sync file
59 let key = match moduleRegex source >>= (!!!) 1
60 lines = split eol source
61 imports = catMaybes $ (\a -> match importRegex a >>= (!!!) 1) <$> lines
62 return $ (\a -> tuple2 a { file: file, imports: imports }) <$> key
63
64mkDeps :: forall eff. String -> Graph -> [String]
65mkDeps key graph = toList $ go empty key
66 where
67 go :: Set String -> String -> Set String
68 go acc key =
69 let node = fromMaybe {file: "", imports: []} (lookup key graph)
70 uniq = filter (not <<< flip member acc) node.imports
71 acc' = foldl (flip insert) acc node.imports
72 in if null uniq
73 then acc'
74 else unions $ go acc' <$> uniq
75
76addDeps :: forall eff. LoaderRef -> Graph -> [String] -> Eff (loader :: Loader | eff) Unit
77addDeps ref graph deps = const unit <$> (sequence $ add <$> deps)
78 where add dep = let res = lookup dep graph
79 path = (\a -> resolve a.file) <$> res
80 in maybe (pure unit) (addDependency ref) path
81
82type LoaderAff eff a = Aff (loader :: Loader, glob :: Glob, cp :: ChildProcess, fs :: FS | eff) a
83
84loader' :: forall eff. LoaderRef -> String -> LoaderAff eff (Maybe String)
85loader' ref source = do 31loader' ref source = do
86 liftEff $ cacheable ref 32 liftEff $ cacheable ref
87 33
88 let request = getRemainingRequest ref 34 let request = getRemainingRequest ref
89 parsed = parseQuery $ query ref 35 parsed = parseQuery $ query ref
90 srcs = loaderSrcOption parsed 36 srcs = fromMaybe [] (loaderSrcOption parsed)
91 opts = pscMakeOptions parsed 37 opts = pscOptions parsed
92 pattern = pursPattern $ fromMaybe [] srcs 38 moduleName = match moduleRegex source >>= (!!!) 1
93 key = match moduleRegex source >>= (!!!) 1 39 result = (\a -> "module.exports = require('" ++ a ++ "');") <$> moduleName
94
95 files <- glob pattern
96 graph <- liftEff $ mkGraph files
97
98 let deps = fromMaybe [] $ flip mkDeps graph <$> key
99 outputPath = fromMaybe pscMakeDefaultOutput $ pscMakeOutputOption parsed
100 indexPath = (\a -> join [ outputPath, a, indexFilename ]) <$> key
101
102 liftEff $ clearDependencies ref
103 liftEff $ addDependency ref (resourcePath ref)
104 liftEff $ addDeps ref graph deps
105
106 spawn pscMakeCommand (opts <> files)
107 indexFile <- sequence $ readFileUtf8 <$> indexPath
108 return indexFile
109 40
110type LoaderEff eff a = Eff (loader :: Loader, glob :: Glob, cp :: ChildProcess, fs :: FS | eff) a 41 spawn pscCommand (srcs <> opts)
42 return result
111 43
112loader :: forall eff. LoaderRef -> String -> LoaderEff eff Unit 44loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit
113loader ref source = do 45loader ref source = do
114 callback <- async ref 46 callback <- async ref
115 runAff (\e -> callback (Just e) "") 47 runAff (\e -> callback (Just e) "")
116 (maybe (callback (Just $ error "Loader has failed to run") "") 48 (maybe (callback (Just (error "Loader has failed to run")) "")
117 (callback Nothing)) 49 (callback Nothing))
118 (loader' ref source) 50 (loader' ref source)
119 51
120loaderFn :: forall eff. Fn2 LoaderRef String (LoaderEff eff Unit) 52loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit)
121loaderFn = mkFn2 loader 53loaderFn = mkFn2 loader
diff --git a/src/LoaderRef.purs b/src/LoaderRef.purs
index 2d62754..2567b1e 100644
--- a/src/LoaderRef.purs
+++ b/src/LoaderRef.purs
@@ -3,16 +3,12 @@ module PursLoader.LoaderRef
3 , Loader() 3 , Loader()
4 , async 4 , async
5 , cacheable 5 , cacheable
6 , clearDependencies
7 , resourcePath
8 , addDependency
9 , query 6 , query
10 ) where 7 ) where
11 8
12import Control.Monad.Eff (Eff()) 9import Control.Monad.Eff (Eff())
13import Control.Monad.Eff.Exception (Error()) 10import Control.Monad.Eff.Exception (Error())
14 11
15import Data.Foreign (Foreign())
16import Data.Function (Fn3(), runFn3) 12import Data.Function (Fn3(), runFn3)
17import Data.Maybe (Maybe(), fromMaybe, isJust) 13import Data.Maybe (Maybe(), fromMaybe, isJust)
18 14
@@ -48,27 +44,6 @@ function cacheable(ref){
48 }; 44 };
49}""" :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit 45}""" :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit
50 46
51foreign import clearDependencies """
52function clearDependencies(ref){
53 return function(){
54 return ref.clearDependencies();
55 };
56}""" :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit
57
58foreign import resourcePath """
59function resourcePath(ref){
60 return ref.resourcePath;
61}""" :: LoaderRef -> String
62
63foreign import addDependency """
64function addDependency(ref){
65 return function(dep){
66 return function(){
67 return ref.addDependency(dep);
68 };
69 };
70}""" :: forall eff. LoaderRef -> String -> Eff (loader :: Loader | eff) Unit
71
72foreign import query """ 47foreign import query """
73function query(ref){ 48function query(ref){
74 return ref.query; 49 return ref.query;
diff --git a/src/OS.purs b/src/OS.purs
deleted file mode 100644
index 590c3d6..0000000
--- a/src/OS.purs
+++ /dev/null
@@ -1,3 +0,0 @@
1module PursLoader.OS (eol) where
2
3foreign import eol "var eol = require('os').EOL;" :: String
diff --git a/src/Options.purs b/src/Options.purs
index c47bebc..be21877 100644
--- a/src/Options.purs
+++ b/src/Options.purs
@@ -1,17 +1,16 @@
1module PursLoader.Options 1module PursLoader.Options
2 ( pscMakeOptions 2 ( pscOptions
3 , pscMakeDefaultOutput
4 , pscMakeOutputOption
5 , loaderSrcOption 3 , loaderSrcOption
6 ) where 4 ) where
7 5
6import Data.Array (concat)
8import Data.Either (either) 7import Data.Either (either)
9 8
10import Data.Foreign (Foreign(), F()) 9import Data.Foreign (Foreign(), F())
11import Data.Foreign.Class (IsForeign, read, readProp) 10import Data.Foreign.Class (IsForeign, read, readProp)
12import Data.Foreign.NullOrUndefined (NullOrUndefined(), runNullOrUndefined) 11import Data.Foreign.NullOrUndefined (NullOrUndefined(..), runNullOrUndefined)
13 12
14import Data.Maybe (Maybe(..), maybe) 13import Data.Maybe (Maybe(..), maybe, fromMaybe)
15 14
16noPreludeOpt = "no-prelude" 15noPreludeOpt = "no-prelude"
17 16
@@ -29,9 +28,11 @@ commentsOpt = "comments"
29 28
30noPrefixOpt = "no-prefix" 29noPrefixOpt = "no-prefix"
31 30
31requirePathOpt = "require-path"
32
32srcOpt = "src" 33srcOpt = "src"
33 34
34pscMakeDefaultOutput = "output" 35ffiOpt = "ffi"
35 36
36newtype Options 37newtype Options
37 = Options { noPrelude :: NullOrUndefined Boolean 38 = Options { noPrelude :: NullOrUndefined Boolean
@@ -42,7 +43,9 @@ newtype Options
42 , comments :: NullOrUndefined Boolean 43 , comments :: NullOrUndefined Boolean
43 , output :: NullOrUndefined String 44 , output :: NullOrUndefined String
44 , noPrefix :: NullOrUndefined Boolean 45 , noPrefix :: NullOrUndefined Boolean
46 , requirePath :: NullOrUndefined String
45 , src :: NullOrUndefined [String] 47 , src :: NullOrUndefined [String]
48 , ffi :: NullOrUndefined [String]
46 } 49 }
47 50
48instance isForeignOptions :: IsForeign Options where 51instance isForeignOptions :: IsForeign Options where
@@ -54,7 +57,9 @@ instance isForeignOptions :: IsForeign Options where
54 , comments: _ 57 , comments: _
55 , output: _ 58 , output: _
56 , noPrefix: _ 59 , noPrefix: _
60 , requirePath: _
57 , src: _ 61 , src: _
62 , ffi: _
58 } <$> readProp noPreludeOpt obj 63 } <$> readProp noPreludeOpt obj
59 <*> readProp noOptsOpt obj 64 <*> readProp noOptsOpt obj
60 <*> readProp noMagicDoOpt obj 65 <*> readProp noMagicDoOpt obj
@@ -63,26 +68,25 @@ instance isForeignOptions :: IsForeign Options where
63 <*> readProp commentsOpt obj 68 <*> readProp commentsOpt obj
64 <*> readProp outputOpt obj 69 <*> readProp outputOpt obj
65 <*> readProp noPrefixOpt obj 70 <*> readProp noPrefixOpt obj
66 <*> readProp srcOpt obj) 71 <*> readProp requirePathOpt obj
72 <*> readProp srcOpt obj
73 <*> readProp ffiOpt obj)
67 74
68class LoaderOption a where 75class LoaderOption a where
69 opt :: String -> NullOrUndefined a -> [String] 76 opt :: String -> NullOrUndefined a -> [String]
70 77
71instance booleanLoaderOption :: LoaderOption Boolean where 78instance booleanLoaderOption :: LoaderOption Boolean where
72 opt key opt = maybe [] (\a -> if a then ["--" ++ key] else []) 79 opt key val = maybe [] (\a -> if a then ["--" ++ key] else []) (runNullOrUndefined val)
73 (runNullOrUndefined opt)
74 80
75instance stringLoaderOption :: LoaderOption String where 81instance stringLoaderOption :: LoaderOption String where
76 opt key opt = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) 82 opt key val = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) (runNullOrUndefined val)
77 (runNullOrUndefined opt)
78 83
79pscMakeOutputOption :: Foreign -> Maybe String 84instance arrayLoaderOption :: (LoaderOption a) => LoaderOption [a] where
80pscMakeOutputOption query = either (const Nothing) 85 opt key val = concat (opt key <$> (NullOrUndefined <<< Just)
81 (\(Options a) -> runNullOrUndefined a.output) 86 <$> (fromMaybe [] (runNullOrUndefined val)))
82 (read query)
83 87
84pscMakeOptions :: Foreign -> [String] 88pscOptions :: Foreign -> [String]
85pscMakeOptions query = either (const []) fold parsed 89pscOptions query = either (const []) fold parsed
86 where parsed = read query :: F Options 90 where parsed = read query :: F Options
87 fold (Options a) = opt noPreludeOpt a.noPrelude <> 91 fold (Options a) = opt noPreludeOpt a.noPrelude <>
88 opt noOptsOpt a.noOpts <> 92 opt noOptsOpt a.noOpts <>
@@ -91,9 +95,9 @@ pscMakeOptions query = either (const []) fold parsed
91 opt verboseErrorsOpt a.verboseErrors <> 95 opt verboseErrorsOpt a.verboseErrors <>
92 opt commentsOpt a.comments <> 96 opt commentsOpt a.comments <>
93 opt outputOpt a.output <> 97 opt outputOpt a.output <>
94 opt noPrefixOpt a.noPrefix 98 opt noPrefixOpt a.noPrefix <>
99 opt requirePathOpt a.requirePath <>
100 opt ffiOpt a.ffi
95 101
96loaderSrcOption :: Foreign -> Maybe [String] 102loaderSrcOption :: Foreign -> Maybe [String]
97loaderSrcOption query = either (const Nothing) 103loaderSrcOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.src) (read query)
98 (\(Options a) -> runNullOrUndefined a.src)
99 (read query)
diff --git a/src/Path.purs b/src/Path.purs
deleted file mode 100644
index e071e35..0000000
--- a/src/Path.purs
+++ /dev/null
@@ -1,36 +0,0 @@
1module PursLoader.Path
2 ( dirname
3 , join
4 , relative
5 , resolve
6 ) where
7
8foreign import dirname """
9function dirname(filepath) {
10 var path = require('path');
11 return path.dirname(filepath);
12}
13""" :: String -> String
14
15foreign import join """
16function join(parts) {
17 var path = require('path');
18 return path.join.apply(path, parts);
19}
20""" :: [String] -> String
21
22foreign import relative """
23function relative(from) {
24 return function(to){
25 var path = require('path');
26 return path.relative(from, to);
27 };
28}
29""" :: String -> String -> String
30
31foreign import resolve """
32function resolve(filepath) {
33 var path = require('path');
34 return path.resolve(filepath);
35}
36""" :: String -> String