-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.es6
138 lines (115 loc) · 3.35 KB
/
index.es6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Get stack traces that point to the original ES6 code.
import "source-map-support/register";
if (typeof _babelPolyfill === "undefined") {
// Include babel polyfill
require("babel/polyfill");
}
// Babel does not expose a proper main entry in its package.json. It seems that
// this causes the es6 import to fail.
const babel = require("babel-core");
import arrify from "arrify";
import chokidar from "chokidar";
import defaults from "lodash/object/defaults";
import fs from "fs-extra";
import path from "path";
import { EventEmitter } from "events";
import { Logger } from "eazy-logger";
const DEFAULT_OPTS = {
logLevel: "debug",
persistent: true,
delete: true,
babel: {}
};
class BabelWatcher extends EventEmitter {
constructor(srcDir, destDir, opts) {
super();
opts = defaults(opts || {}, DEFAULT_OPTS);
this._srcDir = srcDir;
this._destDir = destDir;
this._logger = new Logger({
level: opts.logLevel,
prefix: "[{blue:watch-babel}] "
});
// Have we hit the ready state?
this._ready = false;
this._delete = opts.delete;
this._babelOpts = opts.babel;
const globs = arrify(opts.glob || ".");
const chokidarOpts = {
cwd: srcDir,
persistent: opts.persistent
};
this._watcher = chokidar.watch(globs, chokidarOpts)
.on("all", (e, p, s) => this._handleWatchEvent(e, p, s))
.on("error", e => this._handleError(e))
.on("ready", () => this._handleReady());
}
get ready() {
return this._ready;
}
get srcDir() {
return this._srcDir;
}
get destDir() {
return this._destDir;
}
close() {
this._watcher.close();
this.removeAllListeners();
}
_handleReady() {
this._ready = true;
this._logger.info("{cyan:Watching} {magenta:%s}", this._srcDir);
this.emit("ready");
}
_handleError(e) {
this._logger.error("{red:Error: %s}", e);
this.emit("error", e);
}
_handleWatchEvent(event, filePath) {
if (!filePath.length) {
filePath = ".";
}
const srcPath = path.join(this._srcDir, filePath);
const destPath = path.join(this._destDir, filePath);
switch (event) {
case "add":
case "change":
let result;
try {
result = babel.transformFileSync(srcPath, this._babelOpts);
} catch (e) {
const frameDetails = e.codeFrame ? `\n${e.codeFrame}` : "";
this._logger.error("{cyan:Transpilation {red:failed} for {green:%s}}:\n{red:%s%s",
srcPath, e, frameDetails);
this.emit("failure", filePath, e);
return;
}
// TODO handle external source maps
fs.outputFileSync(destPath, result.code);
this._logger.debug("{cyan:Transpiled} {green:%s} -> {green:%s}", srcPath, destPath);
this.emit("success", filePath);
break;
case "unlink":
if (!this._delete) {
return;
}
fs.removeSync(destPath);
this._logger.debug("{cyan:Deleted} {green:%s}", destPath);
this.emit("delete", filePath);
break;
case "unlinkDir":
if (!this._delete) {
return;
}
fs.removeSync(destPath);
break;
}
}
}
function watchBabel(src, dest, opts) {
return new BabelWatcher(src, dest, opts);
}
// Read version in from package.json
watchBabel.version = require("./package.json").version;
export default watchBabel;