diff --git a/src/transformers/typescript.ts b/src/transformers/typescript.ts index 74bcc9b9..a2fea144 100644 --- a/src/transformers/typescript.ts +++ b/src/transformers/typescript.ts @@ -1,4 +1,4 @@ -import { dirname } from 'path'; +import { dirname, isAbsolute, join } from 'path'; import ts from 'typescript'; @@ -53,6 +53,53 @@ const importTransformer: ts.TransformerFactory = (context) => { return (node) => ts.visitNode(node, visit); }; +export function loadTsconfig( + compilerOptionsJSON: any, + filename: string, + tsOptions: Options.Typescript, +) { + if (typeof tsOptions.tsconfigFile === 'boolean') { + return { errors: [], options: compilerOptionsJSON }; + } + + let basePath = process.cwd(); + + const fileDirectory = (tsOptions.tsconfigDirectory || + dirname(filename)) as string; + + let tsconfigFile = + tsOptions.tsconfigFile || + ts.findConfigFile(fileDirectory, ts.sys.fileExists); + + tsconfigFile = isAbsolute(tsconfigFile) + ? tsconfigFile + : join(basePath, tsconfigFile); + + basePath = dirname(tsconfigFile); + + const { error, config } = ts.readConfigFile(tsconfigFile, ts.sys.readFile); + + if (error) { + throw new Error(formatDiagnostics(error, basePath)); + } + + // Do this so TS will not search for initial files which might take a while + config.include = []; + + let { errors, options } = ts.parseJsonConfigFileContent( + config, + ts.sys, + basePath, + compilerOptionsJSON, + tsconfigFile, + ); + + // Filter out "no files found error" + errors = errors.filter((d) => d.code !== 18003); + + return { errors, options }; +} + const transformer: Transformer = ({ content, filename, @@ -64,38 +111,14 @@ const transformer: Transformer = ({ target: 'es6', }; - let basePath = process.cwd(); - - if (options.tsconfigFile !== false || options.tsconfigDirectory) { - const fileDirectory = (options.tsconfigDirectory || - dirname(filename)) as string; - - const tsconfigFile = - options.tsconfigFile || - ts.findConfigFile(fileDirectory, ts.sys.fileExists); - - if (typeof tsconfigFile === 'string') { - basePath = dirname(tsconfigFile); - - const { error, config } = ts.readConfigFile( - tsconfigFile, - ts.sys.readFile, - ); - - if (error) { - throw new Error(formatDiagnostics(error, basePath)); - } - - Object.assign(compilerOptionsJSON, config.compilerOptions); - } - } + const basePath = process.cwd(); Object.assign(compilerOptionsJSON, options.compilerOptions); - const { - errors, - options: convertedCompilerOptions, - } = ts.convertCompilerOptionsFromJson(compilerOptionsJSON, basePath); + const { errors, options: convertedCompilerOptions } = + options.tsconfigFile !== false || options.tsconfigDirectory + ? loadTsconfig(compilerOptionsJSON, filename, options) + : ts.convertCompilerOptionsFromJson(compilerOptionsJSON, basePath); if (errors.length) { throw new Error(formatDiagnostics(errors, basePath)); diff --git a/test/fixtures/tsconfig.extends1.json b/test/fixtures/tsconfig.extends1.json new file mode 100644 index 00000000..5abf2235 --- /dev/null +++ b/test/fixtures/tsconfig.extends1.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.extends2.json", + "compilerOptions": { + "esModuleInterop": true, + } +} diff --git a/test/fixtures/tsconfig.extends2.json b/test/fixtures/tsconfig.extends2.json new file mode 100644 index 00000000..b767cba7 --- /dev/null +++ b/test/fixtures/tsconfig.extends2.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "skipLibCheck": false, + } +} diff --git a/test/transformers/typescript.test.ts b/test/transformers/typescript.test.ts index 0f9efef8..95342039 100644 --- a/test/transformers/typescript.test.ts +++ b/test/transformers/typescript.test.ts @@ -3,8 +3,14 @@ import { resolve } from 'path'; import type { Diagnostic } from 'typescript'; import sveltePreprocess from '../../src'; +import { loadTsconfig } from '../../src/transformers/typescript'; import type { Processed } from '../../src/types'; -import { preprocess, getFixtureContent, spyConsole } from '../utils'; +import { + preprocess, + getFixtureContent, + spyConsole, + getTestAppFilename, +} from '../utils'; spyConsole({ silent: true }); @@ -103,5 +109,17 @@ describe('transformer - typescript', () => { return expect(code).toContain(getFixtureContent('script.js')); }); + + it('supports extends field', () => { + const { options } = loadTsconfig({}, getTestAppFilename(), { + tsconfigFile: './test/fixtures/tsconfig.extends1.json', + }); + + expect(options).toMatchObject({ + module: 5, + skipLibCheck: false, + esModuleInterop: true, + }); + }); }); });