Skip to content

Commit

Permalink
fix: allow extending multiple config files
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Jan 18, 2025
1 parent 5559a0a commit f1c0cf6
Showing 1 changed file with 54 additions and 36 deletions.
90 changes: 54 additions & 36 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export function readConfig(
}> = [];
let config: any = { compilerOptions: {} };
let basePath = cwd;
let configFilePath: string | undefined = undefined;
let rootConfigPath: string | undefined = undefined;
const projectSearchDir = resolve(cwd, rawApiOptions.projectSearchDir ?? cwd);

const {
Expand All @@ -170,62 +170,80 @@ export function readConfig(
if (project) {
const resolved = resolve(cwd, project);
const nested = join(resolved, 'tsconfig.json');
configFilePath = fileExists(nested) ? nested : resolved;
rootConfigPath = fileExists(nested) ? nested : resolved;
} else {
configFilePath = ts.findConfigFile(projectSearchDir, fileExists);
rootConfigPath = ts.findConfigFile(projectSearchDir, fileExists);
}

if (configFilePath) {
let pathToNextConfigInChain = configFilePath;
if (rootConfigPath) {
// If root extends [a, c] and a extends b, c extends d, then this array will look like:
// [root, c, d, a, b]
let configPaths = [rootConfigPath];
const tsInternals = createTsInternals(ts);
const errors: Array<_ts.Diagnostic> = [];

// Follow chain of "extends"
while (true) {
const result = ts.readConfigFile(pathToNextConfigInChain, readFile);
for (
let configPathIndex = 0;
configPathIndex < configPaths.length;
configPathIndex++
) {
const configPath = configPaths[configPathIndex];
const result = ts.readConfigFile(configPath, readFile);

// Return diagnostics.
if (result.error) {
return {
configFilePath,
configFilePath: rootConfigPath,
config: { errors: [result.error], fileNames: [], options: {} },
tsNodeOptionsFromTsconfig: {},
optionBasePaths: {},
};
}

const c = result.config;
const bp = dirname(pathToNextConfigInChain);
const bp = dirname(configPath);
configChain.push({
config: c,
basePath: bp,
configPath: pathToNextConfigInChain,
configPath: configPath,
});

if (c.extends == null) break;
const resolvedExtendedConfigPath = tsInternals.getExtendsConfigPath(
c.extends,
{
fileExists,
readDirectory: ts.sys.readDirectory,
readFile,
useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
trace: tsTrace,
},
bp,
errors,
(ts as unknown as TSInternal).createCompilerDiagnostic
);
if (errors.length) {
return {
configFilePath,
config: { errors, fileNames: [], options: {} },
tsNodeOptionsFromTsconfig: {},
optionBasePaths: {},
};
if (c.extends == null) continue;
const extendsArray = Array.isArray(c.extends) ? c.extends : [c.extends];
for (const e of extendsArray) {
const resolvedExtendedConfigPath = tsInternals.getExtendsConfigPath(
e,
{
fileExists,
readDirectory: ts.sys.readDirectory,
readFile,
useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
trace: tsTrace,
},
bp,
errors,
(ts as unknown as TSInternal).createCompilerDiagnostic
);
if (errors.length) {
return {
configFilePath: rootConfigPath,
config: { errors, fileNames: [], options: {} },
tsNodeOptionsFromTsconfig: {},
optionBasePaths: {},
};
}
if (resolvedExtendedConfigPath != null) {
// Tricky! If "extends" array is [a, c] then this will splice them into this order:
// [root, c, a]
// This is what we want.
configPaths.splice(
configPathIndex + 1,
0,
resolvedExtendedConfigPath
);
}
}
if (resolvedExtendedConfigPath == null) break;
pathToNextConfigInChain = resolvedExtendedConfigPath;
}

({ config, basePath } = configChain[0]);
Expand Down Expand Up @@ -277,7 +295,7 @@ export function readConfig(
rawApiOptions.files ?? tsNodeOptionsFromTsconfig.files ?? DEFAULTS.files;

// Only if a config file is *not* loaded, load an implicit configuration from @tsconfig/bases
const skipDefaultCompilerOptions = configFilePath != null;
const skipDefaultCompilerOptions = rootConfigPath != null;
const defaultCompilerOptionsForNodeVersion = skipDefaultCompilerOptions
? undefined
: {
Expand Down Expand Up @@ -316,12 +334,12 @@ export function readConfig(
},
basePath,
undefined,
configFilePath
rootConfigPath
)
);

return {
configFilePath,
configFilePath: rootConfigPath,
config: fixedConfig,
tsNodeOptionsFromTsconfig,
optionBasePaths,
Expand Down

0 comments on commit f1c0cf6

Please sign in to comment.