diff --git a/CHANGES.md b/CHANGES.md index 56dd7065..031bb332 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +**Fixed:** + +* Fix `clean` commands in paths with spaces [[#181](https://github.com/insin/nwb/issues/181)] + **Changed:** * The default build for a React component demo app now supports use of a `demo/public/` directory for static content. diff --git a/package.json b/package.json index f91b1eea..ec87eff5 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "eslint-config-jonnybuchanan": "4.7.0", "eventsource": "0.2.1", "nyc": "10.0.0", + "run-series": "1.1.4", "shelljs": "0.7.5", "tree-kill": "1.1.0" }, diff --git a/src/commands/build-demo.js b/src/commands/build-demo.js index c5f09a7b..0088eecd 100644 --- a/src/commands/build-demo.js +++ b/src/commands/build-demo.js @@ -1,10 +1,9 @@ import path from 'path' import glob from 'glob' -import ora from 'ora' +import runSeries from 'run-series' import webpackBuild from '../webpackBuild' -import {logBuildResults} from '../webpackUtils' import cleanDemo from './clean-demo' /** @@ -43,15 +42,8 @@ export default function buildDemo(args, cb) { config.plugins.copy = [{from: path.resolve('demo/public/'), to: dist}] } - cleanDemo(args) - - let spinner = ora('Building demo').start() - webpackBuild(args, config, (err, stats) => { - if (err) { - spinner.fail() - return cb(err) - } - logBuildResults(stats, spinner) - cb() - }) + runSeries([ + (cb) => cleanDemo(args, cb), + (cb) => webpackBuild('demo', args, config, cb), + ], cb) } diff --git a/src/commands/build-inferno-app.js b/src/commands/build-inferno-app.js index 8c8af9ab..55efb6ed 100644 --- a/src/commands/build-inferno-app.js +++ b/src/commands/build-inferno-app.js @@ -1,11 +1,10 @@ import path from 'path' import glob from 'glob' -import ora from 'ora' +import runSeries from 'run-series' import {getDefaultHTMLConfig} from '../appConfig' import webpackBuild from '../webpackBuild' -import {logBuildResults} from '../webpackUtils' import cleanApp from './clean-app' // Using a config function as webpackBuild() sets NODE_ENV to production if it @@ -52,15 +51,8 @@ function buildConfig(args) { export default function buildInfernoApp(args, cb) { let dist = args._[2] || 'dist' - cleanApp({_: ['clean-app', dist]}) - - let spinner = ora(`Building Inferno app`).start() - webpackBuild(args, buildConfig, (err, stats) => { - if (err) { - spinner.fail() - return cb(err) - } - logBuildResults(stats, spinner) - cb() - }) + runSeries([ + (cb) => cleanApp({_: ['clean-app', dist]}, cb), + (cb) => webpackBuild('Inferno app', args, buildConfig, cb), + ], cb) } diff --git a/src/commands/build-preact-app.js b/src/commands/build-preact-app.js index 4f113b3d..2d765fd1 100644 --- a/src/commands/build-preact-app.js +++ b/src/commands/build-preact-app.js @@ -1,11 +1,10 @@ import path from 'path' import glob from 'glob' -import ora from 'ora' +import runSeries from 'run-series' import {getDefaultHTMLConfig} from '../appConfig' import webpackBuild from '../webpackBuild' -import {logBuildResults} from '../webpackUtils' import cleanApp from './clean-app' // Using a config function as webpackBuild() sets NODE_ENV to production if it @@ -52,15 +51,8 @@ function buildConfig(args) { export default function buildPreactApp(args, cb) { let dist = args._[2] || 'dist' - cleanApp({_: ['clean-app', dist]}) - - let spinner = ora(`Building Preact app`).start() - webpackBuild(args, buildConfig, (err, stats) => { - if (err) { - spinner.fail() - return cb(err) - } - logBuildResults(stats, spinner) - cb() - }) + runSeries([ + (cb) => cleanApp({_: ['clean-app', dist]}, cb), + (cb) => webpackBuild('Preact app', args, buildConfig, cb), + ], cb) } diff --git a/src/commands/build-react-app.js b/src/commands/build-react-app.js index 56af61e7..30606a7a 100644 --- a/src/commands/build-react-app.js +++ b/src/commands/build-react-app.js @@ -1,11 +1,10 @@ import path from 'path' import glob from 'glob' -import ora from 'ora' +import runSeries from 'run-series' import {getDefaultHTMLConfig} from '../appConfig' import webpackBuild from '../webpackBuild' -import {logBuildResults} from '../webpackUtils' import cleanApp from './clean-app' // Using a config function as webpackBuild() sets NODE_ENV to production if it @@ -73,19 +72,12 @@ function buildConfig(args) { export default function buildReactApp(args, cb) { let dist = args._[2] || 'dist' - cleanApp({_: ['clean-app', dist]}) - let library = 'React' if (args.inferno) library = 'Inferno (React compat)' else if (args.preact) library = 'Preact (React compat)' - let spinner = ora(`Building ${library} app`).start() - webpackBuild(args, buildConfig, (err, stats) => { - if (err) { - spinner.fail() - return cb(err) - } - logBuildResults(stats, spinner) - cb() - }) + runSeries([ + (cb) => cleanApp({_: ['clean-app', dist]}, cb), + (cb) => webpackBuild(`${library} app`, args, buildConfig, cb), + ], cb) } diff --git a/src/commands/build-react-component.js b/src/commands/build-react-component.js index 43022666..3d5e4a54 100644 --- a/src/commands/build-react-component.js +++ b/src/commands/build-react-component.js @@ -1,4 +1,5 @@ import glob from 'glob' +import runSeries from 'run-series' import moduleBuild from '../moduleBuild' import buildDemo from './build-demo' @@ -32,14 +33,12 @@ export default function buildModule(args, cb) { } } - moduleBuild(args, config, (err) => { - if (err) return cb(err) - // Disable demo build with --no-demo or --no-demo-build - if (args.demo === false || - args['demo-build'] === false || - glob.sync('demo/').length === 0) { - return cb(null) - } - buildDemo(args, cb) - }) + let tasks = [(cb) => moduleBuild(args, config, cb)] + // Disable demo build with --no-demo or --no-demo-build + if (args.demo !== false && + args['demo-build'] !== false && + glob.sync('demo/').length !== 0) { + tasks.push((cb) => buildDemo(args, cb)) + } + runSeries(tasks, cb) } diff --git a/src/commands/build-react.js b/src/commands/build-react.js index 36a73250..173639a5 100644 --- a/src/commands/build-react.js +++ b/src/commands/build-react.js @@ -1,10 +1,9 @@ import path from 'path' -import ora from 'ora' +import runSeries from 'run-series' import {UserError} from '../errors' import webpackBuild from '../webpackBuild' -import {logBuildResults} from '../webpackUtils' import cleanApp from './clean-app' // Using a config function as webpackBuild() sets NODE_ENV to production if it @@ -77,19 +76,12 @@ export default function buildReact(args, cb) { let dist = args._[2] || 'dist' - cleanApp({_: ['clean-app', dist]}) - let library = 'React' if (args.inferno) library = 'Inferno (React compat)' else if (args.preact) library = 'Preact (React compat)' - let spinner = ora(`Building ${library} app`).start() - webpackBuild(args, buildConfig, (err, stats) => { - if (err) { - spinner.fail() - return cb(err) - } - logBuildResults(stats, spinner) - cb() - }) + runSeries([ + (cb) => cleanApp({_: ['clean-app', dist]}, cb), + (cb) => webpackBuild(`${library} app`, args, buildConfig, cb), + ], cb) } diff --git a/src/commands/build-web-app.js b/src/commands/build-web-app.js index 5ff9ba7a..cccb822c 100644 --- a/src/commands/build-web-app.js +++ b/src/commands/build-web-app.js @@ -1,11 +1,10 @@ import path from 'path' import glob from 'glob' -import ora from 'ora' +import runSeries from 'run-series' import {getDefaultHTMLConfig} from '../appConfig' import webpackBuild from '../webpackBuild' -import {logBuildResults} from '../webpackUtils' import cleanApp from './clean-app' // Using a config function as webpackBuild() sets NODE_ENV to production if it @@ -51,15 +50,8 @@ function buildConfig(args) { export default function buildWebApp(args, cb) { let dist = args._[2] || 'dist' - cleanApp({_: ['clean-app', dist]}) - - let spinner = ora('Building app').start() - webpackBuild(args, buildConfig, (err, stats) => { - if (err) { - spinner.fail() - return cb(err) - } - logBuildResults(stats, spinner) - cb() - }) + runSeries([ + (cb) => cleanApp({_: ['clean-app', dist]}, cb), + (cb) => webpackBuild(`app`, args, buildConfig, cb), + ], cb) } diff --git a/src/commands/clean-app.js b/src/commands/clean-app.js index 93045eb6..65ed32f8 100644 --- a/src/commands/clean-app.js +++ b/src/commands/clean-app.js @@ -1,17 +1,6 @@ -import exec from '../exec' +import {clean} from '../utils' -import ora from 'ora' - -export default function cleanApp(args) { +export default function cleanApp(args, cb) { let dist = args._[1] || 'dist' - - let spinner = ora('Cleaning app').start() - try { - exec('rimraf', ['coverage', dist]) - spinner.succeed() - } - catch (err) { - spinner.fail() - throw err - } + clean('app', ['coverage', dist], cb) } diff --git a/src/commands/clean-demo.js b/src/commands/clean-demo.js index 8dc32fcf..95c41217 100644 --- a/src/commands/clean-demo.js +++ b/src/commands/clean-demo.js @@ -1,15 +1,5 @@ -import exec from '../exec' +import {clean} from '../utils' -import ora from 'ora' - -export default function cleanModule(args) { - let spinner = ora('Cleaning demo').start() - try { - exec('rimraf', ['demo/dist']) - spinner.succeed() - } - catch (err) { - spinner.fail() - throw err - } +export default function cleanDemo(args, cb) { + clean('demo', ['demo/dist'], cb) } diff --git a/src/commands/clean-module.js b/src/commands/clean-module.js index 1a7ced5b..deb207b9 100644 --- a/src/commands/clean-module.js +++ b/src/commands/clean-module.js @@ -1,15 +1,5 @@ -import exec from '../exec' +import {clean} from '../utils' -import ora from 'ora' - -export default function cleanModule(args) { - let spinner = ora('Cleaning module').start() - try { - exec('rimraf', ['coverage', 'es', 'lib', 'umd']) - spinner.succeed() - } - catch (err) { - spinner.fail() - throw err - } +export default function cleanModule(args, cb) { + clean('module', ['coverage', 'es', 'lib', 'umd'], cb) } diff --git a/src/commands/clean.js b/src/commands/clean.js index 89309872..2914782e 100644 --- a/src/commands/clean.js +++ b/src/commands/clean.js @@ -13,7 +13,7 @@ const CLEAN_COMMANDS = { /** * Generic clean command, invokes the appropriate project type-specific command. */ -export default function clean(args) { +export default function clean(args, cb) { let userConfig = getUserConfig(args, {required: true}) - CLEAN_COMMANDS[userConfig.type](args) + CLEAN_COMMANDS[userConfig.type](args, cb) } diff --git a/src/moduleBuild.js b/src/moduleBuild.js index feaa67c1..053f00ae 100644 --- a/src/moduleBuild.js +++ b/src/moduleBuild.js @@ -3,7 +3,7 @@ import path from 'path' import glob from 'glob' import ora from 'ora' -import temp from 'temp' +import runSeries from 'run-series' import merge from 'webpack-merge' import cleanModule from './commands/clean-module' @@ -27,9 +27,9 @@ const DEFAULT_BABEL_IGNORE_CONFIG = [ ] /** - * Runs Babel with generated config written to a temporary .babelrc. + * Run Babel with generated config written to a temporary .babelrc. */ -function runBabel({copyFiles, outDir, src}, buildBabelConfig, userBabelConfig) { +function runBabel(name, {copyFiles, outDir, src}, buildBabelConfig, userBabelConfig, cb) { let babelConfig = createBabelConfig(buildBabelConfig, userBabelConfig) babelConfig.ignore = DEFAULT_BABEL_IGNORE_CONFIG @@ -40,71 +40,28 @@ function runBabel({copyFiles, outDir, src}, buildBabelConfig, userBabelConfig) { debug('babel config: %s', deepToString(babelConfig)) - fs.writeFileSync('.babelrc', JSON.stringify(babelConfig, null, 2)) + let spinner = ora(`Creating ${name} build`).start() try { + fs.writeFileSync('.babelrc', JSON.stringify(babelConfig, null, 2)) exec('babel', babelArgs) - } - finally { - fs.unlinkSync('.babelrc') - } -} - -export default function moduleBuild(args, buildConfig = {}, cb) { - // XXX Babel doesn't support passing the path to a babelrc file any more - if (glob.sync('.babelrc').length > 0) { - throw new UserError( - 'Unable to build the module as there is a .babelrc in your project', - 'nwb needs to write a temporary .babelrc to configure the build', - ) - } - - cleanModule(args) - - let src = path.resolve('src') - let userConfig = getUserConfig(args) - let copyFiles = !!args['copy-files'] - - let spinner = ora('Creating ES5 build').start() - runBabel( - {copyFiles, outDir: path.resolve('lib'), src}, - merge(buildConfig.babel, buildConfig.babelDev || {}, { - // Don't force ES5 users of the ES5 build to eat a .require - plugins: [require.resolve('babel-plugin-add-module-exports')], - // Don't set the path to nwb's babel-runtime, as it will need to be a - // peerDependency of your module if you use transform-runtime's helpers - // option. - setRuntimePath: false, - }), - userConfig.babel, - ) - spinner.succeed() - - // The ES6 modules build is enabled by default, and must be explicitly - // disabled if you don't want it. - if (userConfig.npm.esModules !== false) { - spinner = ora('Creating ES6 modules build').start() - runBabel( - {copyFiles, outDir: path.resolve('es'), src}, - merge(buildConfig.babel, buildConfig.babelDev || {}, { - // Don't transpile modules, for use by ES6 module bundlers - modules: false, - // Don't set the path to nwb's babel-runtime, as it will need to be a - // peerDependency of your module if you use transform-runtime's helpers - // option. - setRuntimePath: false, - }), - userConfig.babel, - ) spinner.succeed() + fs.unlink('.babelrc', () => { + cb() + }) } - - temp.cleanupSync() - - if (!userConfig.npm.umd) { - return cb() + catch (err) { + spinner.fail() + fs.unlink('.babelrc', () => { + cb(err) + }) } +} - spinner = ora('Creating UMD builds').start() +/** + * Create development and production UMD builds for