diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f06090b..7b98823e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v0.4.12 + +* [Add `compilerOptions` option](https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/173) (#173) + ## v0.4.11 * [Fix os.cpus is not a function](https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/172) (#172) diff --git a/README.md b/README.md index 202f2ee2..7988e0ce 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,9 @@ It helps to distinguish lints from typescript's diagnostics. * **tsconfig** `string`: Path to *tsconfig.json* file. Default: `path.resolve(compiler.options.context, './tsconfig.json')`. +* **compilerOptions** `object`: +Allows overriding TypeScript options. Should be specified in the same format as you would do for the `compilerOptions` property in tsconfig.json. Default: `{}`. + * **tslint** `string | true`: Path to *tslint.json* file or `true`. If `true`, uses `path.resolve(compiler.options.context, './tslint.json')`. Default: `undefined`. diff --git a/package.json b/package.json index c8920f6b..816e26ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fork-ts-checker-webpack-plugin", - "version": "0.4.11", + "version": "0.4.12", "description": "Runs typescript type checker and linter on separate process.", "main": "lib/index.js", "types": "lib/types/index.d.ts", diff --git a/src/IncrementalChecker.ts b/src/IncrementalChecker.ts index f6b8d9e6..0104ee28 100644 --- a/src/IncrementalChecker.ts +++ b/src/IncrementalChecker.ts @@ -22,6 +22,7 @@ interface ConfigurationFile extends Configuration.IConfigurationFile { export class IncrementalChecker { programConfigFile: string; + compilerOptions: object; linterConfigFile: string | false; watchPaths: string[]; workNumber: number; @@ -41,6 +42,7 @@ export class IncrementalChecker { constructor( programConfigFile: string, + compilerOptions: object, linterConfigFile: string | false, watchPaths: string[], workNumber: number, @@ -49,6 +51,7 @@ export class IncrementalChecker { vue: boolean ) { this.programConfigFile = programConfigFile; + this.compilerOptions = compilerOptions; this.linterConfigFile = linterConfigFile; this.watchPaths = watchPaths; this.workNumber = workNumber || 0; @@ -68,8 +71,8 @@ export class IncrementalChecker { })); } - static loadProgramConfig(configFile: string) { - return ts.parseJsonConfigFileContent( + static loadProgramConfig(configFile: string, compilerOptions: object) { + const parsed = ts.parseJsonConfigFileContent( // Regardless of the setting in the tsconfig.json we want isolatedModules to be false Object.assign(ts.readConfigFile(configFile, ts.sys.readFile).config, { isolatedModules: false @@ -77,6 +80,10 @@ export class IncrementalChecker { ts.sys, path.dirname(configFile) ); + + parsed.options = { ...parsed.options, ...compilerOptions }; + + return parsed; } static loadLinterConfig(configFile: string): ConfigurationFile { @@ -189,7 +196,10 @@ export class IncrementalChecker { loadVueProgram() { this.programConfig = this.programConfig || - VueProgram.loadProgramConfig(this.programConfigFile); + VueProgram.loadProgramConfig( + this.programConfigFile, + this.compilerOptions + ); return VueProgram.createProgram( this.programConfig, @@ -203,7 +213,10 @@ export class IncrementalChecker { loadDefaultProgram() { this.programConfig = this.programConfig || - IncrementalChecker.loadProgramConfig(this.programConfigFile); + IncrementalChecker.loadProgramConfig( + this.programConfigFile, + this.compilerOptions + ); return IncrementalChecker.createProgram( this.programConfig, diff --git a/src/VueProgram.ts b/src/VueProgram.ts index 5dc42e43..9a52f544 100644 --- a/src/VueProgram.ts +++ b/src/VueProgram.ts @@ -12,7 +12,7 @@ interface ResolvedScript { } export class VueProgram { - static loadProgramConfig(configFile: string) { + static loadProgramConfig(configFile: string, compilerOptions: object) { const extraExtensions = ['vue']; const parseConfigHost: ts.ParseConfigHost = { @@ -40,6 +40,7 @@ export class VueProgram { ); parsed.options.allowNonTsExtensions = true; + parsed.options = { ...parsed.options, ...compilerOptions }; return parsed; } diff --git a/src/index.ts b/src/index.ts index 89ceea0c..ee51aaa7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,6 +39,7 @@ interface Logger { interface Options { tsconfig: string; + compilerOptions: object; tslint: string | true; watch: string | string[]; async: boolean; @@ -71,6 +72,7 @@ class ForkTsCheckerWebpackPlugin { options: Partial; tsconfig: string; + compilerOptions: object; tslint: string | true; watch: string[]; ignoreDiagnostics: number[]; @@ -114,6 +116,10 @@ class ForkTsCheckerWebpackPlugin { this.options = Object.assign({}, options); this.tsconfig = options.tsconfig || './tsconfig.json'; + this.compilerOptions = + typeof options.compilerOptions === 'object' + ? options.compilerOptions + : {}; this.tslint = options.tslint ? options.tslint === true ? './tslint.json' @@ -554,6 +560,7 @@ class ForkTsCheckerWebpackPlugin { : ['--max-old-space-size=' + this.memoryLimit], env: Object.assign({}, process.env, { TSCONFIG: this.tsconfigPath, + COMPILER_OPTIONS: JSON.stringify(this.compilerOptions), TSLINT: this.tslintPath || '', WATCH: this.isWatching ? this.watchPaths.join('|') : '', WORK_DIVISION: Math.max(1, this.workersNumber), diff --git a/src/service.ts b/src/service.ts index 7013d485..01307205 100644 --- a/src/service.ts +++ b/src/service.ts @@ -6,6 +6,7 @@ import { NormalizedMessage } from './NormalizedMessage'; const checker = new IncrementalChecker( process.env.TSCONFIG, + JSON.parse(process.env.COMPILER_OPTIONS), process.env.TSLINT === '' ? false : process.env.TSLINT, process.env.WATCH === '' ? [] : process.env.WATCH.split('|'), parseInt(process.env.WORK_NUMBER, 10), diff --git a/test/integration/vue.spec.js b/test/integration/vue.spec.js index e4c6f522..bc622c51 100644 --- a/test/integration/vue.spec.js +++ b/test/integration/vue.spec.js @@ -76,6 +76,7 @@ describe('[INTEGRATION] vue', function() { checker = new IncrementalChecker( plugin.tsconfigPath, + {}, plugin.tslintPath || false, [compiler.context], ForkTsCheckerWebpackPlugin.ONE_CPU, diff --git a/test/unit/IncrementalChecker.spec.js b/test/unit/IncrementalChecker.spec.js index 162eb0eb..bcb1c3c9 100644 --- a/test/unit/IncrementalChecker.spec.js +++ b/test/unit/IncrementalChecker.spec.js @@ -3,11 +3,36 @@ var it = require('mocha').it; var expect = require('chai').expect; var path = require('path'); var minimatch = require('minimatch'); - -var IncrementalChecker = require('../../lib/IncrementalChecker') - .IncrementalChecker; +var mockRequire = require('mock-require'); +var sinon = require('sinon'); describe('[UNIT] IncrementalChecker', function() { + var IncrementalChecker; + + beforeEach(function() { + var parseJsonConfigFileContentStub = sinon.stub().returns({ + options: { + foo: true + } + }); + var readConfigFileStub = sinon.stub().returns({ + config: {} + }); + + mockRequire('typescript', { + parseJsonConfigFileContent: parseJsonConfigFileContentStub, + readConfigFile: readConfigFileStub, + sys: {} + }); + + IncrementalChecker = mockRequire.reRequire('../../lib/IncrementalChecker') + .IncrementalChecker; + }); + + afterEach(function() { + mockRequire.stopAll(); + }); + describe('isFileExcluded', function() { it('should properly filter definition files and listed exclusions', function() { var linterConfig = { @@ -41,4 +66,17 @@ describe('[UNIT] IncrementalChecker', function() { expect(pathsAreExcluded[3]).to.be.true; }); }); + + describe('loadProgramConfig', function() { + it('merges compilerOptions into returned options', function() { + var result = IncrementalChecker.loadProgramConfig('tsconfig.foo.json', { + bar: false + }); + + expect(result.options).to.deep.equal({ + foo: true, + bar: false + }); + }); + }); }); diff --git a/test/unit/VueProgram.spec.js b/test/unit/VueProgram.spec.js index 26f86ac8..9991cc0d 100644 --- a/test/unit/VueProgram.spec.js +++ b/test/unit/VueProgram.spec.js @@ -2,9 +2,36 @@ var ts = require('typescript'); var describe = require('mocha').describe; var it = require('mocha').it; var expect = require('chai').expect; -var VueProgram = require('../../lib/VueProgram').VueProgram; +var mockRequire = require('mock-require'); +var sinon = require('sinon'); describe('[UNIT] VueProgram', function() { + var VueProgram; + + beforeEach(function() { + var parseJsonConfigFileContentStub = sinon.stub().returns({ + options: { + foo: true + } + }); + var readConfigFileStub = sinon.stub().returns({ + config: {} + }); + + mockRequire('typescript', { + parseJsonConfigFileContent: parseJsonConfigFileContentStub, + readConfigFile: readConfigFileStub, + sys: {}, + ScriptKind: ts.ScriptKind + }); + + VueProgram = mockRequire.reRequire('../../lib/VueProgram').VueProgram; + }); + + afterEach(function() { + mockRequire.stopAll(); + }); + it('should determine if file is a Vue file', function() { expect(VueProgram.isVue('./test.vue')).to.be.true; expect(VueProgram.isVue('../test.vue')).to.be.true; @@ -130,4 +157,24 @@ describe('[UNIT] VueProgram', function() { ].join('\n') ); }); + + describe('loadProgramConfig', function() { + it('sets allowNonTsExtensions to true on returned options', function() { + var result = VueProgram.loadProgramConfig('tsconfig.foo.json', {}); + + expect(result.options.allowNonTsExtensions).to.equal(true); + }); + + it('merges compilerOptions into returned options', function() { + var result = VueProgram.loadProgramConfig('tsconfig.foo.json', { + bar: false + }); + + expect(result.options).to.deep.equal({ + foo: true, + bar: false, + allowNonTsExtensions: true + }); + }); + }); });