From 9a9926299038f28249cc855aeeb4de5ae3cb7da8 Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Tue, 8 Aug 2017 17:51:11 -0700 Subject: [PATCH 1/5] More gulp config --- gulpfile.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 00826c36..9fa9c95f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,12 +9,21 @@ const merge2 = require('merge2'); const path = require('path'); const through = require('through2'); -const tslintPath = './tslint.json' +const tslintPath = './tslint.json'; const tsconfigPath = './tsconfig.json'; const outDir = 'build'; function onError() {} +// If --dev is passed, override certain ts config options +let tsDevOptions = {}; +if (util.env.dev) { + tsDevOptions = { + allowUnreachableCode: true, + noUnusedParameters: false + }; +} + /** * Helper function that creates a gulp task function that opens files in a * directory that match a certain glob pattern, transpiles them, and writes them @@ -31,7 +40,7 @@ function makeCompileFn(baseDir, globs) { const transpileGlob = globs.transpile || '**/*.ts'; const copyGlob = globs.copy || '**/!(*.ts)'; return () => { - const tsProject = typescript.createProject(tsconfigPath)(); + const tsProject = typescript.createProject(tsconfigPath, tsDevOptions)(); const { dts, js } = gulp.src(`${baseDir}/${transpileGlob}`) .pipe(sourcemaps.init()) .pipe(tsProject) @@ -149,4 +158,18 @@ gulp.task('test.single', ['compile', '.compileSingleTestFile'], () => { })); }); -gulp.task('default', ['compile']); +gulp.task('help', () => { + console.log(` +gulp help: Prints this message. +gulp clean: Deletes transpiled code. +gulp compile: Transpiles src. +gulp lint: Lints src and test. +gulp test.compile: Transpiles src and test. +gulp test: Runs \`gulp test.compile\`, and then runs all tests. +gulp test.single --file $FILE: Transpiles src and $FILE, and runs only the transpiled $FILE. (See also: #5) +gulp * --color: Prints output in color; particularly useful for tests. +gulp * --dev: Runs the task with relaxed TS compiler options. + `.trim()); +}); + +gulp.task('default', ['help']); From 4ee475112cfac939e5e5c0bc781d55380c94cede Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Tue, 8 Aug 2017 18:15:53 -0700 Subject: [PATCH 2/5] fix tslint path --- gulpfile.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 9fa9c95f..707a985c 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,7 +9,7 @@ const merge2 = require('merge2'); const path = require('path'); const through = require('through2'); -const tslintPath = './tslint.json'; +const tslintPath = './node_modules/google-ts-style/tslint.json'; const tsconfigPath = './tsconfig.json'; const outDir = 'build'; @@ -64,7 +64,7 @@ function makeCompileFn(baseDir, globs) { */ gulp.task('lint', () => { const program = require('tslint').Linter.createProgram(tsconfigPath); - gulp.src(srcGlob) + gulp.src(['src/**/*.ts', 'test/**/*.ts']) .pipe(tslint({ configuration: tslintPath, formatter: 'prose', @@ -163,7 +163,7 @@ gulp.task('help', () => { gulp help: Prints this message. gulp clean: Deletes transpiled code. gulp compile: Transpiles src. -gulp lint: Lints src and test. +gulp lint: Emits linting errors found in src/ and test/. gulp test.compile: Transpiles src and test. gulp test: Runs \`gulp test.compile\`, and then runs all tests. gulp test.single --file $FILE: Transpiles src and $FILE, and runs only the transpiled $FILE. (See also: #5) From a49c05ba009d0576d4a9f8ed3ff03e912dd41521 Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Wed, 9 Aug 2017 12:31:07 -0700 Subject: [PATCH 3/5] more precise options --- gulpfile.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 707a985c..ed5b7cf8 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -20,7 +20,10 @@ let tsDevOptions = {}; if (util.env.dev) { tsDevOptions = { allowUnreachableCode: true, - noUnusedParameters: false + noUnusedParameters: false, + noImplicitAny: false, + noImplicitThis: false, + noEmitOnError: false }; } @@ -28,7 +31,6 @@ if (util.env.dev) { * Helper function that creates a gulp task function that opens files in a * directory that match a certain glob pattern, transpiles them, and writes them * to an output directory. - * @param {string} baseDir The name of the directory containing the files. * @param {Object} globs * @param {string=} globs.transpile The glob pattern for files to transpile. * Defaults to match all *.ts files in baseDir (incl. subdirectories). @@ -36,25 +38,25 @@ if (util.env.dev) { * Defaults to match all but *.ts files in baseDir (incl. subdirectories). * @return A gulp task function. */ -function makeCompileFn(baseDir, globs) { +function makeCompileFn(globs) { const transpileGlob = globs.transpile || '**/*.ts'; - const copyGlob = globs.copy || '**/!(*.ts)'; + const copyGlob = globs.copy || '!(**/*)'; return () => { const tsProject = typescript.createProject(tsconfigPath, tsDevOptions)(); - const { dts, js } = gulp.src(`${baseDir}/${transpileGlob}`) + const { dts, js } = gulp.src(transpileGlob, { base: '.' }) .pipe(sourcemaps.init()) .pipe(tsProject) .on('error', onError); const jsmap = js.pipe(sourcemaps.write('.', { includeContent: false, - sourceRoot: path.relative(`${outDir}/${baseDir}`, baseDir) + sourceRoot: outDir })); - const copy = gulp.src(`${baseDir}/${copyGlob}`); + const copy = gulp.src(copyGlob); return merge2([ - js.pipe(gulp.dest(`${outDir}/${baseDir}`)), + js.pipe(gulp.dest(`${outDir}`)), dts.pipe(gulp.dest(`${outDir}/types`)), - jsmap.pipe(gulp.dest(`${outDir}/${baseDir}`)), - copy.pipe(gulp.dest(`${outDir}/${baseDir}`)) + jsmap.pipe(gulp.dest(`${outDir}`)), + copy.pipe(gulp.dest(`${outDir}`)) ]); }; } @@ -84,14 +86,13 @@ gulp.task('clean', () => { * Currently, all errors are emitted twice. This is being tracked here: * https://github.com/ivogabe/gulp-typescript/issues/438 */ -gulp.task('compile', makeCompileFn('src', - { transpile: '**/*.ts' })); +gulp.task('compile', makeCompileFn({ transpile: ['*.ts', 'src/**/*.ts'] })); /** * Transpiles TypeScript files in both src/ and test/. */ gulp.task('test.compile', ['compile'], - makeCompileFn('test', { transpile: '**/*.ts' })); + makeCompileFn({ transpile: '**/test/**/*.ts', copy: 'test/**/!(*.ts)' })); /** * Starts watching files in src/, running the 'compile' step whenever a file @@ -116,7 +117,7 @@ gulp.task('test', ['test.compile'], () => { * @private */ gulp.task('.compileSingleTestFile', util.env.file ? - makeCompileFn('test', { transpile: path.relative('test', util.env.file) }) : + makeCompileFn({ transpile: path.relative('.', util.env.file) }) : () => { throw new Error('No file specified'); }); /** From dcc18ee2e71538a97545e3c167e73869d40a2821 Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Wed, 9 Aug 2017 15:29:17 -0700 Subject: [PATCH 4/5] include top-level file in transpilation --- gulpfile.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index ed5b7cf8..da9480dc 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -49,9 +49,9 @@ function makeCompileFn(globs) { .on('error', onError); const jsmap = js.pipe(sourcemaps.write('.', { includeContent: false, - sourceRoot: outDir + sourceRoot: '..' })); - const copy = gulp.src(copyGlob); + const copy = gulp.src(copyGlob, { base: '.' }); return merge2([ js.pipe(gulp.dest(`${outDir}`)), dts.pipe(gulp.dest(`${outDir}/types`)), @@ -131,9 +131,9 @@ gulp.task('test.single', ['compile', '.compileSingleTestFile'], () => { // util.env contains CLI arguments for the gulp task. const { file } = util.env; // Determine the path to the transpiled version of this TS file. - const dirWithinTest = path.dirname(path.relative('./test', file)); + const dir = path.dirname(path.relative('.', file)); const basename = path.basename(file, '.ts'); - const transpiledPath = `${outDir}/test/${dirWithinTest}/${basename}.js`; + const transpiledPath = `${outDir}/${dir}/${basename}.js`; // Construct an instance of Mocha's runner API and feed it the path to the // transpiled source. return gulp.src(transpiledPath) @@ -143,11 +143,6 @@ gulp.task('test.single', ['compile', '.compileSingleTestFile'], () => { const runner = new Mocha(); // Add the path to the test file to debug. runner.addFile(file.path); - // "Load" the test file. - // This is a no-op hack so that VS Code is informed that breakpoints set - // in this file should be hit. - // Because mocha's global-scope variables aren't loaded, this will throw. - try { require(file.path); } catch (e) {}; // Run the test suite. runner.run((failures) => { if (failures > 0) { From ceeccb783f3d9af2194d395cff4dd03bb429bc9a Mon Sep 17 00:00:00 2001 From: Kelvin Jin Date: Fri, 11 Aug 2017 12:36:07 -0700 Subject: [PATCH 5/5] Use gulp-help and allow multiple --file params --- gulpfile.js | 127 ++++++++++++++++++++++++--------------------------- package.json | 1 + 2 files changed, 60 insertions(+), 68 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index da9480dc..740845b2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,6 @@ const del = require('del'); -const gulp = require('gulp'); +const _gulp = require('gulp'); +const help = require('gulp-help'); const mocha = require('gulp-mocha'); const sourcemaps = require('gulp-sourcemaps'); const tslint = require('gulp-tslint'); @@ -9,12 +10,19 @@ const merge2 = require('merge2'); const path = require('path'); const through = require('through2'); +// gulp-help monkeypatches tasks to have an additional description parameter +const gulp = help(_gulp); + const tslintPath = './node_modules/google-ts-style/tslint.json'; const tsconfigPath = './tsconfig.json'; const outDir = 'build'; function onError() {} +// Coalesces all specified --file parameters into a single array +const files = !util.env.file ? [] : + Array.isArray(util.env.file) ? util.env.file : [util.env.file]; + // If --dev is passed, override certain ts config options let tsDevOptions = {}; if (util.env.dev) { @@ -64,7 +72,7 @@ function makeCompileFn(globs) { /** * Runs tslint on files in src/, with linting rules defined in tslint.json. */ -gulp.task('lint', () => { +gulp.task('lint', 'Emits linting errors found in src/ and test/.', () => { const program = require('tslint').Linter.createProgram(tsconfigPath); gulp.src(['src/**/*.ts', 'test/**/*.ts']) .pipe(tslint({ @@ -76,7 +84,7 @@ gulp.task('lint', () => { .on('warning', onError); }); -gulp.task('clean', () => { +gulp.task('clean', 'Deletes transpiled code.', () => { return del(outDir); }); @@ -86,86 +94,69 @@ gulp.task('clean', () => { * Currently, all errors are emitted twice. This is being tracked here: * https://github.com/ivogabe/gulp-typescript/issues/438 */ -gulp.task('compile', makeCompileFn({ transpile: ['*.ts', 'src/**/*.ts'] })); +gulp.task('compile', 'Transpiles src/.', + makeCompileFn({ transpile: ['*.ts', 'src/**/*.ts'] })); /** * Transpiles TypeScript files in both src/ and test/. */ -gulp.task('test.compile', ['compile'], - makeCompileFn({ transpile: '**/test/**/*.ts', copy: 'test/**/!(*.ts)' })); - -/** - * Starts watching files in src/, running the 'compile' step whenever a file - * changes. - */ -gulp.task('watch', () => { - gulp.start(['compile']); - return gulp.watch(srcGlob, ['compile']); -}); +gulp.task('test.compile', 'After dep tasks, transpiles test/.', ['compile'], + makeCompileFn({ transpile: ['test/**/*.ts'], copy: 'test/**/!(*.ts)' })); /** * Transpiles src/ and test/, and then runs all tests. */ -gulp.task('test', ['test.compile'], () => { - return gulp.src(`${outDir}/test/**/*.js`) - .pipe(mocha()); -}); +gulp.task('test', 'After dep tasks, runs all tests.', + ['test.compile'], () => { + return gulp.src(`${outDir}/test/**/*.js`) + .pipe(mocha()); + } +); /** - * Compiles a single test file. Only intended as a pre-requisite for - * 'test.single'. - * @private + * Transpiles individual files, specified by the --file flag. */ -gulp.task('.compileSingleTestFile', util.env.file ? - makeCompileFn({ transpile: path.relative('.', util.env.file) }) : - () => { throw new Error('No file specified'); }); +gulp.task('compile.single', 'Transpiles individual files specified by --file.', + makeCompileFn({ + transpile: files.map(f => path.relative('.', f)) + }) +); /** - * Run a single test, specified by its pre-transpiled source path (as supplied - * through the '--file' flag). This is intended to be used as part of a VS Code - * "Gulp task" launch configuration; setting the "args" field to + * Run individual tests, specified by their pre-transpiled source path (as + * supplied through the '--file' flag). This is intended to be used as part of a + * VS Code "Gulp task" launch configuration; setting the "args" field to * ["test.single", "--file", "${file}"] makes it possible for one to debug the * currently open TS mocha test file in one step. */ -gulp.task('test.single', ['compile', '.compileSingleTestFile'], () => { - // util.env contains CLI arguments for the gulp task. - const { file } = util.env; - // Determine the path to the transpiled version of this TS file. - const dir = path.dirname(path.relative('.', file)); - const basename = path.basename(file, '.ts'); - const transpiledPath = `${outDir}/${dir}/${basename}.js`; - // Construct an instance of Mocha's runner API and feed it the path to the - // transpiled source. - return gulp.src(transpiledPath) - .pipe(through.obj((file, enc, cb) => { - // Construct a new Mocha runner instance. - const Mocha = require('mocha'); - const runner = new Mocha(); - // Add the path to the test file to debug. - runner.addFile(file.path); - // Run the test suite. - runner.run((failures) => { - if (failures > 0) { - cb(new Error(`Mocha: ${failures} failures in ${file.path}]`)); - } else { - cb(null); - } - }); - })); -}); - -gulp.task('help', () => { - console.log(` -gulp help: Prints this message. -gulp clean: Deletes transpiled code. -gulp compile: Transpiles src. -gulp lint: Emits linting errors found in src/ and test/. -gulp test.compile: Transpiles src and test. -gulp test: Runs \`gulp test.compile\`, and then runs all tests. -gulp test.single --file $FILE: Transpiles src and $FILE, and runs only the transpiled $FILE. (See also: #5) -gulp * --color: Prints output in color; particularly useful for tests. -gulp * --dev: Runs the task with relaxed TS compiler options. - `.trim()); -}); +gulp.task('test.single', 'After dep tasks, runs individual files specified ' + + 'by --file.', ['compile', 'compile.single'], () => { + // util.env contains CLI arguments for the gulp task. + // Determine the path to the transpiled version of this TS file. + const getTranspiledPath = (file) => { + const dir = path.dirname(path.relative('.', file)); + const basename = path.basename(file, '.ts'); + return `${outDir}/${dir}/${basename}.js`; + }; + // Construct an instance of Mocha's runner API and feed it the path to the + // transpiled source. + return gulp.src(files.map(getTranspiledPath)) + .pipe(through.obj((file, enc, cb) => { + // Construct a new Mocha runner instance. + const Mocha = require('mocha'); + const runner = new Mocha(); + // Add the path to the test file to debug. + runner.addFile(file.path); + // Run the test suite. + runner.run((failures) => { + if (failures > 0) { + cb(new Error(`Mocha: ${failures} failures in ${file.path}]`)); + } else { + cb(null); + } + }); + })); + } +); gulp.task('default', ['help']); diff --git a/package.json b/package.json index 675df80f..57395bae 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "del": "^3.0.0", "google-ts-style": "latest", "gulp": "^3.9.1", + "gulp-help": "^1.6.1", "gulp-mocha": "^4.3.1", "gulp-sourcemaps": "^2.6.0", "gulp-tslint": "^8.1.1",