From 468aec32a8ed5ee2fb5f78a9dfa39f7f3bb633fa Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 29 May 2019 12:08:14 +0700 Subject: [PATCH] Require Node.js 8 and Grunt 1 --- .editorconfig | 2 +- .gitattributes | 2 +- .gitignore | 1 + .npmrc | 1 + .travis.yml | 8 ++- gruntfile.js | 75 ++++++++++++++++++---------- license | 20 ++------ package.json | 106 ++++++++++++++++++++-------------------- readme.md | 17 ++----- tasks/concurrent.js | 89 +++++++++++++++++---------------- test/fixtures/server.js | 4 +- test/test.js | 72 +++++++++++++-------------- 12 files changed, 201 insertions(+), 196 deletions(-) create mode 100644 .npmrc diff --git a/.editorconfig b/.editorconfig index 98a761d..1c6314a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,6 +7,6 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[{package.json,*.yml}] +[*.yml] indent_style = space indent_size = 2 diff --git a/.gitattributes b/.gitattributes index 176a458..6313b56 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -* text=auto +* text=auto eol=lf diff --git a/.gitignore b/.gitignore index 7079eb9..ae7d166 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules +yarn.lock test/tmp diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..43c97e7 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/.travis.yml b/.travis.yml index a78e23d..f98fed0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ -sudo: false language: node_js node_js: - - '5' - - '4' - - '0.12' - - '0.10' + - '12' + - '10' + - '8' diff --git a/gruntfile.js b/gruntfile.js index d685a3e..2a99108 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -1,19 +1,36 @@ 'use strict'; -var supportsColor = require('supports-color'); +const supportsColor = require('supports-color'); -module.exports = function (grunt) { +module.exports = grunt => { grunt.initConfig({ concurrent: { - test: ['test1', 'test2', 'test3'], - testSequence: ['test4', ['test5', 'test6']], - testargs: ['testargs1', 'testargs2'], + test: [ + 'test1', + 'test2', + 'test3' + ], + testSequence: [ + 'test4', [ + 'test5', + 'test6' + ] + ], + testargs: [ + 'testargs1', + 'testargs2' + ], log: { options: { logConcurrentOutput: true }, - tasks: ['nodemon', 'watch'] + tasks: [ + 'nodemon', + 'watch' + ] }, - colors: ['colorcheck'] + colors: [ + 'colorcheck' + ] }, simplemocha: { test: { @@ -24,12 +41,18 @@ module.exports = function (grunt) { } }, clean: { - test: ['test/tmp'] + test: [ + 'test/tmp' + ] }, watch: { scripts: { - files: ['tasks/*.js'], - tasks: ['default'] + files: [ + 'tasks/*.js' + ], + tasks: [ + 'default' + ] } }, nodemon: { @@ -47,54 +70,54 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-simple-mocha'); grunt.loadNpmTasks('grunt-nodemon'); - grunt.registerTask('test1', function () { + grunt.registerTask('test1', () => { console.log('test1'); grunt.file.write('test/tmp/1'); }); grunt.registerTask('test2', function () { - var cb = this.async(); - setTimeout(function () { + const cb = this.async(); + setTimeout(() => { console.log('test2'); grunt.file.write('test/tmp/2'); cb(); }, 1000); }); - grunt.registerTask('test3', function () { + grunt.registerTask('test3', () => { console.log('test3'); grunt.file.write('test/tmp/3'); }); - grunt.registerTask('test4', function () { + grunt.registerTask('test4', () => { console.log('test4'); grunt.file.write('test/tmp/4'); }); - grunt.registerTask('test5', function () { + grunt.registerTask('test5', () => { console.log('test5'); grunt.file.write('test/tmp/5'); sleep(1000); }); - grunt.registerTask('test6', function () { + grunt.registerTask('test6', () => { console.log('test6'); grunt.file.write('test/tmp/6'); }); - grunt.registerTask('testargs1', function () { - var args = grunt.option.flags().join(); + grunt.registerTask('testargs1', () => { + const args = grunt.option.flags().join(); grunt.file.write('test/tmp/args1', args); }); - grunt.registerTask('testargs2', function () { - var args = grunt.option.flags().join(); + grunt.registerTask('testargs2', () => { + const args = grunt.option.flags().join(); grunt.file.write('test/tmp/args2', args); }); - grunt.registerTask('colorcheck', function () { - // writes 'true' or 'false' to the file - var supports = String(Boolean(supportsColor)); + grunt.registerTask('colorcheck', () => { + // Writes 'true' or 'false' to the file + const supports = String(Boolean(supportsColor.stdout)); grunt.file.write('test/tmp/colors', supports); }); @@ -108,8 +131,8 @@ module.exports = function (grunt) { }; function sleep(milliseconds) { - var start = new Date().getTime(); - for (var i = 0; i < 1e7; i++) { + const start = new Date().getTime(); + for (let i = 0; i < 1e7; i++) { if ((new Date().getTime() - start) > milliseconds) { break; } diff --git a/license b/license index 654d0bf..e7af2f7 100644 --- a/license +++ b/license @@ -1,21 +1,9 @@ -The MIT License (MIT) +MIT License Copyright (c) Sindre Sorhus (sindresorhus.com) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/package.json b/package.json index b2ab4a4..4907cf2 100644 --- a/package.json +++ b/package.json @@ -1,55 +1,55 @@ { - "name": "grunt-concurrent", - "version": "2.3.1", - "description": "Run grunt tasks concurrently", - "keywords": [ - "gruntplugin", - "concurrent", - "parallel", - "simultaneous", - "optimize", - "speed", - "perf", - "performance", - "fast", - "faster" - ], - "author": { - "name": "Sindre Sorhus", - "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" - }, - "repository": "sindresorhus/grunt-concurrent", - "scripts": { - "test": "xo && grunt" - }, - "files": [ - "tasks" - ], - "engines": { - "node": ">=0.10.0" - }, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.1", - "async": "^1.2.1", - "indent-string": "^2.0.0", - "pad-stream": "^1.0.0" - }, - "devDependencies": { - "cross-spawn": "^2.0.0", - "grunt": "^0.4.5", - "grunt-cli": "^0.1.13", - "grunt-contrib-clean": "^0.7.0", - "grunt-contrib-watch": "^0.6.1", - "grunt-nodemon": "^0.4.0", - "grunt-simple-mocha": "^0.4.0", - "nodemon": "^1.2.1", - "path-exists": "^2.0.0", - "supports-color": "^3.1.2", - "xo": "*" - }, - "peerDependencies": { - "grunt": ">=0.4.0" - } + "name": "grunt-concurrent", + "version": "2.3.1", + "description": "Run grunt tasks concurrently", + "license": "MIT", + "repository": "sindresorhus/grunt-concurrent", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && grunt" + }, + "files": [ + "tasks" + ], + "keywords": [ + "gruntplugin", + "concurrent", + "parallel", + "simultaneous", + "optimize", + "speed", + "perf", + "performance", + "fast", + "faster" + ], + "dependencies": { + "arrify": "^2.0.1", + "async": "^3.0.1", + "indent-string": "^4.0.0", + "pad-stream": "^2.0.0" + }, + "devDependencies": { + "cross-spawn": "^6.0.5", + "grunt": "^1.0.4", + "grunt-cli": "^1.3.2", + "grunt-contrib-clean": "^2.0.0", + "grunt-contrib-watch": "^1.1.0", + "grunt-nodemon": "^0.4.0", + "grunt-simple-mocha": "^0.4.0", + "nodemon": "^1.2.1", + "path-exists": "^4.0.0", + "supports-color": "^6.1.0", + "xo": "^0.24.0" + }, + "peerDependencies": { + "grunt": ">=1" + } } diff --git a/readme.md b/readme.md index ffb3eb4..b649462 100644 --- a/readme.md +++ b/readme.md @@ -2,12 +2,6 @@ > Run grunt tasks concurrently ---- - -

🔥 Want to strengthen your core JavaScript skills and master ES6?
I would personally recommend this awesome ES6 course by Wes Bos.

- ---- - Running slow tasks like Coffee and Sass concurrently can potentially improve your build time significantly. This task is also useful if you need to run [multiple blocking tasks](#logconcurrentoutput) like `nodemon` and `watch` at once. @@ -23,7 +17,7 @@ $ npm install --save-dev grunt-concurrent ## Usage ```js -require('load-grunt-tasks')(grunt); // npm install --save-dev load-grunt-tasks +require('load-grunt-tasks')(grunt); grunt.initConfig({ concurrent: { @@ -32,8 +26,7 @@ grunt.initConfig({ } }); -// tasks of target1 run concurrently, after they all finished, tasks of target2 run concurrently, -// instead of target1 and target2 run concurrently. +// Tasks of target1 run concurrently, after they all finished, tasks of target2 run concurrently, instead of target1 and target2 running concurrently. grunt.registerTask('default', ['concurrent:target1', 'concurrent:target2']); ``` @@ -46,6 +39,7 @@ grunt.initConfig({ } }); ``` + Now `jshint` will always be done before `coffee` and `sass` runs independent of both of them. @@ -82,8 +76,3 @@ grunt.registerTask('default', ['concurrent:target']); ``` *The output will be messy when combining certain tasks. This option is best used with tasks that don't exit like `watch` and `nodemon` to monitor the output of long-running concurrent tasks.* - - -## License - -MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/tasks/concurrent.js b/tasks/concurrent.js index 74f8098..7feaaf8 100644 --- a/tasks/concurrent.js +++ b/tasks/concurrent.js @@ -1,78 +1,83 @@ 'use strict'; -var os = require('os'); -var padStream = require('pad-stream'); -var async = require('async'); -var arrify = require('arrify'); -var indentString = require('indent-string'); +const os = require('os'); +const padStream = require('pad-stream'); +const async = require('async'); +const arrify = require('arrify'); +const indentString = require('indent-string'); -var cpCache = []; +const subprocesses = []; -module.exports = function (grunt) { +module.exports = grunt => { grunt.registerMultiTask('concurrent', 'Run grunt tasks concurrently', function () { - var cb = this.async(); - var opts = this.options({ + const done = this.async(); + + const options = this.options({ limit: Math.max((os.cpus().length || 1) * 2, 2) }); - var tasks = this.data.tasks || this.data; - var flags = grunt.option.flags(); - if (flags.indexOf('--no-color') === -1 && - flags.indexOf('--no-colors') === -1 && - flags.indexOf('--color=false') === -1) { - // append the flag so that support-colors won't return false - // see issue #70 for details + const tasks = this.data.tasks || this.data; + const flags = grunt.option.flags(); + + if ( + !flags.includes('--no-color') && + !flags.includes('--no-colors') && + !flags.includes('--color=false') + ) { + // Append the flag so that support-colors won't return false + // See issue #70 for details flags.push('--color'); } - if (opts.limit < tasks.length) { + if (options.limit < tasks.length) { grunt.log.oklns( - 'Warning: There are more tasks than your concurrency limit. After ' + - 'this limit is reached no further tasks will be run until the ' + - 'current tasks are completed. You can adjust the limit in the ' + - 'concurrent task options' + 'Warning: There are more tasks than your concurrency limit. After this limit is reached no further tasks will be run until the current tasks are completed. You can adjust the limit in the concurrent task options' ); } - async.eachLimit(tasks, opts.limit, function (task, next) { - var cp = grunt.util.spawn({ + async.eachLimit(tasks, options.limit, (task, next) => { + const subprocess = grunt.util.spawn({ grunt: true, args: arrify(task).concat(flags), opts: { - stdio: ['ignore', 'pipe', 'pipe'] + stdio: [ + 'ignore', + 'pipe', + 'pipe' + ] } - }, function (err, result) { - if (!opts.logConcurrentOutput) { - grunt.log.writeln('\n' + indentString(result.stdout + result.stderr, ' ', 4)); + }, (error, result) => { + if (!options.logConcurrentOutput) { + grunt.log.writeln('\n' + indentString(result.stdout + result.stderr, 4)); } - next(err); + next(error); }); - if (opts.logConcurrentOutput) { - cp.stdout.pipe(padStream(' ', 4)).pipe(process.stdout); - cp.stderr.pipe(padStream(' ', 4)).pipe(process.stderr); + if (options.logConcurrentOutput) { + subprocess.stdout.pipe(padStream(4)).pipe(process.stdout); + subprocess.stderr.pipe(padStream(4)).pipe(process.stderr); } - cpCache.push(cp); - }, function (err) { - if (err) { - grunt.warn(err); + subprocesses.push(subprocess); + }, error => { + if (error) { + grunt.warn(error); } - cb(); + done(); }); }); }; function cleanup() { - cpCache.forEach(function (el) { - el.kill('SIGKILL'); - }); + for (const subprocess of subprocesses) { + subprocess.kill('SIGKILL'); + } } -// make sure all child processes are killed when grunt exits +// Make sure all subprocesses are killed when grunt exits process.on('exit', cleanup); -process.on('SIGINT', function () { +process.on('SIGINT', () => { cleanup(); - process.exit(); // eslint-disable-line xo/no-process-exit + process.exit(); }); diff --git a/test/fixtures/server.js b/test/fixtures/server.js index a550969..778092a 100644 --- a/test/fixtures/server.js +++ b/test/fixtures/server.js @@ -1,7 +1,7 @@ 'use strict'; -var net = require('net'); +const net = require('net'); -var server = net.createServer(function (socket) { +const server = net.createServer(socket => { socket.write('Hello world').pipe(socket); }); diff --git a/test/test.js b/test/test.js index 75032e8..efd0b3a 100644 --- a/test/test.js +++ b/test/test.js @@ -1,71 +1,71 @@ 'use strict'; /* eslint-env mocha */ -var assert = require('assert'); -var fs = require('fs'); -var path = require('path'); -var exec = require('child_process').exec; -var pathExists = require('path-exists'); -var spawn = require('cross-spawn'); +const {strict: assert} = require('assert'); +const fs = require('fs'); +const path = require('path'); +const {exec} = require('child_process'); +const pathExists = require('path-exists'); +const spawn = require('cross-spawn'); -describe('concurrent', function () { - it('runs grunt tasks successfully', function () { +describe('concurrent', () => { + it('runs grunt tasks successfully', () => { assert(pathExists.sync(path.join(__dirname, 'tmp/1'))); assert(pathExists.sync(path.join(__dirname, 'tmp/2'))); assert(pathExists.sync(path.join(__dirname, 'tmp/3'))); }); - it('runs grunt task sequence successfully', function () { - var file5 = fs.statSync(path.join(__dirname, 'tmp/5')); - var file6 = fs.statSync(path.join(__dirname, 'tmp/6')); + it('runs grunt task sequence successfully', () => { + const file5 = fs.statSync(path.join(__dirname, 'tmp/5')); + const file6 = fs.statSync(path.join(__dirname, 'tmp/6')); assert.ok(Date.parse(file5.ctime) < Date.parse(file6.ctime)); }); - it('forwards CLI args to grunt sub-processes', function (done) { - var expected = '--arg1=test,--arg2'; + it('forwards CLI args to grunt sub-processes', done => { + const expected = '--arg1=test,--arg2'; - exec('grunt concurrent:testargs ' + expected, function () { - var args1 = fs.readFileSync(path.join(__dirname, 'tmp/args1'), 'utf8'); - var args2 = fs.readFileSync(path.join(__dirname, 'tmp/args2'), 'utf8'); - assert.ok(args1.indexOf(expected) !== -1); - assert.ok(args2.indexOf(expected) !== -1); + exec('grunt concurrent:testargs ' + expected, () => { + const args1 = fs.readFileSync(path.join(__dirname, 'tmp/args1'), 'utf8'); + const args2 = fs.readFileSync(path.join(__dirname, 'tmp/args2'), 'utf8'); + assert.ok(args1.includes(expected)); + assert.ok(args2.includes(expected)); done(); }); }); - describe('`logConcurrentOutput` option', function () { - var logOutput = ''; + describe('`logConcurrentOutput` option', () => { + let logOutput = ''; - before(function (done) { - var doneCalled = false; - var cp = spawn('grunt', ['concurrent:log']); + before(done => { + let isDoneCalled = false; + const subprocess = spawn('grunt', ['concurrent:log']); - cp.stdout.setEncoding('utf8'); - cp.stdout.on('data', function (data) { + subprocess.stdout.setEncoding('utf8'); + subprocess.stdout.on('data', data => { logOutput += data; - cp.kill(); - if (!doneCalled) { - doneCalled = true; + subprocess.kill(); + if (!isDoneCalled) { + isDoneCalled = true; done(); } }); }); - it('outputs concurrent logging', function () { - var expected = 'Running "concurrent:log" (concurrent) task'; - assert(logOutput.indexOf(expected) !== -1); + it('outputs concurrent logging', () => { + const expected = 'Running "concurrent:log" (concurrent) task'; + assert(logOutput.includes(expected)); }); }); - describe('works with supports-color lib', function () { - it('ensures that colors are supported by default', function (done) { - exec('grunt concurrent:colors', function () { + describe('works with supports-color lib', () => { + it('ensures that colors are supported by default', done => { + exec('grunt concurrent:colors', () => { assert.equal(fs.readFileSync(path.join(__dirname, 'tmp/colors'), 'utf8'), 'true'); done(); }); }); - it('doesn\'t support colors with --no-color option', function (done) { - exec('grunt concurrent:colors --no-color', function () { + it('doesn\'t support colors with --no-color option', done => { + exec('grunt concurrent:colors --no-color', () => { assert.equal(fs.readFileSync(path.join(__dirname, 'tmp/colors'), 'utf8'), 'false'); done(); });