Skip to content

Commit

Permalink
fix(next): respect extends in tsconfig with exclude and include (#16619)
Browse files Browse the repository at this point in the history
  • Loading branch information
calmonr committed Jan 24, 2021
1 parent 5baedf5 commit 783b9d8
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 9 deletions.
18 changes: 9 additions & 9 deletions packages/next/lib/typescript/writeConfigurationDefaults.ts
Expand Up @@ -95,16 +95,16 @@ export async function writeConfigurationDefaults(
}

const desiredCompilerOptions = getDesiredCompilerOptions(ts)
const effectiveConfiguration = await getTypeScriptConfiguration(
ts,
tsConfigPath
)
const {
options: tsOptions,
raw: rawConfig,
} = await getTypeScriptConfiguration(ts, tsConfigPath)

const userTsConfigContent = await fs.readFile(tsConfigPath, {
encoding: 'utf8',
})
const userTsConfig = CommentJson.parse(userTsConfigContent)
if (userTsConfig.compilerOptions == null) {
if (userTsConfig.compilerOptions == null && !('extends' in rawConfig)) {
userTsConfig.compilerOptions = {}
isFirstTimeSetup = true
}
Expand All @@ -114,14 +114,14 @@ export async function writeConfigurationDefaults(
for (const optionKey of Object.keys(desiredCompilerOptions)) {
const check = desiredCompilerOptions[optionKey]
if ('suggested' in check) {
if (!(optionKey in effectiveConfiguration.options)) {
if (!(optionKey in tsOptions)) {
userTsConfig.compilerOptions[optionKey] = check.suggested
suggestedActions.push(
chalk.cyan(optionKey) + ' was set to ' + chalk.bold(check.suggested)
)
}
} else if ('value' in check) {
const ev = effectiveConfiguration.options[optionKey]
const ev = tsOptions[optionKey]
if (
!('parsedValues' in check
? check.parsedValues?.includes(ev)
Expand All @@ -143,7 +143,7 @@ export async function writeConfigurationDefaults(
}
}

if (userTsConfig.include == null) {
if (!('include' in rawConfig)) {
userTsConfig.include = ['next-env.d.ts', '**/*.ts', '**/*.tsx']
suggestedActions.push(
chalk.cyan('include') +
Expand All @@ -152,7 +152,7 @@ export async function writeConfigurationDefaults(
)
}

if (userTsConfig.exclude == null) {
if (!('exclude' in rawConfig)) {
userTsConfig.exclude = ['node_modules']
suggestedActions.push(
chalk.cyan('exclude') + ' was set to ' + chalk.bold(`['node_modules']`)
Expand Down
54 changes: 54 additions & 0 deletions test/integration/tsconfig-verifier/test/index.test.js
Expand Up @@ -10,13 +10,16 @@ jest.setTimeout(1000 * 60 * 5)
describe('tsconfig.json verifier', () => {
const appDir = path.join(__dirname, '../')
const tsConfig = path.join(appDir, 'tsconfig.json')
const tsConfigBase = path.join(appDir, 'tsconfig.base.json')

beforeEach(async () => {
await remove(tsConfig)
await remove(tsConfigBase)
})

afterEach(async () => {
await remove(tsConfig)
await remove(tsConfigBase)
})

it('Creates a default tsconfig.json when one is missing', async () => {
Expand Down Expand Up @@ -258,4 +261,55 @@ describe('tsconfig.json verifier', () => {
"
`)
})

it('allows you to extend another configuration file', async () => {
expect(await exists(tsConfig)).toBe(false)
expect(await exists(tsConfigBase)).toBe(false)

await writeFile(
tsConfigBase,
`
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
`
)
await new Promise((resolve) => setTimeout(resolve, 500))

await writeFile(tsConfig, `{ "extends": "./tsconfig.base.json" }`)
await new Promise((resolve) => setTimeout(resolve, 500))

const { code } = await nextBuild(appDir)
expect(code).toBe(0)

expect(await readFile(tsConfig, 'utf8')).toMatchInlineSnapshot(
`"{ \\"extends\\": \\"./tsconfig.base.json\\" }"`
)
})
})

0 comments on commit 783b9d8

Please sign in to comment.