From de5f8783d7230d1ea7f5aa6ec59fae8e5555ebf1 Mon Sep 17 00:00:00 2001 From: Spencer Snyder Date: Thu, 25 Aug 2022 12:17:26 -0400 Subject: [PATCH] Ensure tsconfig lookups work as expected (#680) --- .gitignore | 2 ++ lib/options-manager.js | 10 +++--- .../@sindresorhus/tsconfig/package.json | 26 ++++++++++++++ .../@sindresorhus/tsconfig/tsconfig.json | 35 +++++++++++++++++++ .../typescript/extends-module/package.json | 3 ++ .../typescript/extends-module/tsconfig.json | 3 ++ test/options-manager.js | 9 +++++ 7 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/package.json create mode 100644 test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/tsconfig.json create mode 100644 test/fixtures/typescript/extends-module/package.json create mode 100644 test/fixtures/typescript/extends-module/tsconfig.json diff --git a/.gitignore b/.gitignore index cc99dbd8..f02242b8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,7 @@ node_modules yarn.lock !test/fixtures/project/node_modules test/fixtures/project/node_modules/.cache +!test/fixtures/typescript/extends-module/node_modules +test/fixtures/typescript/extends-module/node_modules/.cache .nyc_output coverage diff --git a/lib/options-manager.js b/lib/options-manager.js index 2a59705c..c028fc87 100644 --- a/lib/options-manager.js +++ b/lib/options-manager.js @@ -2,6 +2,7 @@ import {existsSync, promises as fs} from 'node:fs'; import process from 'node:process'; import os from 'node:os'; import path from 'node:path'; +import {createRequire} from 'node:module'; import arrify from 'arrify'; import {mergeWith, flow, pick} from 'lodash-es'; import {findUpSync} from 'find-up'; @@ -643,11 +644,10 @@ async function recursiveBuildTsConfig(tsConfig, tsConfigPath) { } // If any of the following are missing, then we need to look up the base config as it could apply - const basePath = path.isAbsolute(tsConfig.extends) - ? tsConfig.extends - : path.resolve(path.dirname(tsConfigPath), tsConfig.extends); - - const baseTsConfig = await readJson(basePath); + // Use node resolution + const require = createRequire(tsConfigPath); + const basePath = require.resolve(tsConfig.extends); + const baseTsConfig = JSON5.parse(await fs.readFile(basePath)); delete tsConfig.extends; diff --git a/test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/package.json b/test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/package.json new file mode 100644 index 00000000..918d2924 --- /dev/null +++ b/test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/package.json @@ -0,0 +1,26 @@ +{ + "name": "@sindresorhus/tsconfig", + "version": "3.0.1", + "description": "Shared TypeScript config for my projects", + "license": "MIT", + "repository": "sindresorhus/tsconfig", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "https://sindresorhus.com" + }, + "main": "tsconfig.json", + "engines": { + "node": ">=14" + }, + "files": [ + "tsconfig.json" + ], + "keywords": [ + "tsconfig", + "typescript", + "ts", + "config", + "configuration" + ] +} diff --git a/test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/tsconfig.json b/test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/tsconfig.json new file mode 100644 index 00000000..0612e961 --- /dev/null +++ b/test/fixtures/typescript/extends-module/node_modules/@sindresorhus/tsconfig/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + // Disabled because of https://github.com/Microsoft/TypeScript/issues/29172 + // "outDir": "dist", + + "module": "node16", + "moduleResolution": "node16", + "moduleDetection": "force", + "target": "ES2020", // Node.js 14 + "lib": [ + "DOM", + "DOM.Iterable", + "ES2020" + ], + "allowSyntheticDefaultImports": true, // To provide backwards compatibility, Node.js allows you to import most CommonJS packages with a default import. This flag tells TypeScript that it's okay to use import on CommonJS modules. + "resolveJsonModule": false, // ESM doesn't yet support JSON modules. + "jsx": "react", + "declaration": true, + "pretty": true, + "newLine": "lf", + "stripInternal": true, + "strict": true, + "noImplicitReturns": true, + "noImplicitOverride": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noPropertyAccessFromIndexSignature": true, + "noEmitOnError": true, + "useDefineForClassFields": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true + } +} diff --git a/test/fixtures/typescript/extends-module/package.json b/test/fixtures/typescript/extends-module/package.json new file mode 100644 index 00000000..90bd27c7 --- /dev/null +++ b/test/fixtures/typescript/extends-module/package.json @@ -0,0 +1,3 @@ +{ + "xo": {} +} diff --git a/test/fixtures/typescript/extends-module/tsconfig.json b/test/fixtures/typescript/extends-module/tsconfig.json new file mode 100644 index 00000000..e4928276 --- /dev/null +++ b/test/fixtures/typescript/extends-module/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@sindresorhus/tsconfig" +} diff --git a/test/options-manager.js b/test/options-manager.js index 9eeef13d..80e614c4 100644 --- a/test/options-manager.js +++ b/test/options-manager.js @@ -671,6 +671,15 @@ test('mergeWithFileConfig: creates temp tsconfig if none present', async t => { t.deepEqual(options.tsConfig, TSCONFIG_DEFAULTS); }); +test('mergeWithFileConfig: tsconfig can properly extend configs in node_modules', async t => { + const cwd = path.resolve('fixtures', 'typescript', 'extends-module'); + const expectedConfigPath = path.join(cwd, 'tsconfig.json'); + const filePath = path.resolve(cwd, 'does-not-matter.ts'); + await t.notThrowsAsync(manager.mergeWithFileConfig({cwd, filePath})); + const {options} = await manager.mergeWithFileConfig({cwd, filePath}); + t.is(options.tsConfigPath, expectedConfigPath); +}); + test('applyOverrides', t => { t.deepEqual( manager.applyOverrides(