aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoreric <thul.eric@gmail.com>2016-01-19 08:41:51 -0500
committereric <thul.eric@gmail.com>2016-01-19 08:41:51 -0500
commit2ecf85616a2b56ec9ff675c8f45b7dcf5607fc86 (patch)
treef8ad39dc0d21ae4add8f2a3877edf24294d2910f
parent94cc1cdd03b9c2115813a698b1e4337bce894321 (diff)
parentc01553307e6fcd0abada0b9b2f9ca8d6bb82b863 (diff)
downloadpurs-loader-2ecf85616a2b56ec9ff675c8f45b7dcf5607fc86.tar.gz
purs-loader-2ecf85616a2b56ec9ff675c8f45b7dcf5607fc86.tar.zst
purs-loader-2ecf85616a2b56ec9ff675c8f45b7dcf5607fc86.zip
Merge pull request #34 from ethul/topic/psc-webpack-plugin
Topic/psc webpack plugin
-rw-r--r--.gitignore2
-rw-r--r--README.md69
-rw-r--r--bower.json5
-rw-r--r--docs/PursLoader/ChildProcess.md15
-rw-r--r--docs/PursLoader/FS.md21
-rw-r--r--docs/PursLoader/Glob.md15
-rw-r--r--docs/PursLoader/Loader.md2
-rw-r--r--docs/PursLoader/LoaderRef.md8
-rw-r--r--docs/PursLoader/Options.md24
-rw-r--r--docs/PursLoader/Path.md27
-rw-r--r--example/package.json7
-rw-r--r--example/src/Bar.purs3
-rw-r--r--example/src/Foo.purs6
-rw-r--r--example/src/Test.purs6
-rw-r--r--example/src/entry.js10
-rw-r--r--example/src/jam.js5
-rw-r--r--example/webpack.config.js18
-rw-r--r--package.json12
-rw-r--r--src/PursLoader/ChildProcess.js40
-rw-r--r--src/PursLoader/ChildProcess.purs23
-rw-r--r--src/PursLoader/FS.js36
-rw-r--r--src/PursLoader/FS.purs38
-rw-r--r--src/PursLoader/Glob.js18
-rw-r--r--src/PursLoader/Glob.purs22
-rw-r--r--src/PursLoader/Loader.purs133
-rw-r--r--src/PursLoader/LoaderRef.purs13
-rw-r--r--src/PursLoader/LoaderUtil.purs2
-rw-r--r--src/PursLoader/Options.purs121
-rw-r--r--src/PursLoader/Path.js (renamed from src/PursLoader/Loader.js)11
-rw-r--r--src/PursLoader/Path.purs14
30 files changed, 184 insertions, 542 deletions
diff --git a/.gitignore b/.gitignore
index dd8eead..6c930c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
1.psci 1.psci
2.pulp-cache
2npm-debug.log 3npm-debug.log
3index.json 4index.json
4index.js 5index.js
@@ -9,3 +10,4 @@ example/bundle.js
9example/node_modules/ 10example/node_modules/
10example/bower_components/ 11example/bower_components/
11example/output/ 12example/output/
13tmp/
diff --git a/README.md b/README.md
index bef16af..0e1ce2f 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,9 @@
4 4
5## Install 5## Install
6 6
7Install with [npm](https://npmjs.org/package/purs-loader) 7Install with [npm](https://npmjs.org/package/purs-loader).
8
9This loader works in conjunction with the [PureScript webpack plugin](https://npmjs.org/package/purescript-webpack-plugin). Ensure the plugin is installed and configured accordingly.
8 10
9``` 11```
10npm install purs-loader --save-dev 12npm install purs-loader --save-dev
@@ -12,64 +14,25 @@ npm install purs-loader --save-dev
12 14
13## Options 15## Options
14 16
15###### `noPrelude` (Boolean) 17###### `bundleOutput` (String)
16
17Toggles `--no-prelude` that omits the Prelude.
18
19###### `noTco` (Boolean)
20
21Toggles `--no-tco` that disables tail-call optimizations.
22
23###### `noMagicDo` (Boolean)
24
25Toggles `--no-magic-do` that disables optimizations overloading the do keyword generating efficient code for the `Eff` monad.
26
27###### `noOpts` (Boolean)
28
29Toggles `--no-opts` that skips the optimization phase.
30
31###### `verboseErrors` (Boolean)
32
33Toggles `--verbose-errors` that displays verbose error messages.
34
35###### `comments` (Boolean)
36 18
37Toggles `--comments` that includes comments in generated code. 19Relative path to the bundled JavaScript file generated by the `PurescriptWebpackPlugin`. The default value is `output/bundle.js`.
38
39###### `output` (String)
40
41Sets `--output=<string>` the specifies the output directory, `output` by default.
42
43###### `noPrefix` (Boolean)
44
45Toggles `--no-prefix` that does not include the comment header.
46
47###### `ffi` (String Array)
48
49Specifies the PureScript FFI files setting `--ffi=<string>`. Glob syntax is supported. This option is specified as `ffi[]=path`.
50
51###### `src` (String Array)
52
53Specifies the PureScript source files. Glob syntax is supported. This option is specified as `src[]=path`.
54 20
55## Example 21## Example
56 22
57```js 23```js
58// webpack.config.js 24// webpack.config.js
25'use strict';
59 26
60var path = require('path'); 27var PurescriptWebpackPlugin = require('purescript-webpack-plugin');
61
62var srcs = ['src[]=bower_components/purescript-*/src/**/*.purs', 'src[]=src/**/*.purs'];
63 28
64var ffis = ['ffi[]=bower_components/purescript-*/src/**/*.js']; 29var src = ['bower_components/purescript-*/src/**/*.purs', 'src/**/*.purs'];
65 30
66var output = 'output'; 31var ffi = ['bower_components/purescript-*/src/**/*.js', 'src/**/*FFI.js'];
67 32
68var modulesDirectories = [ 33var modulesDirectories = [
69 'node_modules', 34 'node_modules',
70 // The bower component for purescript-prelude is specified here to 35 'bower_components'
71 // allow JavaScript files to require the 'Prelude' module globally.
72 'bower_components/purescript-prelude/src'
73]; 36];
74 37
75var config 38var config
@@ -79,12 +42,10 @@ var config
79 , filename: 'bundle.js' 42 , filename: 'bundle.js'
80 } 43 }
81 , module: { loaders: [ { test: /\.purs$/ 44 , module: { loaders: [ { test: /\.purs$/
82 , loader: 'purs-loader?output=' + output + '&' + srcs.concat(ffis).join('&') 45 , loader: 'purs-loader'
83 } ] } 46 } ] }
84 , resolve: { modulesDirectories: modulesDirectories 47 , resolve: { modulesDirectories: modulesDirectories }
85 , extensions: ['', '.js', '.purs'] 48 , plugins: [ new PurescriptWebpackPlugin({src: src, ffi: ffi}) ]
86 }
87 , resolveLoader: { root: path.join(__dirname, 'node_modules') }
88 } 49 }
89 ; 50 ;
90 51
@@ -92,7 +53,3 @@ module.exports = config;
92``` 53```
93 54
94See the [example](https://github.com/ethul/purs-loader/tree/master/example) directory for a complete example. 55See the [example](https://github.com/ethul/purs-loader/tree/master/example) directory for a complete example.
95
96## Notes
97
98A `.psci` file is generated during each run of the loader.
diff --git a/bower.json b/bower.json
index aabc633..8b61f6f 100644
--- a/bower.json
+++ b/bower.json
@@ -1,9 +1,10 @@
1{ 1{
2 "name": "purs-loader", 2 "name": "purs-loader",
3 "private": true, 3 "private": true,
4 "devDependencies": { 4 "dependencies": {
5 "purescript-aff": "^0.13.0", 5 "purescript-aff": "^0.13.0",
6 "purescript-strings": "^0.7.0", 6 "purescript-strings": "^0.7.0",
7 "purescript-foreign": "^0.7.0" 7 "purescript-foreign": "^0.7.0",
8 "purescript-unsafe-coerce": "~0.1.0"
8 } 9 }
9} 10}
diff --git a/docs/PursLoader/ChildProcess.md b/docs/PursLoader/ChildProcess.md
deleted file mode 100644
index 7c2e414..0000000
--- a/docs/PursLoader/ChildProcess.md
+++ /dev/null
@@ -1,15 +0,0 @@
1## Module PursLoader.ChildProcess
2
3#### `ChildProcess`
4
5``` purescript
6data ChildProcess :: !
7```
8
9#### `spawn`
10
11``` purescript
12spawn :: forall eff. String -> Array String -> Aff (cp :: ChildProcess | eff) String
13```
14
15
diff --git a/docs/PursLoader/FS.md b/docs/PursLoader/FS.md
deleted file mode 100644
index 811fcbd..0000000
--- a/docs/PursLoader/FS.md
+++ /dev/null
@@ -1,21 +0,0 @@
1## Module PursLoader.FS
2
3#### `FS`
4
5``` purescript
6data FS :: !
7```
8
9#### `writeFileUtf8`
10
11``` purescript
12writeFileUtf8 :: forall eff. String -> String -> Aff (fs :: FS | eff) Unit
13```
14
15#### `findFileUtf8`
16
17``` purescript
18findFileUtf8 :: forall eff. Regex -> Array String -> Aff (fs :: FS | eff) (Maybe String)
19```
20
21
diff --git a/docs/PursLoader/Glob.md b/docs/PursLoader/Glob.md
deleted file mode 100644
index f7abe78..0000000
--- a/docs/PursLoader/Glob.md
+++ /dev/null
@@ -1,15 +0,0 @@
1## Module PursLoader.Glob
2
3#### `Glob`
4
5``` purescript
6data Glob :: !
7```
8
9#### `globAll`
10
11``` purescript
12globAll :: forall eff. Array String -> Aff (glob :: Glob | eff) (Array (Array String))
13```
14
15
diff --git a/docs/PursLoader/Loader.md b/docs/PursLoader/Loader.md
index f81c486..bb02470 100644
--- a/docs/PursLoader/Loader.md
+++ b/docs/PursLoader/Loader.md
@@ -3,7 +3,7 @@
3#### `Effects` 3#### `Effects`
4 4
5``` purescript 5``` purescript
6type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader, err :: EXCEPTION | eff) 6type Effects eff = (loader :: Loader | eff)
7``` 7```
8 8
9#### `loader` 9#### `loader`
diff --git a/docs/PursLoader/LoaderRef.md b/docs/PursLoader/LoaderRef.md
index 36c1550..60341f7 100644
--- a/docs/PursLoader/LoaderRef.md
+++ b/docs/PursLoader/LoaderRef.md
@@ -1,5 +1,11 @@
1## Module PursLoader.LoaderRef 1## Module PursLoader.LoaderRef
2 2
3#### `AsyncCallback`
4
5``` purescript
6type AsyncCallback eff = Maybe Error -> String -> Eff (loader :: Loader | eff) Unit
7```
8
3#### `LoaderRef` 9#### `LoaderRef`
4 10
5``` purescript 11``` purescript
@@ -15,7 +21,7 @@ data Loader :: !
15#### `async` 21#### `async`
16 22
17``` purescript 23``` purescript
18async :: forall eff a. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> a -> Eff (loader :: Loader | eff) Unit) 24async :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> String -> Eff (loader :: Loader | eff) Unit)
19``` 25```
20 26
21#### `cacheable` 27#### `cacheable`
diff --git a/docs/PursLoader/Options.md b/docs/PursLoader/Options.md
index 4202475..2bfcddd 100644
--- a/docs/PursLoader/Options.md
+++ b/docs/PursLoader/Options.md
@@ -8,31 +8,13 @@ newtype Options
8 8
9##### Instances 9##### Instances
10``` purescript 10``` purescript
11instance isForeignOptions :: IsForeign Options 11IsForeign Options
12``` 12```
13 13
14#### `output` 14#### `runOptions`
15 15
16``` purescript 16``` purescript
17output :: Options -> String 17runOptions :: Options -> Options_
18```
19
20#### `pscOptions`
21
22``` purescript
23pscOptions :: Options -> Array String
24```
25
26#### `loaderSrcOption`
27
28``` purescript
29loaderSrcOption :: Foreign -> Maybe (Array String)
30```
31
32#### `loaderFFIOption`
33
34``` purescript
35loaderFFIOption :: Foreign -> Maybe (Array String)
36``` 18```
37 19
38 20
diff --git a/docs/PursLoader/Path.md b/docs/PursLoader/Path.md
new file mode 100644
index 0000000..cc00436
--- /dev/null
+++ b/docs/PursLoader/Path.md
@@ -0,0 +1,27 @@
1## Module PursLoader.Path
2
3#### `relative`
4
5``` purescript
6relative :: String -> String -> String
7```
8
9#### `resolve`
10
11``` purescript
12resolve :: String -> String
13```
14
15#### `dirname`
16
17``` purescript
18dirname :: String -> String
19```
20
21#### `joinPath`
22
23``` purescript
24joinPath :: String -> String -> String
25```
26
27
diff --git a/example/package.json b/example/package.json
index d1319b1..e256de8 100644
--- a/example/package.json
+++ b/example/package.json
@@ -3,15 +3,16 @@
3 "version": "0.0.0", 3 "version": "0.0.0",
4 "private": true, 4 "private": true,
5 "scripts": { 5 "scripts": {
6 "build": "mkdir -p output && ./node_modules/.bin/webpack --progress --colors", 6 "build": "webpack --progress --colors --bail",
7 "build:watch": "mkdir -p output && ./node_modules/.bin/webpack --progress --colors --watch", 7 "build:watch": "webpack --progress --colors --watch",
8 "run": "node bundle.js", 8 "run": "node bundle.js",
9 "clean": "rm -rf bower_components && rm -rf bundle.js && rm -rf node_modules && rm -rf output" 9 "clean": "rm -rf bower_components && rm -rf bundle.js && rm -rf node_modules && rm -rf output"
10 }, 10 },
11 "license": "MIT", 11 "license": "MIT",
12 "devDependencies": { 12 "devDependencies": {
13 "node-libs-browser": "^0.5.2", 13 "node-libs-browser": "^0.5.2",
14 "purescript-webpack-plugin": "^0.1.1",
14 "purs-loader": "file:../", 15 "purs-loader": "file:../",
15 "webpack": "^1.10.1" 16 "webpack": "^1.12.9"
16 } 17 }
17} 18}
diff --git a/example/src/Bar.purs b/example/src/Bar.purs
new file mode 100644
index 0000000..a37171f
--- /dev/null
+++ b/example/src/Bar.purs
@@ -0,0 +1,3 @@
1module Bar where
2
3test = "b"
diff --git a/example/src/Foo.purs b/example/src/Foo.purs
index b234e0d..97b7cec 100644
--- a/example/src/Foo.purs
+++ b/example/src/Foo.purs
@@ -1,9 +1,9 @@
1module Foo (foo) where 1module Foo where
2 2
3import Prelude 3import Prelude
4 4
5import qualified Foo.Bar as B 5import qualified Foo.Bar as B
6 6
7foo = "b" 7foo = "A"
8 8
9foo' = "c" 9bar = "B"
diff --git a/example/src/Test.purs b/example/src/Test.purs
index 133a192..3a92681 100644
--- a/example/src/Test.purs
+++ b/example/src/Test.purs
@@ -1,7 +1,7 @@
1module Test (test, testing) where 1module Test (testing) where
2 2
3import Prelude 3bar = "c"
4 4
5test = "a" 5goo = "a"
6 6
7foreign import testing :: String 7foreign import testing :: String
diff --git a/example/src/entry.js b/example/src/entry.js
index cde8507..a1e2a99 100644
--- a/example/src/entry.js
+++ b/example/src/entry.js
@@ -1,9 +1,11 @@
1var Prelude = require('Prelude'); 1var Prelude = require('purescript-prelude/src/Prelude');
2 2
3var test = require('./Test.purs'); 3var test = require('./Test');
4 4
5var foo = require('./Foo.purs'); 5var foo = require('./Foo.purs');
6 6
7var baz = require('./Foo/Baz.purs'); 7var baz = require('./Foo/Baz');
8 8
9console.log(Prelude, test, foo, baz); 9var jam = require('./jam');
10
11console.log(Prelude, test, foo, baz, jam);
diff --git a/example/src/jam.js b/example/src/jam.js
new file mode 100644
index 0000000..8889a69
--- /dev/null
+++ b/example/src/jam.js
@@ -0,0 +1,5 @@
1var x = 'a';
2
3var abcde = require('./Bar');
4
5module.exports = abcde;
diff --git a/example/webpack.config.js b/example/webpack.config.js
index f1456d5..602de84 100644
--- a/example/webpack.config.js
+++ b/example/webpack.config.js
@@ -1,14 +1,14 @@
1var path = require('path'); 1'use strict';
2 2
3var srcs = ['src[]=bower_components/purescript-*/src/**/*.purs', 'src[]=src/**/*.purs']; 3var PurescriptWebpackPlugin = require('purescript-webpack-plugin');
4 4
5var ffis = ['ffi[]=bower_components/purescript-*/src/**/*.js', 'ffi[]=src/**/*FFI.js']; 5var src = ['bower_components/purescript-*/src/**/*.purs', 'src/**/*.purs'];
6 6
7var output = 'output'; 7var ffi = ['bower_components/purescript-*/src/**/*.js', 'src/**/*FFI.js'];
8 8
9var modulesDirectories = [ 9var modulesDirectories = [
10 'node_modules', 10 'node_modules',
11 'bower_components/purescript-prelude/src' 11 'bower_components'
12]; 12];
13 13
14var config 14var config
@@ -18,12 +18,10 @@ var config
18 , filename: 'bundle.js' 18 , filename: 'bundle.js'
19 } 19 }
20 , module: { loaders: [ { test: /\.purs$/ 20 , module: { loaders: [ { test: /\.purs$/
21 , loader: 'purs-loader?output=' + output + '&' + srcs.concat(ffis).join('&') 21 , loader: 'purs-loader'
22 } ] } 22 } ] }
23 , resolve: { modulesDirectories: modulesDirectories 23 , resolve: { modulesDirectories: modulesDirectories, extensions: [ '', '.js', '.purs'] }
24 , extensions: ['', '.js'] 24 , plugins: [ new PurescriptWebpackPlugin({src: src, ffi: ffi}) ]
25 }
26 , resolveLoader: { root: path.join(__dirname, 'node_modules') }
27 } 25 }
28 ; 26 ;
29 27
diff --git a/package.json b/package.json
index b1ae011..13d4c6c 100644
--- a/package.json
+++ b/package.json
@@ -10,24 +10,22 @@
10 }, 10 },
11 "scripts": { 11 "scripts": {
12 "build": "npm run-script build:compile && npm run-script build:docs && npm run-script build:package", 12 "build": "npm run-script build:compile && npm run-script build:docs && npm run-script build:package",
13 "build:compile": "./node_modules/.bin/pulp build -o build", 13 "build:compile": "pulp build -o build --force",
14 "build:docs": "./node_modules/.bin/pulp docs", 14 "build:docs": "pulp docs",
15 "build:package": "./node_modules/.bin/webpack --progress --colors --profile --bail", 15 "build:package": "webpack --progress --colors --profile --bail",
16 "build:watch": "./node_modules/.bin/pulp -w build -o build", 16 "build:watch": "pulp -w build -o build --force",
17 "build:json": "./node_modules/.bin/webpack --progress --colors --profile --bail --json > index.json", 17 "build:json": "webpack --progress --colors --profile --bail --json > index.json",
18 "prepublish": "npm run-script build" 18 "prepublish": "npm run-script build"
19 }, 19 },
20 "files": [ 20 "files": [
21 "index.js" 21 "index.js"
22 ], 22 ],
23 "devDependencies": { 23 "devDependencies": {
24 "pulp": "^4.3.0",
25 "webpack": "^1.8.4" 24 "webpack": "^1.8.4"
26 }, 25 },
27 "dependencies": { 26 "dependencies": {
28 "async": "^1.3.0", 27 "async": "^1.3.0",
29 "chalk": "^1.1.0", 28 "chalk": "^1.1.0",
30 "glob": "^5.0.3",
31 "loader-utils": "^0.2.6" 29 "loader-utils": "^0.2.6"
32 } 30 }
33} 31}
diff --git a/src/PursLoader/ChildProcess.js b/src/PursLoader/ChildProcess.js
deleted file mode 100644
index d62aef6..0000000
--- a/src/PursLoader/ChildProcess.js
+++ /dev/null
@@ -1,40 +0,0 @@
1'use strict';
2
3// module PursLoader.ChildProcess
4
5var child_process = require('child_process');
6
7var chalk = require('chalk');
8
9function spawnFn(command, args, errback, callback) {
10 return function(){
11 var process = child_process.spawn(command, args);
12
13 var stdout = new Buffer(0);
14
15 var stderr = new Buffer(0);
16
17 process.stdout.on('data', function(data){
18 stdout = Buffer.concat([stdout, new Buffer(data)]);
19 });
20
21 process.stderr.on('data', function(data){
22 stderr = Buffer.concat([stderr, new Buffer(data)]);
23 });
24
25 process.on('close', function(code){
26 var output = stdout.toString('utf-8');
27
28 var error = stderr.toString('utf-8');
29
30 if (error.length > 0) {
31 console.error('\n' + chalk.red('*') + ' ' + error);
32 }
33
34 if (code !== 0) errback(new Error('Process terminated with code ' + code))();
35 else callback(output)();
36 });
37 };
38}
39
40exports.spawnFn = spawnFn;
diff --git a/src/PursLoader/ChildProcess.purs b/src/PursLoader/ChildProcess.purs
deleted file mode 100644
index 3bd960b..0000000
--- a/src/PursLoader/ChildProcess.purs
+++ /dev/null
@@ -1,23 +0,0 @@
1module PursLoader.ChildProcess
2 ( ChildProcess()
3 , spawn
4 ) where
5
6import Prelude (Unit(), ($))
7
8import Control.Monad.Aff (Aff(), makeAff)
9import Control.Monad.Eff (Eff())
10import Control.Monad.Eff.Exception (Error())
11
12import Data.Function
13
14foreign import data ChildProcess :: !
15
16spawn :: forall eff. String -> Array String -> Aff (cp :: ChildProcess | eff) String
17spawn command args = makeAff $ runFn4 spawnFn command args
18
19foreign import spawnFn :: forall eff. Fn4 String
20 (Array String)
21 (Error -> Eff (cp :: ChildProcess | eff) Unit)
22 (String -> Eff (cp :: ChildProcess | eff) Unit)
23 (Eff (cp :: ChildProcess | eff) Unit)
diff --git a/src/PursLoader/FS.js b/src/PursLoader/FS.js
deleted file mode 100644
index 1a7f5b0..0000000
--- a/src/PursLoader/FS.js
+++ /dev/null
@@ -1,36 +0,0 @@
1'use strict';
2
3// module PursLoader.FS
4
5var fs = require('fs');
6
7var async = require('async');
8
9function writeFileUtf8Fn(filepath, contents, errback, callback) {
10 return function(){
11 fs.writeFile(filepath, contents, function(error){
12 if (error) errback(error)();
13 else callback()();
14 });
15 };
16}
17
18function findFileUtf8Fn(nothing, just, regex, filepaths, errback, callback) {
19 return function(){
20 function findFile(filepath, callback) {
21 fs.readFile(filepath, {encoding: 'utf-8'}, function(error, result){
22 if (error) callback(false);
23 else callback(regex.test(result));
24 });
25 }
26
27 async.detect(filepaths, findFile, function(result){
28 if (!result) callback(nothing)();
29 else callback(just(result))();
30 });
31 };
32}
33
34exports.writeFileUtf8Fn = writeFileUtf8Fn;
35
36exports.findFileUtf8Fn = findFileUtf8Fn;
diff --git a/src/PursLoader/FS.purs b/src/PursLoader/FS.purs
deleted file mode 100644
index 969e3d0..0000000
--- a/src/PursLoader/FS.purs
+++ /dev/null
@@ -1,38 +0,0 @@
1module PursLoader.FS
2 ( FS()
3 , writeFileUtf8
4 , findFileUtf8
5 ) where
6
7import Prelude (Unit(), ($))
8
9import Control.Monad.Aff (Aff(), makeAff)
10import Control.Monad.Eff (Eff())
11import Control.Monad.Eff.Exception (Error())
12
13import Data.Maybe (Maybe(..))
14import Data.String.Regex (Regex())
15
16import Data.Function
17
18foreign import data FS :: !
19
20writeFileUtf8 :: forall eff. String -> String -> Aff (fs :: FS | eff) Unit
21writeFileUtf8 filepath contents = makeAff $ runFn4 writeFileUtf8Fn filepath contents
22
23foreign import writeFileUtf8Fn :: forall eff. Fn4 String
24 String
25 (Error -> Eff (fs :: FS | eff) Unit)
26 (Unit -> Eff (fs :: FS | eff) Unit)
27 (Eff (fs :: FS | eff) Unit)
28
29findFileUtf8 :: forall eff. Regex -> Array String -> Aff (fs :: FS | eff) (Maybe String)
30findFileUtf8 regexp filepaths = makeAff $ runFn6 findFileUtf8Fn Nothing Just regexp filepaths
31
32foreign import findFileUtf8Fn :: forall eff. Fn6 (Maybe String)
33 (String -> Maybe String)
34 Regex
35 (Array String)
36 (Error -> Eff (fs :: FS | eff) Unit)
37 (Maybe String -> Eff (fs :: FS | eff) Unit)
38 (Eff (fs :: FS | eff) Unit)
diff --git a/src/PursLoader/Glob.js b/src/PursLoader/Glob.js
deleted file mode 100644
index 960ae9a..0000000
--- a/src/PursLoader/Glob.js
+++ /dev/null
@@ -1,18 +0,0 @@
1'use strict';
2
3// module PursLoader.Glob
4
5var glob = require('glob');
6
7var async = require('async');
8
9function globAllFn(patterns, errback, callback) {
10 return function(){
11 async.map(patterns, glob, function(error, result){
12 if (error) errback(new Error(error))();
13 else callback(result)();
14 });
15 };
16}
17
18exports.globAllFn = globAllFn;
diff --git a/src/PursLoader/Glob.purs b/src/PursLoader/Glob.purs
deleted file mode 100644
index 45eeb56..0000000
--- a/src/PursLoader/Glob.purs
+++ /dev/null
@@ -1,22 +0,0 @@
1module PursLoader.Glob
2 ( Glob()
3 , globAll
4 ) where
5
6import Prelude (Unit(), ($))
7
8import Control.Monad.Aff (Aff(), makeAff)
9import Control.Monad.Eff (Eff())
10import Control.Monad.Eff.Exception (Error())
11
12import Data.Function
13
14foreign import data Glob :: !
15
16globAll :: forall eff. Array String -> Aff (glob :: Glob | eff) (Array (Array String))
17globAll patterns = makeAff $ runFn3 globAllFn patterns
18
19foreign import globAllFn :: forall eff. Fn3 (Array String)
20 (Error -> Eff (glob :: Glob | eff) Unit)
21 ((Array (Array String)) -> Eff (glob :: Glob | eff) Unit)
22 (Eff (glob :: Glob | eff) Unit)
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
diff --git a/src/PursLoader/LoaderRef.purs b/src/PursLoader/LoaderRef.purs
index 33c4f7e..87d6006 100644
--- a/src/PursLoader/LoaderRef.purs
+++ b/src/PursLoader/LoaderRef.purs
@@ -1,6 +1,7 @@
1module PursLoader.LoaderRef 1module PursLoader.LoaderRef
2 ( LoaderRef() 2 ( LoaderRef()
3 , Loader() 3 , Loader()
4 , AsyncCallback()
4 , async 5 , async
5 , cacheable 6 , cacheable
6 , query 7 , query
@@ -17,16 +18,18 @@ import Control.Monad.Eff.Exception (Error())
17import Data.Function (Fn3(), runFn3) 18import Data.Function (Fn3(), runFn3)
18import Data.Maybe (Maybe(), fromMaybe, isJust) 19import Data.Maybe (Maybe(), fromMaybe, isJust)
19 20
21type AsyncCallback eff = Maybe Error -> String -> Eff (loader :: Loader | eff) Unit
22
20data LoaderRef 23data LoaderRef
21 24
22foreign import data Loader :: ! 25foreign import data Loader :: !
23 26
24foreign import asyncFn :: forall eff a. Fn3 (Maybe Error -> Boolean) 27foreign import asyncFn :: forall eff. Fn3 (Maybe Error -> Boolean)
25 (Error -> Maybe Error -> Error) 28 (Error -> Maybe Error -> Error)
26 LoaderRef 29 LoaderRef
27 (Eff (loader :: Loader | eff) (Maybe Error -> a -> Eff (loader :: Loader | eff) Unit)) 30 (Eff (loader :: Loader | eff) (AsyncCallback eff))
28 31
29async :: forall eff a. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> a -> Eff (loader :: Loader | eff) Unit) 32async :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) (Maybe Error -> String -> Eff (loader :: Loader | eff) Unit)
30async ref = runFn3 asyncFn isJust fromMaybe ref 33async ref = runFn3 asyncFn isJust fromMaybe ref
31 34
32foreign import cacheable :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit 35foreign import cacheable :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit
diff --git a/src/PursLoader/LoaderUtil.purs b/src/PursLoader/LoaderUtil.purs
index 3e5a7bc..45495c8 100644
--- a/src/PursLoader/LoaderUtil.purs
+++ b/src/PursLoader/LoaderUtil.purs
@@ -4,6 +4,4 @@ module PursLoader.LoaderUtil
4 4
5import Data.Foreign (Foreign()) 5import Data.Foreign (Foreign())
6 6
7import PursLoader.LoaderRef (LoaderRef())
8
9foreign import parseQuery :: String -> Foreign 7foreign import parseQuery :: String -> Foreign
diff --git a/src/PursLoader/Options.purs b/src/PursLoader/Options.purs
index 1650652..706ddd2 100644
--- a/src/PursLoader/Options.purs
+++ b/src/PursLoader/Options.purs
@@ -1,111 +1,30 @@
1module PursLoader.Options 1module PursLoader.Options
2 ( pscOptions 2 ( Options()
3 , loaderSrcOption 3 , runOptions
4 , loaderFFIOption
5 , Options()
6 , output
7 ) where 4 ) where
8 5
9import Prelude (Unit(), (<>), (<$>), (<<<), (++), (<*>), ($), const, id) 6import Prelude ((<$>), (<<<), id)
10 7
11import Data.Array (concat) 8import Data.Foreign.Class (IsForeign, readProp)
12import Data.Either (either) 9import Data.Foreign.NullOrUndefined (runNullOrUndefined)
10import Data.Maybe (maybe)
13 11
14import Data.Foreign (Foreign(), F()) 12import PursLoader.Path (joinPath)
15import Data.Foreign.Class (IsForeign, read, readProp)
16import Data.Foreign.NullOrUndefined (NullOrUndefined(..), runNullOrUndefined)
17 13
18import Data.Maybe (Maybe(..), maybe, fromMaybe) 14newtype Options = Options { bundleOutput :: String }
19 15
20noPreludeOpt = "no-prelude" 16type Options_ = { bundleOutput :: String }
21 17
22noOptsOpt = "no-opts" 18runOptions :: Options -> Options_
23 19runOptions (Options options) = options
24noMagicDoOpt = "no-magic-do"
25
26noTcoOpt = "no-tco"
27
28verboseErrorsOpt = "verbose-errors"
29
30outputOpt = "output"
31
32commentsOpt = "comments"
33
34noPrefixOpt = "no-prefix"
35
36requirePathOpt = "require-path"
37
38srcOpt = "src"
39
40ffiOpt = "ffi"
41
42newtype Options
43 = Options { noPrelude :: NullOrUndefined Boolean
44 , noOpts :: NullOrUndefined Boolean
45 , noMagicDo :: NullOrUndefined Boolean
46 , noTco :: NullOrUndefined Boolean
47 , verboseErrors :: NullOrUndefined Boolean
48 , comments :: NullOrUndefined Boolean
49 , output :: String
50 , noPrefix :: NullOrUndefined Boolean
51 , requirePath :: String
52 , src :: NullOrUndefined (Array String)
53 , ffi :: NullOrUndefined (Array String)
54 }
55
56output :: Options -> String
57output (Options o) = o.output
58 20
59instance isForeignOptions :: IsForeign Options where 21instance isForeignOptions :: IsForeign Options where
60 read obj = Options <$> ({ noPrelude: _ 22 read obj =
61 , noOpts: _ 23 Options <$> ({ bundleOutput: _ }
62 , noMagicDo: _ 24 <$> (maybe bundleOutputDefault id <<< runNullOrUndefined <$> readProp bundleOutput obj))
63 , noTco: _ 25 where
64 , verboseErrors: _ 26 bundleOutput :: String
65 , comments: _ 27 bundleOutput = "bundleOutput"
66 , output: _ 28
67 , noPrefix: _ 29 bundleOutputDefault :: String
68 , requirePath: "../" 30 bundleOutputDefault = joinPath "output" "bundle.js"
69 , src: _
70 , ffi: _
71 } <$> readProp noPreludeOpt obj
72 <*> readProp noOptsOpt obj
73 <*> readProp noMagicDoOpt obj
74 <*> readProp noTcoOpt obj
75 <*> readProp verboseErrorsOpt obj
76 <*> readProp commentsOpt obj
77 <*> (maybe "output" id <<< runNullOrUndefined <$> readProp outputOpt obj)
78 <*> readProp noPrefixOpt obj
79 <*> readProp srcOpt obj
80 <*> readProp ffiOpt obj)
81
82class LoaderOption a where
83 opt :: String -> NullOrUndefined a -> Array String
84
85instance booleanLoaderOption :: LoaderOption Boolean where
86 opt key val = maybe [] (\a -> if a then ["--" ++ key] else []) (runNullOrUndefined val)
87
88instance stringLoaderOption :: LoaderOption String where
89 opt key val = maybe [] (\a -> ["--" ++ key ++ "=" ++ a]) (runNullOrUndefined val)
90
91instance arrayLoaderOption :: (LoaderOption a) => LoaderOption (Array a) where
92 opt key val = concat (opt key <$> (NullOrUndefined <<< Just)
93 <$> (fromMaybe [] (runNullOrUndefined val)))
94
95pscOptions :: Options -> Array String
96pscOptions (Options a) = opt noPreludeOpt a.noPrelude <>
97 opt noOptsOpt a.noOpts <>
98 opt noMagicDoOpt a.noMagicDo <>
99 opt noTcoOpt a.noTco <>
100 opt verboseErrorsOpt a.verboseErrors <>
101 opt commentsOpt a.comments <>
102 opt outputOpt (NullOrUndefined $ Just a.output) <>
103 opt noPrefixOpt a.noPrefix <>
104 opt requirePathOpt (NullOrUndefined $ Just a.requirePath) <>
105 opt ffiOpt a.ffi
106
107loaderSrcOption :: Foreign -> Maybe (Array String)
108loaderSrcOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.src) (read query)
109
110loaderFFIOption :: Foreign -> Maybe (Array String)
111loaderFFIOption query = either (const Nothing) (\(Options a) -> runNullOrUndefined a.ffi) (read query)
diff --git a/src/PursLoader/Loader.js b/src/PursLoader/Path.js
index 45e9c2f..878f256 100644
--- a/src/PursLoader/Loader.js
+++ b/src/PursLoader/Path.js
@@ -1,27 +1,22 @@
1'use strict' 1'use strict'
2 2
3// module PursLoader.Loader 3// module PursLoader.Path
4 4
5var path = require('path'); 5var path = require('path');
6 6
7var cwd = process.cwd();
8
9function relative(from) { 7function relative(from) {
10 return function(to){ 8 return function(to){
11 return path.relative(from, to); 9 return path.relative(from, to);
12 }; 10 };
13} 11}
12exports.relative = relative;
13
14 14
15function joinPath(a) { 15function joinPath(a) {
16 return function(b) { 16 return function(b) {
17 return path.join(a, b); 17 return path.join(a, b);
18 }; 18 };
19} 19}
20
21exports.cwd = cwd;
22
23exports.relative = relative;
24
25exports.joinPath = joinPath; 20exports.joinPath = joinPath;
26 21
27exports.resolve = path.resolve; 22exports.resolve = path.resolve;
diff --git a/src/PursLoader/Path.purs b/src/PursLoader/Path.purs
new file mode 100644
index 0000000..98cad5a
--- /dev/null
+++ b/src/PursLoader/Path.purs
@@ -0,0 +1,14 @@
1module PursLoader.Path
2 ( relative
3 , resolve
4 , dirname
5 , joinPath
6 ) where
7
8foreign import relative :: String -> String -> String
9
10foreign import resolve :: String -> String
11
12foreign import dirname :: String -> String
13
14foreign import joinPath :: String -> String -> String