diff options
-rw-r--r-- | MODULE.md | 97 | ||||
-rw-r--r-- | README.md | 54 | ||||
-rw-r--r-- | example/README.md | 2 | ||||
-rw-r--r-- | example/bower.json | 2 | ||||
-rw-r--r-- | example/package.json | 2 | ||||
-rw-r--r-- | example/src/Foo.purs | 5 | ||||
-rw-r--r-- | example/src/Foo/Bar.purs | 2 | ||||
-rw-r--r-- | example/src/Test.purs | 2 | ||||
-rw-r--r-- | example/src/entry.js | 6 | ||||
-rw-r--r-- | example/webpack.config.js | 21 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/FS.purs | 35 | ||||
-rw-r--r-- | src/Glob.purs | 22 | ||||
-rw-r--r-- | src/Loader.purs | 126 | ||||
-rw-r--r-- | src/LoaderRef.purs | 25 | ||||
-rw-r--r-- | src/LoaderUtil.purs | 9 | ||||
-rw-r--r-- | src/OS.purs | 3 | ||||
-rw-r--r-- | src/Options.purs | 50 | ||||
-rw-r--r-- | src/Path.purs | 36 | ||||
-rw-r--r-- | webpack.config.js | 9 |
20 files changed, 206 insertions, 303 deletions
@@ -26,17 +26,10 @@ data FS :: ! | |||
26 | ``` | 26 | ``` |
27 | 27 | ||
28 | 28 | ||
29 | #### `readFileUtf8` | 29 | #### `writeFileUtf8` |
30 | 30 | ||
31 | ``` purescript | 31 | ``` purescript |
32 | readFileUtf8 :: forall eff. String -> Aff (fs :: FS | eff) String | 32 | writeFileUtf8 :: forall eff. String -> String -> Aff (fs :: FS | eff) Unit |
33 | ``` | ||
34 | |||
35 | |||
36 | #### `readFileUtf8Sync` | ||
37 | |||
38 | ``` purescript | ||
39 | readFileUtf8Sync :: forall eff. String -> Eff (fs :: FS | eff) String | ||
40 | ``` | 33 | ``` |
41 | 34 | ||
42 | 35 | ||
@@ -50,34 +43,34 @@ data Glob :: ! | |||
50 | ``` | 43 | ``` |
51 | 44 | ||
52 | 45 | ||
53 | #### `glob` | 46 | #### `globAll` |
54 | 47 | ||
55 | ``` purescript | 48 | ``` purescript |
56 | glob :: forall eff. String -> Aff (glob :: Glob | eff) [String] | 49 | globAll :: forall eff. [String] -> Aff (glob :: Glob | eff) [[String]] |
57 | ``` | 50 | ``` |
58 | 51 | ||
59 | 52 | ||
60 | 53 | ||
61 | ## Module PursLoader.Loader | 54 | ## Module PursLoader.Loader |
62 | 55 | ||
63 | #### `LoaderEff` | 56 | #### `Effects` |
64 | 57 | ||
65 | ``` purescript | 58 | ``` purescript |
66 | type LoaderEff eff a = Eff (fs :: FS, cp :: ChildProcess, glob :: Glob, loader :: Loader | eff) a | 59 | type Effects eff = (loader :: Loader, glob :: Glob, fs :: FS, cp :: ChildProcess | eff) |
67 | ``` | 60 | ``` |
68 | 61 | ||
69 | 62 | ||
70 | #### `loader` | 63 | #### `loader` |
71 | 64 | ||
72 | ``` purescript | 65 | ``` purescript |
73 | loader :: forall eff. LoaderRef -> String -> LoaderEff eff Unit | 66 | loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit |
74 | ``` | 67 | ``` |
75 | 68 | ||
76 | 69 | ||
77 | #### `loaderFn` | 70 | #### `loaderFn` |
78 | 71 | ||
79 | ``` purescript | 72 | ``` purescript |
80 | loaderFn :: forall eff. Fn2 LoaderRef String (LoaderEff eff Unit) | 73 | loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) |
81 | ``` | 74 | ``` |
82 | 75 | ||
83 | 76 | ||
@@ -112,27 +105,6 @@ cacheable :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit | |||
112 | ``` | 105 | ``` |
113 | 106 | ||
114 | 107 | ||
115 | #### `clearDependencies` | ||
116 | |||
117 | ``` purescript | ||
118 | clearDependencies :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit | ||
119 | ``` | ||
120 | |||
121 | |||
122 | #### `resourcePath` | ||
123 | |||
124 | ``` purescript | ||
125 | resourcePath :: LoaderRef -> String | ||
126 | ``` | ||
127 | |||
128 | |||
129 | #### `addDependency` | ||
130 | |||
131 | ``` purescript | ||
132 | addDependency :: forall eff. LoaderRef -> String -> Eff (loader :: Loader | eff) Unit | ||
133 | ``` | ||
134 | |||
135 | |||
136 | #### `query` | 108 | #### `query` |
137 | 109 | ||
138 | ``` purescript | 110 | ``` purescript |
@@ -143,13 +115,6 @@ query :: LoaderRef -> String | |||
143 | 115 | ||
144 | ## Module PursLoader.LoaderUtil | 116 | ## Module PursLoader.LoaderUtil |
145 | 117 | ||
146 | #### `getRemainingRequest` | ||
147 | |||
148 | ``` purescript | ||
149 | getRemainingRequest :: LoaderRef -> String | ||
150 | ``` | ||
151 | |||
152 | |||
153 | #### `parseQuery` | 118 | #### `parseQuery` |
154 | 119 | ||
155 | ``` purescript | 120 | ``` purescript |
@@ -158,16 +123,6 @@ parseQuery :: String -> Foreign | |||
158 | 123 | ||
159 | 124 | ||
160 | 125 | ||
161 | ## Module PursLoader.OS | ||
162 | |||
163 | #### `eol` | ||
164 | |||
165 | ``` purescript | ||
166 | eol :: String | ||
167 | ``` | ||
168 | |||
169 | |||
170 | |||
171 | ## Module PursLoader.Options | 126 | ## Module PursLoader.Options |
172 | 127 | ||
173 | #### `isForeignOptions` | 128 | #### `isForeignOptions` |
@@ -191,17 +146,17 @@ instance stringLoaderOption :: LoaderOption String | |||
191 | ``` | 146 | ``` |
192 | 147 | ||
193 | 148 | ||
194 | #### `pscMakeOutputOption` | 149 | #### `arrayLoaderOption` |
195 | 150 | ||
196 | ``` purescript | 151 | ``` purescript |
197 | pscMakeOutputOption :: Foreign -> Maybe String | 152 | instance arrayLoaderOption :: (LoaderOption a) => LoaderOption [a] |
198 | ``` | 153 | ``` |
199 | 154 | ||
200 | 155 | ||
201 | #### `pscMakeOptions` | 156 | #### `pscOptions` |
202 | 157 | ||
203 | ``` purescript | 158 | ``` purescript |
204 | pscMakeOptions :: Foreign -> [String] | 159 | pscOptions :: Foreign -> [String] |
205 | ``` | 160 | ``` |
206 | 161 | ||
207 | 162 | ||
@@ -212,34 +167,10 @@ loaderSrcOption :: Foreign -> Maybe [String] | |||
212 | ``` | 167 | ``` |
213 | 168 | ||
214 | 169 | ||
215 | 170 | #### `loaderFFIOption` | |
216 | ## Module PursLoader.Path | ||
217 | |||
218 | #### `dirname` | ||
219 | |||
220 | ``` purescript | ||
221 | dirname :: String -> String | ||
222 | ``` | ||
223 | |||
224 | |||
225 | #### `join` | ||
226 | |||
227 | ``` purescript | ||
228 | join :: [String] -> String | ||
229 | ``` | ||
230 | |||
231 | |||
232 | #### `relative` | ||
233 | |||
234 | ``` purescript | ||
235 | relative :: String -> String -> String | ||
236 | ``` | ||
237 | |||
238 | |||
239 | #### `resolve` | ||
240 | 171 | ||
241 | ``` purescript | 172 | ``` purescript |
242 | resolve :: String -> String | 173 | loaderFFIOption :: Foreign -> Maybe [String] |
243 | ``` | 174 | ``` |
244 | 175 | ||
245 | 176 | ||
@@ -44,10 +44,62 @@ Sets `--output=<string>` the specifies the output directory, `output` by default | |||
44 | 44 | ||
45 | Toggles `--no-prefix` that does not include the comment header. | 45 | Toggles `--no-prefix` that does not include the comment header. |
46 | 46 | ||
47 | ###### `requirePath` (String) | ||
48 | |||
49 | Sets `--require-path=<string>` that specifies the path prefix to use for `require()` calls in the generated JavaScript. | ||
50 | |||
51 | ###### `ffi` (String Array) | ||
52 | |||
53 | Specifies the PureScript FFI files setting `--ffi=<string>`. Glob syntax is supported. This option is specified as `ffi[]=path`. | ||
54 | |||
47 | ###### `src` (String Array) | 55 | ###### `src` (String Array) |
48 | 56 | ||
49 | Specifies PureScript source paths to be globbed for `.purs` files. By default, `bower_components` is search. Additional paths may be specified using this option. This option is specified as `src[]=path`. | 57 | Specifies the PureScript source files. Glob syntax is supported. This option is specified as `src[]=path`. |
50 | 58 | ||
51 | ## Example | 59 | ## Example |
52 | 60 | ||
61 | ```js | ||
62 | // webpack.config.js | ||
63 | |||
64 | var path = require('path'); | ||
65 | |||
66 | var srcs = ['src[]=bower_components/purescript-*/src/**/*.purs', 'src[]=src/**/*.purs']; | ||
67 | |||
68 | var ffis = ['ffi[]=bower_components/purescript-*/src/**/*.js']; | ||
69 | |||
70 | var output = 'output'; | ||
71 | |||
72 | var modulesDirectories = [ | ||
73 | 'node_modules', | ||
74 | // The bower component for purescript-prelude is specified here to | ||
75 | // allow JavaScript files to require the 'Prelude' module globally. | ||
76 | 'bower_components/purescript-prelude/src', | ||
77 | // The output directory is specified here to allow PureScript files in | ||
78 | // your source to import other PureScript modules in your source. | ||
79 | output | ||
80 | ]; | ||
81 | |||
82 | var config | ||
83 | = { entry: './src/entry' | ||
84 | , output: { path: __dirname | ||
85 | , pathinfo: true | ||
86 | , filename: 'bundle.js' | ||
87 | } | ||
88 | , module: { loaders: [ { test: /\.purs$/ | ||
89 | , loader: 'purs-loader?output=' + output + '&' + srcs.concat(ffis).join('&') | ||
90 | } ] } | ||
91 | , resolve: { modulesDirectories: modulesDirectories | ||
92 | , extensions: ['', '.js', '.purs'] | ||
93 | } | ||
94 | , resolveLoader: { root: path.join(__dirname, 'node_modules') } | ||
95 | } | ||
96 | ; | ||
97 | |||
98 | module.exports = config; | ||
99 | ``` | ||
100 | |||
53 | See the [example](https://github.com/ethul/purs-loader/tree/master/example) directory for a complete example. | 101 | See the [example](https://github.com/ethul/purs-loader/tree/master/example) directory for a complete example. |
102 | |||
103 | ## Notes | ||
104 | |||
105 | A `.psci` file is generated during each run of the loader. | ||
diff --git a/example/README.md b/example/README.md index 87b9bc7..bac4f6c 100644 --- a/example/README.md +++ b/example/README.md | |||
@@ -1,6 +1,6 @@ | |||
1 | ```bash | 1 | ```bash |
2 | bower install | 2 | bower install |
3 | npm install | 3 | npm install |
4 | npm run-script webpack | 4 | npm run-script build |
5 | npm run-script run | 5 | npm run-script run |
6 | ``` | 6 | ``` |
diff --git a/example/bower.json b/example/bower.json index b4a1c78..c83e735 100644 --- a/example/bower.json +++ b/example/bower.json | |||
@@ -2,6 +2,6 @@ | |||
2 | "name": "example", | 2 | "name": "example", |
3 | "private": true, | 3 | "private": true, |
4 | "devDependencies": { | 4 | "devDependencies": { |
5 | "purescript-maybe": "~0.2.1" | 5 | "purescript-prelude": "~0.1.0" |
6 | } | 6 | } |
7 | } | 7 | } |
diff --git a/example/package.json b/example/package.json index 915eb27..df3e74f 100644 --- a/example/package.json +++ b/example/package.json | |||
@@ -3,7 +3,7 @@ | |||
3 | "version": "0.0.0", | 3 | "version": "0.0.0", |
4 | "private": true, | 4 | "private": true, |
5 | "scripts": { | 5 | "scripts": { |
6 | "webpack": "./node_modules/.bin/webpack", | 6 | "build": "mkdir -p output && ./node_modules/.bin/webpack", |
7 | "run": "node bundle.js", | 7 | "run": "node bundle.js", |
8 | "clean": "rm -rf bower_components && rm -rf bundle.js && rm -rf node_modules && rm -rf output" | 8 | "clean": "rm -rf bower_components && rm -rf bundle.js && rm -rf node_modules && rm -rf output" |
9 | }, | 9 | }, |
diff --git a/example/src/Foo.purs b/example/src/Foo.purs index 3e3a04c..b234e0d 100644 --- a/example/src/Foo.purs +++ b/example/src/Foo.purs | |||
@@ -1,6 +1,9 @@ | |||
1 | module Foo (foo) where | 1 | module Foo (foo) where |
2 | 2 | ||
3 | import Data.Maybe | 3 | import Prelude |
4 | |||
4 | import qualified Foo.Bar as B | 5 | import qualified Foo.Bar as B |
5 | 6 | ||
6 | foo = "b" | 7 | foo = "b" |
8 | |||
9 | foo' = "c" | ||
diff --git a/example/src/Foo/Bar.purs b/example/src/Foo/Bar.purs index 4ae100d..6932902 100644 --- a/example/src/Foo/Bar.purs +++ b/example/src/Foo/Bar.purs | |||
@@ -1,3 +1,5 @@ | |||
1 | module Foo.Bar (bar) where | 1 | module Foo.Bar (bar) where |
2 | 2 | ||
3 | bar = "c" | 3 | bar = "c" |
4 | |||
5 | bar' = "d" | ||
diff --git a/example/src/Test.purs b/example/src/Test.purs index 8a5cb88..d9f1b96 100644 --- a/example/src/Test.purs +++ b/example/src/Test.purs | |||
@@ -1,5 +1,5 @@ | |||
1 | module Test (test) where | 1 | module Test (test) where |
2 | 2 | ||
3 | import Data.Maybe | 3 | import Prelude |
4 | 4 | ||
5 | test = "a" | 5 | test = "a" |
diff --git a/example/src/entry.js b/example/src/entry.js index cc09034..344d4c6 100644 --- a/example/src/entry.js +++ b/example/src/entry.js | |||
@@ -1,7 +1,11 @@ | |||
1 | var Prelude = require('Prelude'); | ||
2 | |||
1 | var test = require('./Test'); | 3 | var test = require('./Test'); |
2 | 4 | ||
3 | var foo = require('./Foo'); | 5 | var foo = require('./Foo'); |
4 | 6 | ||
5 | var baz = require('./Foo/Baz'); | 7 | var baz = require('./Foo/Baz'); |
6 | 8 | ||
7 | console.log(test, foo, baz); | 9 | var bar = require('./Foo/Bar'); |
10 | |||
11 | console.log(Prelude, test, foo, baz, bar); | ||
diff --git a/example/webpack.config.js b/example/webpack.config.js index f67e83a..9294904 100644 --- a/example/webpack.config.js +++ b/example/webpack.config.js | |||
@@ -1,14 +1,27 @@ | |||
1 | var path = require('path'); | 1 | var path = require('path'); |
2 | 2 | ||
3 | var srcs = ['src[]=bower_components/purescript-*/src/**/*.purs', 'src[]=src/**/*.purs']; | ||
4 | |||
5 | var ffis = ['ffi[]=bower_components/purescript-*/src/**/*.js']; | ||
6 | |||
7 | var output = 'output'; | ||
8 | |||
9 | var modulesDirectories = [ | ||
10 | 'node_modules', | ||
11 | 'bower_components/purescript-prelude/src', | ||
12 | output | ||
13 | ]; | ||
14 | |||
3 | var config | 15 | var config |
4 | = { entry: './src/entry' | 16 | = { entry: './src/entry' |
5 | , output: { path: __dirname | 17 | , output: { path: __dirname |
18 | , pathinfo: true | ||
6 | , filename: 'bundle.js' | 19 | , filename: 'bundle.js' |
7 | } | 20 | } |
8 | , module: { loaders: [ { test: /\.purs$/, loader: 'purs-loader?src[]=src' } ] } | 21 | , module: { loaders: [ { test: /\.purs$/ |
9 | , resolve: { modulesDirectories: [ 'node_modules', | 22 | , loader: 'purs-loader?output=' + output + '&' + srcs.concat(ffis).join('&') |
10 | 'output' | 23 | } ] } |
11 | ] | 24 | , resolve: { modulesDirectories: modulesDirectories |
12 | , extensions: ['', '.js', '.purs'] | 25 | , extensions: ['', '.js', '.purs'] |
13 | } | 26 | } |
14 | , resolveLoader: { root: path.join(__dirname, 'node_modules') } | 27 | , resolveLoader: { root: path.join(__dirname, 'node_modules') } |
diff --git a/package.json b/package.json index 39c743b..f98769e 100644 --- a/package.json +++ b/package.json | |||
@@ -28,6 +28,7 @@ | |||
28 | "webpack": "^1.8.4" | 28 | "webpack": "^1.8.4" |
29 | }, | 29 | }, |
30 | "dependencies": { | 30 | "dependencies": { |
31 | "async": "^1.3.0", | ||
31 | "glob": "^5.0.3", | 32 | "glob": "^5.0.3", |
32 | "loader-utils": "^0.2.6" | 33 | "loader-utils": "^0.2.6" |
33 | } | 34 | } |
diff --git a/src/FS.purs b/src/FS.purs index 68fe2f9..a56fe26 100644 --- a/src/FS.purs +++ b/src/FS.purs | |||
@@ -1,7 +1,6 @@ | |||
1 | module PursLoader.FS | 1 | module PursLoader.FS |
2 | ( FS() | 2 | ( FS() |
3 | , readFileUtf8 | 3 | , writeFileUtf8 |
4 | , readFileUtf8Sync | ||
5 | ) where | 4 | ) where |
6 | 5 | ||
7 | import Control.Monad.Aff (Aff(), makeAff) | 6 | import Control.Monad.Aff (Aff(), makeAff) |
@@ -12,34 +11,22 @@ import Data.Function | |||
12 | 11 | ||
13 | foreign import data FS :: ! | 12 | foreign import data FS :: ! |
14 | 13 | ||
15 | readFileUtf8 :: forall eff. String -> Aff (fs :: FS | eff) String | 14 | writeFileUtf8 :: forall eff. String -> String -> Aff (fs :: FS | eff) Unit |
16 | readFileUtf8 filepath = makeAff $ runFn3 readFileUtf8Fn filepath | 15 | writeFileUtf8 filepath contents = makeAff $ runFn4 writeFileUtf8Fn filepath contents |
17 | 16 | ||
18 | readFileUtf8Sync :: forall eff. String -> Eff (fs :: FS | eff) String | 17 | foreign import writeFileUtf8Fn """ |
19 | readFileUtf8Sync filepath = readFileUtf8SyncFn filepath | 18 | function writeFileUtf8Fn(filepath, contents, errback, callback) { |
20 | |||
21 | foreign import readFileUtf8Fn """ | ||
22 | function readFileUtf8Fn(filepath, errback, callback) { | ||
23 | return function(){ | 19 | return function(){ |
24 | var fs = require('fs'); | 20 | var fs = require('fs'); |
25 | 21 | ||
26 | fs.readFile(filepath, 'utf-8', function(e, data){ | 22 | fs.writeFile(filepath, contents, function(error){ |
27 | if (e) errback(e)(); | 23 | if (error) errback(error)(); |
28 | else callback(data)(); | 24 | else callback()(); |
29 | }); | 25 | }); |
30 | }; | 26 | }; |
31 | } | 27 | } |
32 | """ :: forall eff. Fn3 String | 28 | """ :: forall eff. Fn4 String |
29 | String | ||
33 | (Error -> Eff (fs :: FS | eff) Unit) | 30 | (Error -> Eff (fs :: FS | eff) Unit) |
34 | (String -> Eff (fs :: FS | eff) Unit) | 31 | (Unit -> Eff (fs :: FS | eff) Unit) |
35 | (Eff (fs :: FS | eff) Unit) | 32 | (Eff (fs :: FS | eff) Unit) |
36 | |||
37 | foreign import readFileUtf8SyncFn """ | ||
38 | function 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 index 7bc9212..392d9e4 100644 --- a/src/Glob.purs +++ b/src/Glob.purs | |||
@@ -1,6 +1,6 @@ | |||
1 | module PursLoader.Glob | 1 | module PursLoader.Glob |
2 | ( Glob() | 2 | ( Glob() |
3 | , glob | 3 | , globAll |
4 | ) where | 4 | ) where |
5 | 5 | ||
6 | import Control.Monad.Aff (Aff(), makeAff) | 6 | import Control.Monad.Aff (Aff(), makeAff) |
@@ -11,21 +11,23 @@ import Data.Function | |||
11 | 11 | ||
12 | foreign import data Glob :: ! | 12 | foreign import data Glob :: ! |
13 | 13 | ||
14 | glob :: forall eff. String -> Aff (glob :: Glob | eff) [String] | 14 | globAll :: forall eff. [String] -> Aff (glob :: Glob | eff) [[String]] |
15 | glob pattern = makeAff $ runFn3 globFn pattern | 15 | globAll patterns = makeAff $ runFn3 globAllFn patterns |
16 | 16 | ||
17 | foreign import globFn """ | 17 | foreign import globAllFn """ |
18 | function globFn(pattern, errback, callback) { | 18 | function globAllFn(patterns, errback, callback) { |
19 | return function(){ | 19 | return function(){ |
20 | var glob = require('glob'); | 20 | var glob = require('glob'); |
21 | 21 | ||
22 | glob(pattern, function(e, data){ | 22 | var async = require('async'); |
23 | if (e) errback(e)(); | 23 | |
24 | else callback(data)(); | 24 | async.map(patterns, glob, function(error, result){ |
25 | if (error) errback(new Error(error))(); | ||
26 | else callback(result)(); | ||
25 | }); | 27 | }); |
26 | }; | 28 | }; |
27 | } | 29 | } |
28 | """ :: forall eff. Fn3 String | 30 | """ :: forall eff. Fn3 [String] |
29 | (Error -> Eff (glob :: Glob | eff) Unit) | 31 | (Error -> Eff (glob :: Glob | eff) Unit) |
30 | ([String] -> Eff (glob :: Glob | eff) Unit) | 32 | ([[String]] -> Eff (glob :: Glob | eff) Unit) |
31 | (Eff (glob :: Glob | eff) Unit) | 33 | (Eff (glob :: Glob | eff) Unit) |
diff --git a/src/Loader.purs b/src/Loader.purs index fedc424..872a51c 100644 --- a/src/Loader.purs +++ b/src/Loader.purs | |||
@@ -1,5 +1,5 @@ | |||
1 | module PursLoader.Loader | 1 | module PursLoader.Loader |
2 | ( LoaderEff() | 2 | ( Effects() |
3 | , loader | 3 | , loader |
4 | , loaderFn | 4 | , loaderFn |
5 | ) where | 5 | ) where |
@@ -9,113 +9,81 @@ import Control.Monad.Eff (Eff()) | |||
9 | import Control.Monad.Eff.Class (liftEff) | 9 | import Control.Monad.Eff.Class (liftEff) |
10 | import Control.Monad.Eff.Exception (error) | 10 | import Control.Monad.Eff.Exception (error) |
11 | 11 | ||
12 | import Data.Array ((!!), catMaybes, concat, filter, null) | 12 | import Data.Array ((!!), concat) |
13 | import Data.Foldable (foldl) | ||
14 | import Data.Function (Fn2(), mkFn2) | 13 | import Data.Function (Fn2(), mkFn2) |
15 | import Data.Maybe (Maybe(..), fromMaybe, maybe) | 14 | import Data.Maybe (Maybe(..), fromMaybe, maybe) |
16 | import Data.Set (Set(), empty, insert, member, toList, unions) | 15 | import Data.String (joinWith) |
17 | import Data.String (joinWith, split) | 16 | import Data.String.Regex (match, noFlags, regex) |
18 | import Data.String.Regex (Regex(), match, noFlags, regex) | ||
19 | import Data.StrMap (StrMap(), fromList, lookup) | ||
20 | import Data.Traversable (sequence) | ||
21 | import Data.Tuple.Nested (tuple2) | ||
22 | 17 | ||
23 | import PursLoader.ChildProcess (ChildProcess(), spawn) | 18 | import PursLoader.ChildProcess (ChildProcess(), spawn) |
24 | import PursLoader.FS (FS(), readFileUtf8, readFileUtf8Sync) | 19 | import PursLoader.FS (FS(), writeFileUtf8) |
25 | import PursLoader.Glob (Glob(), glob) | 20 | import PursLoader.Glob (Glob(), globAll) |
26 | import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, clearDependencies, addDependency, query, resourcePath) | 21 | import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query) |
27 | import PursLoader.LoaderUtil (getRemainingRequest, parseQuery) | 22 | import PursLoader.LoaderUtil (parseQuery) |
28 | import PursLoader.OS (eol) | 23 | import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions) |
29 | import PursLoader.Options (loaderSrcOption, pscMakeOptions, pscMakeDefaultOutput, pscMakeOutputOption) | ||
30 | import PursLoader.Path (dirname, join, relative, resolve) | ||
31 | 24 | ||
32 | foreign import cwd "var cwd = process.cwd();" :: String | 25 | type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader | eff) |
33 | 26 | ||
34 | moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } | 27 | moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } |
35 | 28 | ||
36 | importRegex = regex "^\\s*import\\s+(?:qualified\\s+)?([\\w\\.]+)" noFlags { ignoreCase = true } | 29 | pscCommand = "psc" |
37 | |||
38 | bowerPattern = join [ "bower_components", "purescript-*", "src" ] | ||
39 | 30 | ||
40 | pscMakeCommand = "psc-make" | 31 | psciCommand = "psci" |
41 | 32 | ||
42 | indexFilename = "index.js" | 33 | psciFilename = ".psci" |
43 | 34 | ||
44 | (!!!) = flip (!!) | 35 | (!!!) = flip (!!) |
45 | 36 | ||
46 | pursPattern :: [String] -> String | 37 | foreign import cwd "var cwd = process.cwd();" :: String |
47 | pursPattern srcs = join [ "{" ++ joinWith "," ([ bowerPattern ] <> srcs) ++ "}" | ||
48 | , "**" | ||
49 | , "*.purs" | ||
50 | ] | ||
51 | |||
52 | type GraphModule = { file :: String, imports :: [String] } | ||
53 | 38 | ||
54 | type Graph = StrMap GraphModule | 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 | ||
55 | 53 | ||
56 | mkGraph :: forall eff. [String] -> Eff (fs :: FS | eff) Graph | 54 | loadForeign :: String -> String |
57 | mkGraph files = (fromList <<< catMaybes) <$> sequence (parse <$> files) | 55 | loadForeign a = ":f " ++ relative cwd a |
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 | 56 | ||
64 | mkDeps :: forall eff. String -> Graph -> [String] | 57 | loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String) |
65 | mkDeps 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 | |||
76 | addDeps :: forall eff. LoaderRef -> Graph -> [String] -> Eff (loader :: Loader | eff) Unit | ||
77 | addDeps 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 | |||
82 | type LoaderAff eff a = Aff (loader :: Loader, glob :: Glob, cp :: ChildProcess, fs :: FS | eff) a | ||
83 | |||
84 | loader' :: forall eff. LoaderRef -> String -> LoaderAff eff (Maybe String) | ||
85 | loader' ref source = do | 58 | loader' ref source = do |
86 | liftEff $ cacheable ref | 59 | liftEff $ cacheable ref |
87 | 60 | ||
88 | let request = getRemainingRequest ref | 61 | let parsed = parseQuery $ query ref |
89 | parsed = parseQuery $ query ref | 62 | srcs = fromMaybe [] (loaderSrcOption parsed) |
90 | srcs = loaderSrcOption parsed | 63 | ffis = fromMaybe [] (loaderFFIOption parsed) |
91 | opts = pscMakeOptions parsed | 64 | opts = pscOptions parsed |
92 | pattern = pursPattern $ fromMaybe [] srcs | 65 | |
93 | key = match moduleRegex source >>= (!!!) 1 | 66 | spawn pscCommand (srcs <> opts) |
94 | 67 | ||
95 | files <- glob pattern | 68 | srcss <- globAll srcs |
96 | graph <- liftEff $ mkGraph files | 69 | ffiss <- globAll ffis |
97 | 70 | ||
98 | let deps = fromMaybe [] $ flip mkDeps graph <$> key | 71 | let psciFile = mkPsci srcss ffiss |
99 | outputPath = fromMaybe pscMakeDefaultOutput $ pscMakeOutputOption parsed | ||
100 | indexPath = (\a -> join [ outputPath, a, indexFilename ]) <$> key | ||
101 | 72 | ||
102 | liftEff $ clearDependencies ref | 73 | writeFileUtf8 psciFilename psciFile |
103 | liftEff $ addDependency ref (resourcePath ref) | ||
104 | liftEff $ addDeps ref graph deps | ||
105 | 74 | ||
106 | spawn pscMakeCommand (opts <> files) | 75 | let moduleName = match moduleRegex source >>= (!!!) 1 |
107 | indexFile <- sequence $ readFileUtf8 <$> indexPath | 76 | result = (\a -> "module.exports = require('" ++ a ++ "');") <$> moduleName |
108 | return indexFile | ||
109 | 77 | ||
110 | type LoaderEff eff a = Eff (loader :: Loader, glob :: Glob, cp :: ChildProcess, fs :: FS | eff) a | 78 | return result |
111 | 79 | ||
112 | loader :: forall eff. LoaderRef -> String -> LoaderEff eff Unit | 80 | loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit |
113 | loader ref source = do | 81 | loader ref source = do |
114 | callback <- async ref | 82 | callback <- async ref |
115 | runAff (\e -> callback (Just e) "") | 83 | runAff (\e -> callback (Just e) "") |
116 | (maybe (callback (Just $ error "Loader has failed to run") "") | 84 | (maybe (callback (Just (error "Loader has failed to run")) "") |
117 | (callback Nothing)) | 85 | (callback Nothing)) |
118 | (loader' ref source) | 86 | (loader' ref source) |
119 | 87 | ||
120 | loaderFn :: forall eff. Fn2 LoaderRef String (LoaderEff eff Unit) | 88 | loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) |
121 | loaderFn = mkFn2 loader | 89 | loaderFn = 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 | ||
12 | import Control.Monad.Eff (Eff()) | 9 | import Control.Monad.Eff (Eff()) |
13 | import Control.Monad.Eff.Exception (Error()) | 10 | import Control.Monad.Eff.Exception (Error()) |
14 | 11 | ||
15 | import Data.Foreign (Foreign()) | ||
16 | import Data.Function (Fn3(), runFn3) | 12 | import Data.Function (Fn3(), runFn3) |
17 | import Data.Maybe (Maybe(), fromMaybe, isJust) | 13 | import 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 | ||
51 | foreign import clearDependencies """ | ||
52 | function clearDependencies(ref){ | ||
53 | return function(){ | ||
54 | return ref.clearDependencies(); | ||
55 | }; | ||
56 | }""" :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit | ||
57 | |||
58 | foreign import resourcePath """ | ||
59 | function resourcePath(ref){ | ||
60 | return ref.resourcePath; | ||
61 | }""" :: LoaderRef -> String | ||
62 | |||
63 | foreign import addDependency """ | ||
64 | function 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 | |||
72 | foreign import query """ | 47 | foreign import query """ |
73 | function query(ref){ | 48 | function query(ref){ |
74 | return ref.query; | 49 | return ref.query; |
diff --git a/src/LoaderUtil.purs b/src/LoaderUtil.purs index f22be44..86be124 100644 --- a/src/LoaderUtil.purs +++ b/src/LoaderUtil.purs | |||
@@ -1,18 +1,11 @@ | |||
1 | module PursLoader.LoaderUtil | 1 | module PursLoader.LoaderUtil |
2 | ( getRemainingRequest | 2 | ( parseQuery |
3 | , parseQuery | ||
4 | ) where | 3 | ) where |
5 | 4 | ||
6 | import Data.Foreign (Foreign()) | 5 | import Data.Foreign (Foreign()) |
7 | 6 | ||
8 | import PursLoader.LoaderRef (LoaderRef()) | 7 | import PursLoader.LoaderRef (LoaderRef()) |
9 | 8 | ||
10 | foreign import getRemainingRequest """ | ||
11 | function getRemainingRequest(ref){ | ||
12 | var loaderUtils = require('loader-utils'); | ||
13 | return loaderUtils.getRemainingRequest(ref); | ||
14 | }""" :: LoaderRef -> String | ||
15 | |||
16 | foreign import parseQuery """ | 9 | foreign import parseQuery """ |
17 | function parseQuery(query){ | 10 | function parseQuery(query){ |
18 | var loaderUtils = require('loader-utils'); | 11 | var loaderUtils = require('loader-utils'); |
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 @@ | |||
1 | module PursLoader.OS (eol) where | ||
2 | |||
3 | foreign import eol "var eol = require('os').EOL;" :: String | ||
diff --git a/src/Options.purs b/src/Options.purs index c47bebc..51e9be5 100644 --- a/src/Options.purs +++ b/src/Options.purs | |||
@@ -1,17 +1,17 @@ | |||
1 | module PursLoader.Options | 1 | module PursLoader.Options |
2 | ( pscMakeOptions | 2 | ( pscOptions |
3 | , pscMakeDefaultOutput | ||
4 | , pscMakeOutputOption | ||
5 | , loaderSrcOption | 3 | , loaderSrcOption |
4 | , loaderFFIOption | ||
6 | ) where | 5 | ) where |
7 | 6 | ||
7 | import Data.Array (concat) | ||
8 | import Data.Either (either) | 8 | import Data.Either (either) |
9 | 9 | ||
10 | import Data.Foreign (Foreign(), F()) | 10 | import Data.Foreign (Foreign(), F()) |
11 | import Data.Foreign.Class (IsForeign, read, readProp) | 11 | import Data.Foreign.Class (IsForeign, read, readProp) |
12 | import Data.Foreign.NullOrUndefined (NullOrUndefined(), runNullOrUndefined) | 12 | import Data.Foreign.NullOrUndefined (NullOrUndefined(..), runNullOrUndefined) |
13 | 13 | ||
14 | import Data.Maybe (Maybe(..), maybe) | 14 | import Data.Maybe (Maybe(..), maybe, fromMaybe) |
15 | 15 | ||
16 | noPreludeOpt = "no-prelude" | 16 | noPreludeOpt = "no-prelude" |
17 | 17 | ||
@@ -29,9 +29,11 @@ commentsOpt = "comments" | |||
29 | 29 | ||
30 | noPrefixOpt = "no-prefix" | 30 | noPrefixOpt = "no-prefix" |
31 | 31 | ||
32 | requirePathOpt = "require-path" | ||
33 | |||
32 | srcOpt = "src" | 34 | srcOpt = "src" |
33 | 35 | ||
34 | pscMakeDefaultOutput = "output" | 36 | ffiOpt = "ffi" |
35 | 37 | ||
36 | newtype Options | 38 | newtype Options |
37 | = Options { noPrelude :: NullOrUndefined Boolean | 39 | = Options { noPrelude :: NullOrUndefined Boolean |
@@ -42,7 +44,9 @@ newtype Options | |||
42 | , comments :: NullOrUndefined Boolean | 44 | , comments :: NullOrUndefined Boolean |
43 | , output :: NullOrUndefined String | 45 | , output :: NullOrUndefined String |
44 | , noPrefix :: NullOrUndefined Boolean | 46 | , noPrefix :: NullOrUndefined Boolean |
47 | , requirePath :: NullOrUndefined String | ||
45 | , src :: NullOrUndefined [String] | 48 | , src :: NullOrUndefined [String] |
49 | , ffi :: NullOrUndefined [String] | ||
46 | } | 50 | } |
47 | 51 | ||
48 | instance isForeignOptions :: IsForeign Options where | 52 | instance isForeignOptions :: IsForeign Options where |
@@ -54,7 +58,9 @@ instance isForeignOptions :: IsForeign Options where | |||
54 | , comments: _ | 58 | , comments: _ |
55 | , output: _ | 59 | , output: _ |
56 | , noPrefix: _ | 60 | , noPrefix: _ |
61 | , requirePath: _ | ||
57 | , src: _ | 62 | , src: _ |
63 | , ffi: _ | ||
58 | } <$> readProp noPreludeOpt obj | 64 | } <$> readProp noPreludeOpt obj |
59 | <*> readProp noOptsOpt obj | 65 | <*> readProp noOptsOpt obj |
60 | <*> readProp noMagicDoOpt obj | 66 | <*> readProp noMagicDoOpt obj |
@@ -63,26 +69,25 @@ instance isForeignOptions :: IsForeign Options where | |||
63 | <*> readProp commentsOpt obj | 69 | <*> readProp commentsOpt obj |
64 | <*> readProp outputOpt obj | 70 | <*> readProp outputOpt obj |
65 | <*> readProp noPrefixOpt obj | 71 | <*> readProp noPrefixOpt obj |
66 | <*> readProp srcOpt obj) | 72 | <*> readProp requirePathOpt obj |
73 | <*> readProp srcOpt obj | ||
74 | <*> readProp ffiOpt obj) | ||
67 | 75 | ||
68 | class LoaderOption a where | 76 | class LoaderOption a where |
69 | opt :: String -> NullOrUndefined a -> [String] | 77 | opt :: String -> NullOrUndefined a -> [String] |
70 | 78 | ||
71 | instance booleanLoaderOption :: LoaderOption Boolean where | 79 | instance booleanLoaderOption :: LoaderOption Boolean where |
72 | opt key opt = maybe [] (\a -> if a then ["--" ++ key] else []) | 80 | opt key val = maybe [] (\a -> if a then ["--" ++ key] else []) (runNullOrUndefined val) |
73 | (runNullOrUndefined opt) | ||
74 | 81 | ||
75 | instance stringLoaderOption :: LoaderOption String where | 82 | instance stringLoaderOption :: LoaderOption String where |
76 | opt key opt = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) | 83 | opt key val = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) (runNullOrUndefined val) |
77 | (runNullOrUndefined opt) | ||
78 | 84 | ||
79 | pscMakeOutputOption :: Foreign -> Maybe String | 85 | instance arrayLoaderOption :: (LoaderOption a) => LoaderOption [a] where |
80 | pscMakeOutputOption query = either (const Nothing) | 86 | opt key val = concat (opt key <$> (NullOrUndefined <<< Just) |
81 | (\(Options a) -> runNullOrUndefined a.output) | 87 | <$> (fromMaybe [] (runNullOrUndefined val))) |
82 | (read query) | ||
83 | 88 | ||
84 | pscMakeOptions :: Foreign -> [String] | 89 | pscOptions :: Foreign -> [String] |
85 | pscMakeOptions query = either (const []) fold parsed | 90 | pscOptions query = either (const []) fold parsed |
86 | where parsed = read query :: F Options | 91 | where parsed = read query :: F Options |
87 | fold (Options a) = opt noPreludeOpt a.noPrelude <> | 92 | fold (Options a) = opt noPreludeOpt a.noPrelude <> |
88 | opt noOptsOpt a.noOpts <> | 93 | opt noOptsOpt a.noOpts <> |
@@ -91,9 +96,12 @@ pscMakeOptions query = either (const []) fold parsed | |||
91 | opt verboseErrorsOpt a.verboseErrors <> | 96 | opt verboseErrorsOpt a.verboseErrors <> |
92 | opt commentsOpt a.comments <> | 97 | opt commentsOpt a.comments <> |
93 | opt outputOpt a.output <> | 98 | opt outputOpt a.output <> |
94 | opt noPrefixOpt a.noPrefix | 99 | opt noPrefixOpt a.noPrefix <> |
100 | opt requirePathOpt a.requirePath <> | ||
101 | opt ffiOpt a.ffi | ||
95 | 102 | ||
96 | loaderSrcOption :: Foreign -> Maybe [String] | 103 | loaderSrcOption :: Foreign -> Maybe [String] |
97 | loaderSrcOption query = either (const Nothing) | 104 | loaderSrcOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.src) (read query) |
98 | (\(Options a) -> runNullOrUndefined a.src) | 105 | |
99 | (read query) | 106 | loaderFFIOption :: Foreign -> Maybe [String] |
107 | loaderFFIOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.ffi) (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 @@ | |||
1 | module PursLoader.Path | ||
2 | ( dirname | ||
3 | , join | ||
4 | , relative | ||
5 | , resolve | ||
6 | ) where | ||
7 | |||
8 | foreign import dirname """ | ||
9 | function dirname(filepath) { | ||
10 | var path = require('path'); | ||
11 | return path.dirname(filepath); | ||
12 | } | ||
13 | """ :: String -> String | ||
14 | |||
15 | foreign import join """ | ||
16 | function join(parts) { | ||
17 | var path = require('path'); | ||
18 | return path.join.apply(path, parts); | ||
19 | } | ||
20 | """ :: [String] -> String | ||
21 | |||
22 | foreign import relative """ | ||
23 | function relative(from) { | ||
24 | return function(to){ | ||
25 | var path = require('path'); | ||
26 | return path.relative(from, to); | ||
27 | }; | ||
28 | } | ||
29 | """ :: String -> String -> String | ||
30 | |||
31 | foreign import resolve """ | ||
32 | function resolve(filepath) { | ||
33 | var path = require('path'); | ||
34 | return path.resolve(filepath); | ||
35 | } | ||
36 | """ :: String -> String | ||
diff --git a/webpack.config.js b/webpack.config.js index 11b9069..a39832f 100644 --- a/webpack.config.js +++ b/webpack.config.js | |||
@@ -4,6 +4,8 @@ var path = require('path'); | |||
4 | 4 | ||
5 | var webpack = require('webpack'); | 5 | var webpack = require('webpack'); |
6 | 6 | ||
7 | var packageJson = require('./package.json'); | ||
8 | |||
7 | var noErrorsPlugin = webpack.NoErrorsPlugin; | 9 | var noErrorsPlugin = webpack.NoErrorsPlugin; |
8 | 10 | ||
9 | var dedupePlugin = webpack.optimize.DedupePlugin; | 11 | var dedupePlugin = webpack.optimize.DedupePlugin; |
@@ -12,9 +14,10 @@ var config | |||
12 | = { cache: true | 14 | = { cache: true |
13 | , target: 'node' | 15 | , target: 'node' |
14 | , entry: { index: './entry' } | 16 | , entry: { index: './entry' } |
15 | , externals: { 'glob': 'commonjs glob' | 17 | , externals: Object.keys(packageJson.dependencies).reduce(function(b, a){ |
16 | , 'loader-utils': 'commonjs loader-utils' | 18 | b[a] = 'commonjs ' + a; |
17 | } | 19 | return b; |
20 | }, {}) | ||
18 | , output: { path: __dirname | 21 | , output: { path: __dirname |
19 | , filename: '[name].js' | 22 | , filename: '[name].js' |
20 | , libraryTarget: 'commonjs2' | 23 | , libraryTarget: 'commonjs2' |