UNPKG

4.26 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2015, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 */
9
10import sane from 'sane';
11import { resolve as resolvePath } from 'path';
12import { spawn } from 'child_process';
13
14process.env.PATH += ':./node_modules/.bin';
15
16const is_windows = process.platform === 'win32'
17
18// still creates the NUL file in the current working directory
19const dev_null = is_windows ? 'NUL' : '/dev/null'
20
21var cmd = resolvePath(__dirname);
22var srcDir = resolvePath(cmd, './source');
23
24function exec(command, options) {
25 return new Promise(function (resolve, reject) {
26 var child = spawn(command, options, {
27 cmd: cmd,
28 env: process.env,
29 stdio: 'inherit'
30 });
31 child.on('exit', function (code) {
32 if (code === 0) {
33 resolve(true);
34 } else {
35 reject(new Error('Error code: ' + code));
36 }
37 });
38 });
39}
40
41var watcher = sane(srcDir, { glob: ['**/*.*'] })
42 .on('ready', startWatch)
43 .on('add', changeFile)
44 .on('delete', deleteFile)
45 .on('change', changeFile);
46
47process.on('SIGINT', function () {
48 watcher.close();
49 console.log(CLEARLINE + yellow(invert('stopped watching')));
50 process.exit();
51});
52
53var isChecking;
54var needsCheck;
55var toCheck = {};
56var timeout;
57
58function startWatch() {
59 process.stdout.write(CLEARSCREEN + green(invert('watching...')));
60}
61
62function changeFile(filepath, root, stat) {
63 if (!stat.isDirectory()) {
64 toCheck[filepath] = true;
65 debouncedCheck();
66 }
67}
68
69function deleteFile(filepath) {
70 delete toCheck[filepath];
71 debouncedCheck();
72}
73
74function debouncedCheck() {
75 needsCheck = true;
76 clearTimeout(timeout);
77 timeout = setTimeout(guardedCheck, 250);
78}
79
80function guardedCheck() {
81 if (isChecking || !needsCheck) {
82 return;
83 }
84 isChecking = true;
85 var filepaths = Object.keys(toCheck);
86 toCheck = {};
87 needsCheck = false;
88 checkFiles(filepaths).then(() => {
89 isChecking = false;
90 process.nextTick(guardedCheck);
91 });
92}
93
94function checkFiles(filepaths) {
95 console.log('\u001b[2J');
96
97 // return parseFiles(filepaths)
98 // .then(() => runTests(filepaths))
99 return runTests(filepaths)
100 .catch(() => false)
101 .then(success => {
102 process.stdout.write(
103 '\n' + (success ? '' : '\x07') + green(invert('watching...'))
104 );
105 });
106}
107
108// Checking steps
109
110function executable(command) {
111 if (is_windows) {
112 return command + '.cmd'
113 }
114 return command
115}
116
117function parseFiles(filepaths) {
118 console.log('Checking Syntax');
119
120 return Promise.all(filepaths.map(filepath => {
121 if (isJS(filepath) && !isTest(filepath)) {
122 return exec(executable('babel'), [
123 '--optional', 'runtime',
124 '--out-file', dev_null,
125 srcPath(filepath)
126 ]);
127 }
128 }));
129}
130
131function runTests(filepaths) {
132 console.log('\nRunning Tests');
133
134 return exec(executable('mocha'), [
135 '--reporter', 'spec',
136 '--bail',
137 '--require', 'scripts/mocha-bootload'
138 ].concat(
139 allTests(filepaths) ? filepaths.map(srcPath) : ['test/**/*.js'] // 'src/**/__tests__/**/*.js'
140 )).catch(() => false);
141}
142
143// Filepath
144
145function srcPath(filepath) {
146 return resolvePath(srcDir, filepath);
147}
148
149// Predicates
150
151function isJS(filepath) {
152 return filepath.indexOf('.js') === filepath.length - 3;
153}
154
155function allTests(filepaths) {
156 return filepaths.length > 0 && filepaths.every(isTest);
157}
158
159function isTest(filepath) {
160 return isJS(filepath) && ~filepath.indexOf('__tests__/');
161}
162
163// Print helpers
164
165var CLEARSCREEN = '\u001b[2J';
166var CLEARLINE = '\r\x1B[K';
167var CHECK = green('\u2713');
168var X = red('\u2718');
169
170function invert(str) {
171 return `\u001b[7m ${str} \u001b[27m`;
172}
173
174function red(str) {
175 return `\x1B[K\u001b[1m\u001b[31m${str}\u001b[39m\u001b[22m`;
176}
177
178function green(str) {
179 return `\x1B[K\u001b[1m\u001b[32m${str}\u001b[39m\u001b[22m`;
180}
181
182function yellow(str) {
183 return `\x1B[K\u001b[1m\u001b[33m${str}\u001b[39m\u001b[22m`;
184}
\No newline at end of file