Skip to content

Commit

Permalink
feat: add implicit compilerOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
privatenumber committed Jan 21, 2025
1 parent b671a94 commit 865dd9a
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 88 deletions.
163 changes: 163 additions & 0 deletions src/parse-tsconfig/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,167 @@ const compilerFieldsWithConfigDir = [
'tsBuildInfoFile',
] as const;

const normalizeCompilerOptions = (
compilerOptions: TsConfigJson.CompilerOptions,
) => {
if (compilerOptions.strict) {
const strictOptions = [
'noImplicitAny',
'noImplicitThis',
'strictNullChecks',
'strictFunctionTypes',
'strictBindCallApply',
'strictPropertyInitialization',
'strictBuiltinIteratorReturn',
'alwaysStrict',
'useUnknownInCatchVariables',
] as const;

for (const key of strictOptions) {
if (compilerOptions[key] === undefined) {
compilerOptions[key] = true;
}
}
}

if (compilerOptions.target) {
let target = compilerOptions.target.toLowerCase() as TsConfigJson.CompilerOptions.Target;

if (target === 'es2015') {
target = 'es6';
}

// Lower case
compilerOptions.target = target;

if (target === 'esnext') {
compilerOptions.module ??= 'es6';
compilerOptions.moduleResolution ??= 'classic';
compilerOptions.useDefineForClassFields ??= true;
}

if (
target === 'es6'
|| target === 'es2016'
|| target === 'es2017'
|| target === 'es2018'
|| target === 'es2019'
|| target === 'es2020'
|| target === 'es2021'
|| target === 'es2022'
|| target === 'es2023'
|| target === 'es2024'
) {
compilerOptions.module ??= 'es6';
compilerOptions.moduleResolution ??= 'classic';
}

if (
target === 'es2022'
|| target === 'es2023'
|| target === 'es2024'
) {
compilerOptions.useDefineForClassFields ??= true;
}
}

if (compilerOptions.module) {
let module = compilerOptions.module.toLowerCase() as TsConfigJson.CompilerOptions.Module;

if (module === 'es2015') {
module = 'es6';
}

compilerOptions.module = module;

if (
module === 'es6'
|| module === 'es2020'
|| module === 'es2022'
|| module === 'esnext'
|| module === 'none'
|| module === 'system'
|| module === 'umd'
|| module === 'amd'
) {
compilerOptions.moduleResolution ??= 'classic';
}

if (module === 'system') {
compilerOptions.allowSyntheticDefaultImports ??= true;
}

if (
module === 'node16'
|| module === 'nodenext'
|| module === 'preserve'
) {
compilerOptions.esModuleInterop ??= true;
compilerOptions.allowSyntheticDefaultImports ??= true;
}

if (
module === 'node16'
|| module === 'nodenext'
) {
compilerOptions.moduleDetection ??= 'force';
compilerOptions.useDefineForClassFields ??= true;
}

if (module === 'node16') {
compilerOptions.target ??= 'es2022';
compilerOptions.moduleResolution ??= 'node16';
}

if (module === 'nodenext') {
compilerOptions.target ??= 'esnext';
compilerOptions.moduleResolution ??= 'nodenext';
}

if (module === 'preserve') {
compilerOptions.moduleResolution ??= 'bundler';
}
}

if (compilerOptions.moduleResolution) {
let moduleResolution = compilerOptions.moduleResolution.toLowerCase() as
TsConfigJson.CompilerOptions.ModuleResolution;

if (moduleResolution === 'node') {
moduleResolution = 'node10';
}

compilerOptions.moduleResolution = moduleResolution;

if (
moduleResolution === 'node16'
|| moduleResolution === 'nodenext'
|| moduleResolution === 'bundler'
) {
compilerOptions.resolvePackageJsonExports ??= true;
compilerOptions.resolvePackageJsonImports ??= true;
}

if (moduleResolution === 'bundler') {
compilerOptions.allowSyntheticDefaultImports ??= true;
compilerOptions.resolveJsonModule ??= true;
}
}

if (compilerOptions.esModuleInterop) {
compilerOptions.allowSyntheticDefaultImports ??= true;
}

if (compilerOptions.verbatimModuleSyntax) {
compilerOptions.isolatedModules ??= true;
compilerOptions.preserveConstEnums ??= true;
}

if (compilerOptions.isolatedModules) {
compilerOptions.preserveConstEnums ??= true;
}
};

/**
* Parses a tsconfig file at a given path
*
Expand Down Expand Up @@ -299,6 +460,8 @@ export const parseTsconfig = (
);
}
}

normalizeCompilerOptions(compilerOptions);
}

for (const property of filesProperties) {
Expand Down
Empty file added tests/fixtures/yarn-pnp/a.ts
Empty file.
22 changes: 7 additions & 15 deletions tests/fixtures/yarn-pnp/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
const { parseTsconfig } = require('get-tsconfig');
const tests = [
() => parseTsconfig('./tsconfig.package.json'),
() => parseTsconfig('./tsconfig.package-path.json'),
() => parseTsconfig('./tsconfig.package-path-directory.json'),
() => parseTsconfig('./tsconfig.org-package.json'),
() => parseTsconfig('./tsconfig.missing-extends.json'),
() => parseTsconfig('./tsconfig.invalid-extends.json'),
];

for (const test of tests) {
try {
console.log(test());
} catch (error) {
console.log('Error:', error.message);
process.exitCode = 1;
}
const tsconfigPath = process.argv[2];

try {
const parsed = parseTsconfig(tsconfigPath);
console.log(JSON.stringify(parsed));
} catch (error) {
console.error(error);
}
25 changes: 21 additions & 4 deletions tests/specs/get-tsconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'node:path';
import { testSuite, expect } from 'manten';
import { createFixture } from 'fs-fixture';
import slash from 'slash';
import { getTscTsconfig } from '../utils.js';
import { getTsconfig } from '#get-tsconfig';

const compilerOptions = {
Expand Down Expand Up @@ -33,48 +34,64 @@ export default testSuite(({ describe }) => {
test('from directory path', async () => {
await using fixture = await createFixture({
'tsconfig.json': tsconfigJson,
'a.ts': '',
});

const expected = await getTscTsconfig(fixture.path);
delete expected.files;

const tsconfig = getTsconfig(fixture.path);
expect(tsconfig).toStrictEqual({
path: slash(fixture.getPath('tsconfig.json')),
config: { compilerOptions },
config: expected,
});
});

test('from index.js path', async () => {
await using fixture = await createFixture({
'tsconfig.json': tsconfigJson,
'a.ts': '',
});

const expected = await getTscTsconfig(fixture.path);
delete expected.files;

const tsconfig = getTsconfig(fixture.getPath('index.js'));
expect(tsconfig).toStrictEqual({
path: slash(fixture.getPath('tsconfig.json')),
config: { compilerOptions },
config: expected,
});
});

test('custom name', async () => {
const customName = 'tsconfig-custom-name.json';
await using fixture = await createFixture({
[customName]: tsconfigJson,
'a.ts': '',
});

const expected = await getTscTsconfig(fixture.path, customName);
delete expected.files;

const tsconfig = getTsconfig(fixture.path, customName);
expect(tsconfig).toStrictEqual({
path: slash(path.join(fixture.path, customName)),
config: { compilerOptions },
config: expected,
});
});

test('cache', async () => {
await using fixture = await createFixture({
'tsconfig.json': tsconfigJson,
'a.ts': '',
});

const expected = await getTscTsconfig(fixture.path);
delete expected.files;

const expectedResult = {
path: slash(fixture.getPath('tsconfig.json')),
config: { compilerOptions },
config: expected,
};

const cache = new Map();
Expand Down
7 changes: 3 additions & 4 deletions tests/specs/parse-tsconfig/extends/merges.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ export default testSuite(({ describe }) => {

const tsconfig = parseTsconfig(fixture.getPath('tsconfig.json'));

// TODO: TS 5.5 --showConfig returns extra default fields
expect(expectedTsconfig).toMatchObject(tsconfig);
expect(expectedTsconfig).toStrictEqual(tsconfig);
});

describe('files', ({ test }) => {
Expand Down Expand Up @@ -424,8 +423,8 @@ export default testSuite(({ describe }) => {
delete expectedTsconfig.files;

const tsconfig = parseTsconfig(fixture.getPath('tsconfig.json'));
// TODO: TS 5.5 --showConfig returns extra default fields
expect(expectedTsconfig).toMatchObject(tsconfig);

expect(expectedTsconfig).toStrictEqual(tsconfig);
});

test('watchOptions', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export default testSuite(({ describe }) => {
delete expectedTsconfig.files;

const tsconfig = parseTsconfig(fixture.getPath('tsconfig.json'));
// TODO: TS 5.5 --showConfig returns extra default fields
expect(expectedTsconfig).toMatchObject(tsconfig);

expect(expectedTsconfig).toStrictEqual(tsconfig);
});

test('no extension', async () => {
Expand All @@ -45,8 +45,8 @@ export default testSuite(({ describe }) => {
delete expectedTsconfig.files;

const tsconfig = parseTsconfig(fixture.getPath('tsconfig.json'));
// TODO: TS 5.5 --showConfig returns extra default fields
expect(expectedTsconfig).toMatchObject(tsconfig);

expect(expectedTsconfig).toStrictEqual(tsconfig);
});

test('arbitrary extension', async () => {
Expand All @@ -67,8 +67,8 @@ export default testSuite(({ describe }) => {
delete expectedTsconfig.files;

const tsconfig = parseTsconfig(fixture.getPath('tsconfig.json'));
// TODO: TS 5.5 --showConfig returns extra default fields
expect(expectedTsconfig).toMatchObject(tsconfig);

expect(expectedTsconfig).toStrictEqual(tsconfig);
});
});
});
Loading

0 comments on commit 865dd9a

Please sign in to comment.