]> git.immae.eu Git - github/fretlink/purs-loader.git/blame - index.js
Adding purescript imports as dependencies
[github/fretlink/purs-loader.git] / index.js
CommitLineData
9d38968b 1'use strict';
2
3var os = require('os');
4
5var cp = require('child_process');
6
7var path = require('path')
8
9var fs = require('fs');
10
11var glob = require('glob');
12
13var lodash = require('lodash');
14
15var chalk = require('chalk');
16
17var lu = require('loader-utils');
18
19var cwd = process.cwd();
20
21var MODULE_RE = /(?:^|\n)module\s+([\w\.]+)/i;
22
23var IMPORT_RE = /^\s*import\s+(?:qualified\s+)?([\w\.]+)/i;
24
25var BOWER_PATTERN = path.join('bower_components', 'purescript-*', 'src');
26
27var PSC_MAKE = 'psc-make';
28
29var OUTPUT = 'output';
30
31var OPTIONS = {
32 'no-prelude': '--no-prelude',
33 'no-opts': '--no-opts',
34 'no-magic-do': '--no-magic-do',
35 'no-tco': '--no-tco',
36 'verbose-errors': '--verbose-errors',
37 'output': '--output'
38};
a42f24b8 39
a6986505 40function pattern(root) {
41 var as = [ BOWER_PATTERN, root ];
42 return path.join('{' + as.join(',') + '}', '**', '*.purs');
43}
44
9d38968b 45function mkOptions(query) {
46 return lodash.foldl(lodash.keys(query), function(acc, k){
47 var h = function(v){return acc.concat(query[k] && OPTIONS[k] ? [v] : []);}
48 if (k === OUTPUT) return h(OPTIONS[k] + '=' + query[k]);
49 else return h(OPTIONS[k]);
50 }, []);
51}
52
53function mkGraph(files) {
54 var graph = {};
55
56 files.forEach(function(file){
57 var source = fs.readFileSync(file, {encoding: 'utf-8'});
58
59 var result = MODULE_RE.exec(source);
60
61 var module = result ? result[1] : null;
62
63 var imports =
64 lodash.foldl(source.split(os.EOL), function(b, a){
65 var result = IMPORT_RE.exec(a);
66 if (result) b.push(result[1]);
67 return b;
a42f24b8 68 }, [])
9d38968b 69 ;
70
71 if (module) {
72 graph[module] = {
73 file: file,
74 imports: imports || []
75 };
76 }
77 });
78
79 return graph;
80}
81
82function findDeps(graph, module) {
83 function go(acc, module){
84 var node = graph[module];
85
86 var imports = node && node.imports;
87
88 if (lodash.isEmpty(imports)) return acc;
89 else {
90 var deps =
91 lodash.map(imports, function(i){
92 return go(acc.concat(imports), i);
93 })
94 ;
95 return lodash.flatten(deps);
96 }
97 }
98
99 return lodash.unique(go([], module));
100}
101
102function loader(source) {
103 this.cacheable && this.cacheable();
104
105 this.clearDependencies();
106
107 this.addDependency(this.resourcePath);
108
109 var callback = this.async();
110
111 var request = lu.getRemainingRequest(this)
112
113 var root = path.dirname(path.relative(cwd, request));
114
115 var query = lu.parseQuery(this.query);
116
117 var opts = mkOptions(query);
118
119 var that = this;
120
a6986505 121 glob(pattern(root), function(e, files){
a42f24b8 122 if (e !== null) callback(e);
123 else {
124 var cmd = cp.spawn(PSC_MAKE, opts.concat(files));
9d38968b 125
126 var graph = mkGraph(files);
127
a42f24b8 128 cmd.on('close', function(e){
129 if (e) callback(e);
130 else {
a92aa714 131 var result = MODULE_RE.exec(source);
9d38968b 132
133 var module = result ? result[1] : '';
134
135 var dependencies = findDeps(graph, module);
136
137 var indexPath = path.join(query[OUTPUT] || OUTPUT, module, 'index.js');
138
139 fs.readFile(indexPath, 'utf-8', function(e, output){
a42f24b8 140 if (e) callback(e);
9d38968b 141 else {
142 dependencies.forEach(function(dep){
143 var module = graph[dep];
144 if (module) that.addDependency(path.resolve(module.file));
145 });
146
147 callback(null, output);
148 }
a42f24b8 149 });
150 }
151 });
9d38968b 152
a42f24b8 153 cmd.stdout.on('data', function(stdout){
154 console.log('Stdout from \'' + chalk.cyan(PSC_MAKE) + '\'\n' + chalk.magenta(stdout));
155 });
9d38968b 156
a42f24b8 157 cmd.stderr.on('data', function(stderr){
158 console.log('Stderr from \'' + chalk.cyan(PSC_MAKE) + '\'\n' + chalk.magenta(stderr));
159 });
160 }
161 });
9d38968b 162}
163
164module.exports = loader;