1d8009c4bSEvan Baconimport path from 'path'; 2d8009c4bSEvan Baconimport resolveFrom from 'resolve-from'; 3d8009c4bSEvan Bacon 4d8009c4bSEvan Baconexport function evaluateTsConfig(ts: typeof import('typescript'), tsConfigPath: string) { 5d8009c4bSEvan Bacon const formatDiagnosticsHost: import('typescript').FormatDiagnosticsHost = { 6d8009c4bSEvan Bacon getNewLine: () => require('os').EOL, 7d8009c4bSEvan Bacon getCurrentDirectory: ts.sys.getCurrentDirectory, 8d8009c4bSEvan Bacon getCanonicalFileName: (fileName: string) => fileName, 9d8009c4bSEvan Bacon }; 10d8009c4bSEvan Bacon 11d8009c4bSEvan Bacon try { 12d8009c4bSEvan Bacon const { config, error } = ts.readConfigFile(tsConfigPath, ts.sys.readFile); 13d8009c4bSEvan Bacon 14d8009c4bSEvan Bacon if (error) { 15d8009c4bSEvan Bacon throw new Error(ts.formatDiagnostic(error, formatDiagnosticsHost)); 16d8009c4bSEvan Bacon } 17d8009c4bSEvan Bacon 18d8009c4bSEvan Bacon const jsonFileContents = ts.parseJsonConfigFileContent( 19d8009c4bSEvan Bacon config, 20d8009c4bSEvan Bacon { 21d8009c4bSEvan Bacon ...ts.sys, 22d8009c4bSEvan Bacon readDirectory: (_, ext) => [ext ? `file${ext[0]}` : `file.ts`], 23d8009c4bSEvan Bacon }, 24d8009c4bSEvan Bacon path.dirname(tsConfigPath) 25d8009c4bSEvan Bacon ); 26d8009c4bSEvan Bacon 27d8009c4bSEvan Bacon if (jsonFileContents.errors) { 28d8009c4bSEvan Bacon // filter out "no inputs were found in config file" error 29d8009c4bSEvan Bacon jsonFileContents.errors = jsonFileContents.errors.filter(({ code }) => code !== 18003); 30d8009c4bSEvan Bacon } 31d8009c4bSEvan Bacon 32d8009c4bSEvan Bacon if (jsonFileContents.errors?.length) { 33d8009c4bSEvan Bacon throw new Error(ts.formatDiagnostic(jsonFileContents.errors[0], formatDiagnosticsHost)); 34d8009c4bSEvan Bacon } 35d8009c4bSEvan Bacon 36*1117330aSMark Lawlor return { compilerOptions: jsonFileContents.options, raw: config.raw }; 37d8009c4bSEvan Bacon } catch (error: any) { 38d8009c4bSEvan Bacon if (error?.name === 'SyntaxError') { 39d8009c4bSEvan Bacon throw new Error('tsconfig.json is invalid:\n' + (error.message ?? '')); 40d8009c4bSEvan Bacon } 41d8009c4bSEvan Bacon throw error; 42d8009c4bSEvan Bacon } 43d8009c4bSEvan Bacon} 44d8009c4bSEvan Bacon 45d8009c4bSEvan Baconexport function importTypeScriptFromProjectOptionally( 46d8009c4bSEvan Bacon projectRoot: string 47d8009c4bSEvan Bacon): typeof import('typescript') | null { 48d8009c4bSEvan Bacon const resolvedPath = resolveFrom.silent(projectRoot, 'typescript'); 49d8009c4bSEvan Bacon if (!resolvedPath) { 50d8009c4bSEvan Bacon return null; 51d8009c4bSEvan Bacon } 52d8009c4bSEvan Bacon return require(resolvedPath); 53d8009c4bSEvan Bacon} 54