@typed/test
Version:
Testing made simple.
67 lines (54 loc) • 1.97 kB
text/typescript
import fs from 'fs'
import { basename, dirname, join } from 'path'
import {
CompilerOptions,
convertCompilerOptionsFromJson,
findConfigFile,
parseConfigFileTextToJson,
} from 'typescript'
import { diagnosticToString } from './diagnosticToString'
export type TsConfig = {
compilerOptions: CompilerOptions
configPath: string
extends?: string | string[]
files?: string[]
include?: string[]
exclude?: string[]
}
export function findTsConfig(cwd: string = process.cwd()): TsConfig {
const configPath = findConfigFile(cwd, (fileName: string) => fs.existsSync(fileName))
if (!configPath) {
throw new Error('Unable to find TypeScript configuration')
}
const baseConfig = parseConfigFile(cwd, configPath)
if (baseConfig.extends) {
const extensions = Array.isArray(baseConfig.extends) ? baseConfig.extends : [baseConfig.extends]
const extendedConfigPaths = extensions.map(ext => join(dirname(configPath), ext))
const extendedConfigs = extendedConfigPaths.map(path => parseConfigFile(cwd, path))
if (extendedConfigs.length === 1) {
return mergeConfigs(baseConfig, extendedConfigs[0])
}
return extendedConfigs.reduceRight(mergeConfigs, baseConfig)
}
return baseConfig
}
function mergeConfigs(base: TsConfig, extension: TsConfig): TsConfig {
return {
...extension,
...base,
compilerOptions: {
...extension.compilerOptions,
...base.compilerOptions,
},
}
}
function parseConfigFile(cwd: string, filePath: string): TsConfig {
const fileName = basename(filePath)
const contents = fs.readFileSync(filePath).toString()
const { config } = parseConfigFileTextToJson(filePath, contents)
const { options, errors } = convertCompilerOptionsFromJson(config.compilerOptions, cwd, fileName)
if (errors && errors.length > 0) {
throw new Error(errors.map(x => diagnosticToString(x, cwd)).join('\n'))
}
return { ...config, compilerOptions: options, configPath: filePath }
}