tsconfig.ts•1.89 kB
import { inspect } from 'node:util'
import type {
convertCompilerOptionsFromJson,
createProgram,
readConfigFile,
sys,
CompilerOptions as TSCompilerOptions,
} from 'typescript'
export type { TSCompilerOptions }
interface TSModule {
readConfigFile: typeof readConfigFile
convertCompilerOptionsFromJson: typeof convertCompilerOptionsFromJson
sys: typeof sys
createProgram: typeof createProgram
}
/**
* TypeScript helpers. This is a class so that we can dynamically import the TypeScript module
* to reduce runx start time for commands that don't use the typescript package.
*
* @example
*
* ```ts
* const tsHelpers = await new TSHelpers().init()
* const { ts } = tsHelpers
* const tsConfig = tsHelpers.getTSConfig()
* ts.createProgram(entryPoints, tsConfig).emit()
* ```
*/
export class TSHelpers {
#ts: TSModule | undefined
public get ts(): TSModule {
if (!this.#ts) {
throw new Error('TSHelpers not initialized. Call init() first.')
}
return this.#ts
}
async init(): Promise<TSHelpers> {
this.#ts = (await import('typescript')) as TSModule
return this
}
getTSConfig(configPath = 'tsconfig.json'): TSCompilerOptions {
const jsonCompopts = this.getCompilerOptionsJSONFollowExtends(configPath)
const tmp = this.ts.convertCompilerOptionsFromJson(jsonCompopts, '')
if (tmp.errors.length > 0) {
throw new Error(`failed parse config: ${inspect(tmp)}`)
}
const tsCompopts: TSCompilerOptions = tmp.options
return tsCompopts
}
getCompilerOptionsJSONFollowExtends(configPath: string): {
[key: string]: unknown
} {
let compopts = {}
const config = this.ts.readConfigFile(configPath, this.ts.sys.readFile).config
if (config.extends !== undefined) {
const rqrpath = require.resolve(config.extends)
compopts = this.getCompilerOptionsJSONFollowExtends(rqrpath)
}
return {
...compopts,
...config.compilerOptions,
}
}
}