diff --git a/cmds/build.js b/cmds/build.js index 5ce215ace..05d31839d 100644 --- a/cmds/build.js +++ b/cmds/build.js @@ -1,7 +1,12 @@ 'use strict' +const path = require('path') + +const chokidar = require('chokidar') + const build = require('../src/build') const onError = require('../src/error-handler') +const utils = require('../src/utils') module.exports = { command: 'build', @@ -16,6 +21,11 @@ module.exports = { alias: 'l', describe: 'Transpile src to lib', default: true + }, + watch: { + alias: 'w', + describe: 'Keep watching source files for changes', + default: false } }, handler (argv) { diff --git a/package.json b/package.json index 78e214aa7..286bcaaf2 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "babel-preset-flow-node": "^2.0.1", "browserify-zlib": "^0.2.0", "chalk": "^2.3.0", + "chokidar": "^2.0.3", "clean-documentation-theme": "^0.5.2", "codecov": "^3.0.0", "conventional-changelog": "^1.1.7", diff --git a/src/build/lib.js b/src/build/lib.js index 47544a4dc..9ebd4d1dc 100644 --- a/src/build/lib.js +++ b/src/build/lib.js @@ -4,9 +4,10 @@ const path = require('path') const babelCore = require('babel-core') +const chokidar = require('chokidar') const fs = require('fs-extra') -const glob = require('glob') -const pify = require('pify') + +const utils = require('../utils') const babelConfig = { env: { @@ -28,7 +29,17 @@ const babelConfig = { } } -const transform = (src, dest) => { +/** + * Babel transpiles a file from `src` to `lib` + * + * @param {string} filename The filename relative to the `src` directory + * + * @returns {Promise} + */ +const transform = (filename) => { + const src = path.join('src', filename) + const dest = path.join('lib', filename) + // To have the right filename in the source map babelConfig.sourceFileName = path.join('..', src) @@ -45,16 +56,38 @@ const transform = (src, dest) => { }) } -const babel = () => { - const src = 'src' - const dest = 'lib' +const babel = (ctx) => { + const srcDir = path.join(utils.getBasePath(), 'src') + + return new Promise((resolve, reject) => { + // The watcher code is based on the babel-cli code (MIT licensed): + // https://github.com/babel/babel/blob/6597a472b30419493f123bff1e9194e4c09e488e/packages/babel-cli/src/babel/dir.js#L164-L188` + const watcher = chokidar.watch(srcDir, { + persistent: ctx.watch, + ignoreInitial: false, + awaitWriteFinish: { + stabilityThreshold: 50, + pollInterval: 10 + } + }) + + ;['add', 'change'].forEach((type) => { + watcher.on(type, (filename) => { + const relative = path.relative(srcDir, filename) + console.log('Transpile file: ' + relative) + transform(relative) + }) + }) - return pify(glob)('./**/*.js', { - cwd: path.join(process.cwd(), src) - }).then((filenames) => { - return Promise.all(filenames.map((filename) => { - return transform(path.join(src, filename), path.join(dest, filename)) - })) + watcher + .on('ready', () => { + // Finish the task after the initial scan. If files are watched, the + // task will keep running though. + resolve() + }) + .on('error', (err) => { + reject(err) + }) }) }