1 | "use strict";
|
2 | var fs = require("fs");
|
3 | var path = require("path");
|
4 | var child_process = require("child_process");
|
5 | var babel = require("babel-core");
|
6 | var resolve = require("resolve");
|
7 | var constants = require("./constants");
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | function promisify(f) {
|
14 | var args = Array.from(arguments).slice(1);
|
15 | return new Promise(function (resolve, reject) {
|
16 | args.push(function (err, data) {
|
17 | if (err) {
|
18 | reject(err);
|
19 | }
|
20 | else {
|
21 | resolve(data);
|
22 | }
|
23 | });
|
24 | f.apply(null, args);
|
25 | });
|
26 | }
|
27 | exports.promisify = promisify;
|
28 |
|
29 | function stderrLog(err) {
|
30 | var msg = typeof err === "string"
|
31 | ? err
|
32 | : err.message + (err.stack ? "\n" + err.stack : "");
|
33 | if (typeof process === "object")
|
34 | process.stderr.write(msg + "\n");
|
35 | else
|
36 | console.log(msg);
|
37 | }
|
38 | exports.stderrLog = stderrLog;
|
39 |
|
40 | function stdoutLog(s) {
|
41 | if (typeof process === "object") {
|
42 | process.stdout.write(s + "\n");
|
43 | }
|
44 | else {
|
45 | console.log(s);
|
46 | }
|
47 | }
|
48 | exports.stdoutLog = stdoutLog;
|
49 |
|
50 | function finish(code, continuation) {
|
51 | var err = code === 0 ? null : "FABLE EXIT CODE: " + code;
|
52 | if (typeof continuation === "object") {
|
53 | if (err && typeof continuation.reject === "function") {
|
54 | continuation.reject(err);
|
55 | return;
|
56 | }
|
57 | else if (typeof continuation.resolve === "function") {
|
58 | continuation.resolve(null);
|
59 | return;
|
60 | }
|
61 | }
|
62 | if (typeof process === "object") {
|
63 | process.exit(code);
|
64 | }
|
65 | else if (err) {
|
66 | throw err;
|
67 | }
|
68 | }
|
69 | exports.finish = finish;
|
70 | function splitByWhitespace(str) {
|
71 | function stripQuotes(str, start, end) {
|
72 | return str[start] === '"' && str[end - 1] === '"'
|
73 | ? str.substring(start + 1, end - 1)
|
74 | : str.substring(start, end);
|
75 | }
|
76 | var reg = /\s+(?=([^"]*"[^"]*")*[^"]*$)/g;
|
77 | reg.lastIndex = 0;
|
78 | var tmp, tmp2, results = [], lastIndex = 0;
|
79 | while ((tmp = reg.exec(str)) !== null) {
|
80 | results.push(stripQuotes(str, lastIndex, tmp.index));
|
81 | lastIndex = tmp.index + tmp[0].length;
|
82 | }
|
83 | results.push(stripQuotes(str, lastIndex, str.length));
|
84 | return results;
|
85 | }
|
86 | exports.splitByWhitespace = splitByWhitespace;
|
87 | function runCommandPrivate(workingDir, command, continuation) {
|
88 | var cmd, args;
|
89 | process.stdout.write(workingDir + "> " + command + "\n");
|
90 |
|
91 |
|
92 |
|
93 | if (process.platform === "win32" && continuation) {
|
94 | cmd = "cmd";
|
95 | args = splitByWhitespace(command);
|
96 | args.splice(0, 0, "/C");
|
97 | }
|
98 | else {
|
99 | args = splitByWhitespace(command);
|
100 | cmd = args[0];
|
101 | args = args.slice(1);
|
102 | }
|
103 | var proc = child_process.spawn(cmd, args, { cwd: workingDir });
|
104 | proc.on('exit', function (code) {
|
105 | if (continuation) {
|
106 | code === 0 ? continuation.resolve(code) : continuation.reject(code);
|
107 | }
|
108 | });
|
109 | proc.stderr.on('data', function (data) {
|
110 | stderrLog(data.toString());
|
111 | });
|
112 | proc.stdout.on("data", function (data) {
|
113 | stdoutLog(data.toString());
|
114 | });
|
115 | return proc;
|
116 | }
|
117 |
|
118 | function runCommand(workingDir, command) {
|
119 | return new Promise(function (resolve, reject) {
|
120 | runCommandPrivate(workingDir, command, { resolve: resolve, reject: reject });
|
121 | });
|
122 | }
|
123 | exports.runCommand = runCommand;
|
124 |
|
125 | function runCommandInParallel(workingDir, command) {
|
126 | return runCommandPrivate(workingDir, command);
|
127 | }
|
128 | exports.runCommandInParallel = runCommandInParallel;
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | function resolvePlugins(plugins, basedir, prefix) {
|
136 | if (plugins == null) {
|
137 | return [];
|
138 | }
|
139 | else if (typeof plugins === "object") {
|
140 | if (!Array.isArray(plugins)) {
|
141 | plugins = Object.getOwnPropertyNames(plugins).map(function (k) { return [k, plugins[k]]; });
|
142 | }
|
143 | }
|
144 | else {
|
145 | plugins = [plugins];
|
146 | }
|
147 | return plugins.map(function (plugin) {
|
148 | var config = {};
|
149 | if (Array.isArray(plugin)) {
|
150 | config = plugin[1];
|
151 | plugin = plugin[0];
|
152 | }
|
153 | plugin = prefix && !plugin.startsWith(prefix) ? prefix + plugin : plugin;
|
154 | return [resolve.sync(plugin, { basedir: basedir }), config];
|
155 | });
|
156 | }
|
157 | exports.resolvePlugins = resolvePlugins;
|
158 |
|
159 |
|
160 |
|
161 | function isFSharpProject(filePath) {
|
162 | return typeof filePath === "string"
|
163 | && constants.FSHARP_PROJECT_EXTENSIONS.indexOf(path.extname(filePath).toLowerCase()) >= 0;
|
164 | }
|
165 | exports.isFSharpProject = isFSharpProject;
|
166 |
|
167 |
|
168 |
|
169 | function isFSharpFile(filePath) {
|
170 | return typeof filePath === "string"
|
171 | && constants.FSHARP_FILE_EXTENSIONS.indexOf(path.extname(filePath).toLowerCase()) >= 0;
|
172 | }
|
173 | exports.isFSharpFile = isFSharpFile;
|
174 |
|
175 |
|
176 |
|
177 |
|
178 | function isFullPath(filePath) {
|
179 | return path.resolve(filePath) === filePath;
|
180 | }
|
181 | exports.isFullPath = isFullPath;
|
182 |
|
183 |
|
184 |
|
185 | function pathJoin(path1, path2) {
|
186 | if (!path2) {
|
187 | return path1;
|
188 | }
|
189 | ;
|
190 | return isFullPath(path2) ? path2 : path.join(path1, path2);
|
191 | }
|
192 | exports.pathJoin = pathJoin;
|
193 |
|
194 |
|
195 |
|
196 |
|
197 | function getCommonBaseDir(filePaths) {
|
198 | function getCommonPrefix(xs) {
|
199 | function f(prefix, xs) {
|
200 | if (xs.length === 0) {
|
201 | return prefix;
|
202 | }
|
203 | else {
|
204 | var x = xs[0], i = 0;
|
205 | while (i < prefix.length && i < x.length && x[i] === prefix[i]) {
|
206 | i = i + 1;
|
207 | }
|
208 | return f(prefix.slice(0, i), xs.slice(1));
|
209 | }
|
210 | }
|
211 | return xs.length === 0 ? [] : f(xs[0], xs.slice(1));
|
212 | }
|
213 | var normalized = filePaths.map(function (filePath) { return path.dirname(filePath).replace(/\\/g, '/').split('/'); });
|
214 | return getCommonPrefix(normalized).join('/');
|
215 | }
|
216 | exports.getCommonBaseDir = getCommonBaseDir;
|
217 |
|
218 |
|
219 |
|
220 | function babelify(babelAst, opts) {
|
221 | var outDir = pathJoin(opts.workingDir, opts.outDir);
|
222 | var babelOpts = {
|
223 | babelrc: opts.babelrc || false,
|
224 | filename: babelAst.fileName,
|
225 |
|
226 | presets: opts.babel.presets,
|
227 | plugins: opts.babel.plugins,
|
228 | };
|
229 | var fsCode = null;
|
230 |
|
231 | if (opts.sourceMaps && babelAst.originalFileName) {
|
232 | try {
|
233 | fsCode = fs.readFileSync(babelAst.originalFileName).toString();
|
234 | babelOpts.sourceMaps = opts.sourceMaps,
|
235 | babelOpts.sourceMapTarget = path.basename(babelAst.fileName),
|
236 | babelOpts.sourceFileName = path.relative(path.dirname(babelAst.fileName), babelAst.originalFileName.replace(/\\/g, '/'));
|
237 | }
|
238 | catch (err) {
|
239 | }
|
240 | }
|
241 | var parsed = babel.transformFromAst(babelAst, fsCode, babelOpts);
|
242 | var res = [{
|
243 | isEntry: babelAst.isEntry,
|
244 | fileName: babelAst.fileName,
|
245 | code: parsed.code,
|
246 | map: parsed.map
|
247 | }];
|
248 |
|
249 | if (Array.isArray(babelAst.jsIncludes))
|
250 | babelAst.jsIncludes.forEach(function (js) {
|
251 | parsed = babel.transformFileSync(js.sourcePath, babelOpts);
|
252 | res.push({
|
253 | isEntry: false,
|
254 | fileName: pathJoin(outDir, "js_includes/" + js.name) + ".js",
|
255 | code: parsed.code,
|
256 | map: parsed.map
|
257 | });
|
258 | });
|
259 | var timestamp = " at " + (new Date()).toLocaleTimeString();
|
260 | for (var i = 0; i < res.length; i++) {
|
261 | stdoutLog("Compiled " + path.relative(outDir, res[i].fileName) + timestamp);
|
262 | }
|
263 | return res;
|
264 | }
|
265 | exports.babelify = babelify;
|
266 |
|
267 | function ensureDirExists(dir, cont) {
|
268 | if (fs.existsSync(dir)) {
|
269 | if (typeof cont === "function") {
|
270 | cont();
|
271 | }
|
272 | }
|
273 | else {
|
274 | ensureDirExists(path.dirname(dir), function () {
|
275 | if (!fs.existsSync(dir)) {
|
276 | fs.mkdirSync(dir);
|
277 | }
|
278 | if (typeof cont === "function") {
|
279 | cont();
|
280 | }
|
281 | });
|
282 | }
|
283 | }
|
284 | exports.ensureDirExists = ensureDirExists;
|
285 | function writeFile(fileName, code, map) {
|
286 | ensureDirExists(path.dirname(fileName));
|
287 | fs.writeFileSync(fileName, code);
|
288 | if (map) {
|
289 | fs.appendFileSync(fileName, "\n//# sourceMappingURL=" + path.basename(fileName) + ".map");
|
290 | fs.writeFileSync(fileName + ".map", JSON.stringify(map));
|
291 | }
|
292 | }
|
293 | exports.writeFile = writeFile;
|
294 |
|
295 | function babelifyToFile(babelAst, opts) {
|
296 |
|
297 | babelify(babelAst, opts).forEach(function (parsed) {
|
298 | return writeFile(parsed.fileName, parsed.code, opts.sourceMaps === true ? parsed.map : null);
|
299 | });
|
300 | }
|
301 | exports.babelifyToFile = babelifyToFile;
|