From db409d75278aaf407fff6385a9bcd2ebd8473e1e Mon Sep 17 00:00:00 2001 From: Blake Embrey Date: Fri, 10 Jan 2020 13:45:59 -0800 Subject: [PATCH] Fix order of `DEFAULTS`, `tsconfig`, `rawOptions` --- src/index.spec.ts | 19 ++++++++++--- src/index.ts | 69 +++++++++++++++++++---------------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/index.spec.ts b/src/index.spec.ts index 0d0ad927d..94630817f 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -352,7 +352,20 @@ describe('ts-node', function () { describe('should read ts-node options from tsconfig.json', function () { const BIN_EXEC = `node "${join(__dirname, '../dist/bin')}" --project tests/tsconfig-options/tsconfig.json` - it('options pulled from tsconfig.json', function (done) { + it('should override compiler options from env', function (done) { + exec(`${BIN_EXEC} tests/tsconfig-options/log-options.js`, { + env: { + TS_NODE_COMPILER_OPTIONS: '{"typeRoots": ["env-typeroots"]}' + } + }, function (err, stdout) { + expect(err).to.equal(null) + const { config } = JSON.parse(stdout) + expect(config.options.typeRoots).to.deep.equal([join(__dirname, '../tests/tsconfig-options/env-typeroots')]) + return done() + }) + }) + + it('should use options from `tsconfig.json`', function (done) { exec(`${BIN_EXEC} tests/tsconfig-options/log-options.js`, function (err, stdout) { expect(err).to.equal(null) const { options, config } = JSON.parse(stdout) @@ -365,7 +378,7 @@ describe('ts-node', function () { }) }) - it('flags override tsconfig', function (done) { + it('should have flags override `tsconfig.json`', function (done) { exec(`${BIN_EXEC} --skip-ignore --compiler-options '{"types": ["flags-types"]}' tests/tsconfig-options/log-options.js`, function (err, stdout) { expect(err).to.equal(null) const { options, config } = JSON.parse(stdout) @@ -378,7 +391,7 @@ describe('ts-node', function () { }) }) - it('tsconfig overrides env vars', function (done) { + it('should have `tsconfig.json` override environment', function (done) { exec(`${BIN_EXEC} tests/tsconfig-options/log-options.js`, { env: { ...process.env, diff --git a/src/index.ts b/src/index.ts index fe347f2b6..790c36f9a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -195,29 +195,16 @@ export interface TsConfigOptions extends Omit {} /** - * Like Object.assign or splatting, but never overwrites with `undefined`. - * This matches the behavior for argument and destructuring defaults. + * Like `Object.assign`, but ignores `undefined` properties. */ -function defaults (...sources: Array): T { - const merged: T = Object.create(null) +function assign (initialValue: T, ...sources: Array): T { for (const source of sources) { for (const key of Object.keys(source)) { const value = (source as any)[key] - if (value !== undefined) (merged as any)[key] = value + if (value !== undefined) (initialValue as any)[key] = value } } - return merged -} - -/** - * Like `defaults` but for single values, not objects. - */ -export function defaultValue (...values: Array): T | undefined { - let result: T | undefined = undefined - for (const value of values) { - if (value !== undefined) result = value - } - return result + return initialValue } /** @@ -357,8 +344,9 @@ export function register (opts: RegisterOptions = {}): Register { * Create TypeScript compiler instance. */ export function create (rawOptions: CreateOptions = {}): Register { - const inputOptions = defaults(DEFAULTS, rawOptions) - const cwd = inputOptions.dir ? resolve(inputOptions.dir) : process.cwd() + const dir = rawOptions.dir ?? DEFAULTS.dir + const compilerName = rawOptions.compiler ?? DEFAULTS.compiler + const cwd = dir ? resolve(dir) : process.cwd() /** * Load the typescript compiler. It is required to load the tsconfig but might @@ -371,16 +359,14 @@ export function create (rawOptions: CreateOptions = {}): Register { } // Compute minimum options to read the config file. - let { compiler, ts } = loadCompiler(inputOptions.compiler) + let { compiler, ts } = loadCompiler(compilerName) - // Read config file. + // Read config file and merge new options between env and CLI options. const { config, options: tsconfigOptions } = readConfig(cwd, ts, rawOptions) - - // Merge default options, tsconfig options, and explicit options. - const options = defaults(DEFAULTS, tsconfigOptions || {}, rawOptions) + const options = assign({}, DEFAULTS, tsconfigOptions || {}, rawOptions) // If `compiler` option changed based on tsconfig, re-load the compiler. - if (options.compiler !== inputOptions.compiler) { + if (options.compiler !== compilerName) { ({ compiler, ts } = loadCompiler(options.compiler)) } @@ -850,18 +836,18 @@ function fixConfig (ts: TSCommon, config: _ts.ParsedCommandLine) { } /** - * Load TypeScript configuration. Returns both a parsed typescript config and - * any ts-node options specified in the config file. + * Load TypeScript configuration. Returns the parsed TypeScript config and + * any `ts-node` options specified in the config file. */ function readConfig ( cwd: string, ts: TSCommon, - options: CreateOptions + rawOptions: CreateOptions ): { - /** Parsed TypeScript configuration */ + // Parsed TypeScript configuration. config: _ts.ParsedCommandLine - /** ts-node options pulled from tsconfig */ - options?: TsConfigOptions + // Options pulled from `tsconfig.json`. + options: TsConfigOptions } { let config: any = { compilerOptions: {} } let basePath = cwd @@ -872,7 +858,7 @@ function readConfig ( readFile = ts.sys.readFile, skipProject = DEFAULTS.skipProject, project = DEFAULTS.project - } = options + } = rawOptions // Read project configuration when available. if (!skipProject) { @@ -885,7 +871,10 @@ function readConfig ( // Return diagnostics. if (result.error) { - return { config: { errors: [result.error], fileNames: [], options: {} } } + return { + config: { errors: [result.error], fileNames: [], options: {} }, + options: {} + } } config = result.config @@ -894,13 +883,11 @@ function readConfig ( } // Fix ts-node options that come from tsconfig.json - const tsconfigOptions: TsConfigOptions = { - ...config['ts-node'] - } + const tsconfigOptions: TsConfigOptions = Object.assign({}, config['ts-node']) // Remove resolution of "files". - const filesOption = defaultValue(DEFAULTS.files, tsconfigOptions.files, options.files) - if (!filesOption) { + const files = rawOptions.files ?? tsconfigOptions.files ?? DEFAULTS.files + if (!files) { config.files = [] config.include = [] } @@ -908,10 +895,10 @@ function readConfig ( // Override default configuration options `ts-node` requires. config.compilerOptions = Object.assign( {}, - DEFAULTS.compilerOptions, config.compilerOptions, - config['ts-node']?.compilerOptions, - options.compilerOptions, + DEFAULTS.compilerOptions, + tsconfigOptions.compilerOptions, + rawOptions.compilerOptions, TS_NODE_COMPILER_OPTIONS )