Skip to content

Commit

Permalink
Merge pull request #257 from timocov/mts-cts-issue204
Browse files Browse the repository at this point in the history
  • Loading branch information
timocov committed Aug 30, 2023
2 parents 93f5c79 + fa6eccf commit 9f346f9
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 16 deletions.
56 changes: 46 additions & 10 deletions src/compile-dts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as path from 'path';
import * as ts from 'typescript';

import { verboseLog, warnLog } from './logger';
Expand All @@ -12,6 +11,25 @@ export interface CompileDtsResult {
rootFilesRemapping: Map<string, string>;
}

const declarationExtsRemapping: Record<string, ts.Extension> = {
[ts.Extension.Js]: ts.Extension.Js,
[ts.Extension.Jsx]: ts.Extension.Jsx,
[ts.Extension.Json]: ts.Extension.Json,
[ts.Extension.TsBuildInfo]: ts.Extension.TsBuildInfo,
[ts.Extension.Mjs]: ts.Extension.Mjs,
[ts.Extension.Cjs]: ts.Extension.Cjs,

[ts.Extension.Ts]: ts.Extension.Dts,
[ts.Extension.Tsx]: ts.Extension.Dts,
[ts.Extension.Dts]: ts.Extension.Dts,

[ts.Extension.Mts]: ts.Extension.Dmts,
[ts.Extension.Dmts]: ts.Extension.Dmts,

[ts.Extension.Cts]: ts.Extension.Dcts,
[ts.Extension.Dcts]: ts.Extension.Dcts,
} satisfies Record<ts.Extension, ts.Extension>;

export function compileDts(rootFiles: readonly string[], preferredConfigPath?: string, followSymlinks: boolean = true): CompileDtsResult {
const compilerOptions = getCompilerOptions(rootFiles, preferredConfigPath);

Expand Down Expand Up @@ -41,13 +59,16 @@ export function compileDts(rootFiles: readonly string[], preferredConfigPath?: s
host.resolveModuleNameLiterals = (moduleLiterals: readonly ts.StringLiteralLike[], containingFile: string): ts.ResolvedModuleWithFailedLookupLocations[] => {
return moduleLiterals.map((moduleLiteral: ts.StringLiteralLike): ts.ResolvedModuleWithFailedLookupLocations => {
const resolvedModule = ts.resolveModuleName(moduleLiteral.text, containingFile, compilerOptions, host).resolvedModule;
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
if (resolvedModule && !resolvedModule.isExternalLibraryImport && resolvedModule.extension !== ts.Extension.Dts) {
resolvedModule.extension = ts.Extension.Dts;
if (resolvedModule && !resolvedModule.isExternalLibraryImport) {
const newExt = declarationExtsRemapping[resolvedModule.extension];

verboseLog(`Change module from .ts to .d.ts: ${resolvedModule.resolvedFileName}`);
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
if (newExt !== resolvedModule.extension) {
verboseLog(`Changing module from ${resolvedModule.extension} to ${newExt} for ${resolvedModule.resolvedFileName}`);

resolvedModule.resolvedFileName = changeExtensionToDts(resolvedModule.resolvedFileName);
resolvedModule.extension = newExt;
resolvedModule.resolvedFileName = changeExtensionToDts(resolvedModule.resolvedFileName);
}
}

return { resolvedModule };
Expand Down Expand Up @@ -82,13 +103,28 @@ export function compileDts(rootFiles: readonly string[], preferredConfigPath?: s
}

function changeExtensionToDts(fileName: string): string {
if (fileName.slice(-5) === '.d.ts') {
let ext: ts.Extension | undefined;

// `path.extname` doesn't handle `.d.ts` cases (it returns `.ts` instead of `.d.ts`)
if (fileName.endsWith(ts.Extension.Dts)) {
return fileName;
}

if (fileName.endsWith(ts.Extension.Cts)) {
ext = ts.Extension.Cts;
} else if (fileName.endsWith(ts.Extension.Mts)) {
ext = ts.Extension.Mts;
} else if (fileName.endsWith(ts.Extension.Ts)) {
ext = ts.Extension.Ts;
} else if (fileName.endsWith(ts.Extension.Tsx)) {
ext = ts.Extension.Tsx;
}

if (ext === undefined) {
return fileName;
}

// .ts, .tsx
const ext = path.extname(fileName);
return fileName.slice(0, -ext.length) + '.d.ts';
return fileName.slice(0, -ext.length) + declarationExtsRemapping[ext];
}

/**
Expand Down
32 changes: 26 additions & 6 deletions tests/e2e/all-test-cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,41 @@ function prepareString(str: string): string {
return str.trim().replace(/\r\n/g, '\n');
}

function findInputFile(testCaseDir: string): string {
const tsFilePath = path.join(testCaseDir, 'input.ts');
if (fs.existsSync(tsFilePath)) {
return tsFilePath;
}

const dtsFilePath = path.join(testCaseDir, 'input.d.ts');
if (fs.existsSync(dtsFilePath)) {
return dtsFilePath;
}

const mtsFilePath = path.join(testCaseDir, 'input.mts');
if (fs.existsSync(mtsFilePath)) {
return mtsFilePath;
}

const ctsFilePath = path.join(testCaseDir, 'input.cts');
if (fs.existsSync(ctsFilePath)) {
return ctsFilePath;
}

throw new Error(`Cannot find input file in ${testCaseDir}`);
}

function getTestCases(): TestCase[] {
return fs.readdirSync(testCasesDir)
.filter((filePath: string) => {
return isDirectory(filePath) && path.basename(filePath) !== 'node_modules';
})
.map((directoryName: string) => {
const testCaseDir = path.resolve(testCasesDir, directoryName);
const outputFileName = path.resolve(testCaseDir, 'output.d.ts');

const tsFilePath = path.relative(process.cwd(), path.resolve(testCaseDir, 'input.ts'));
const dtsFilePath = path.relative(process.cwd(), path.resolve(testCaseDir, 'input.d.ts'));

const inputFileName = fs.existsSync(tsFilePath) ? tsFilePath : dtsFilePath;
const inputFileName = findInputFile(testCaseDir);

assert(fs.existsSync(inputFileName), `Input file doesn't exist for ${directoryName}`);
const outputFileName = path.resolve(testCaseDir, 'output.d.ts');
assert(fs.existsSync(outputFileName), `Output file doesn't exist for ${directoryName}`);

const result: TestCase = {
Expand Down
5 changes: 5 additions & 0 deletions tests/e2e/test-cases/cts-extension/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TestCaseConfig } from '../../test-cases/test-case-config';

const config: TestCaseConfig = {};

export = config;
1 change: 1 addition & 0 deletions tests/e2e/test-cases/cts-extension/decl.d.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Decl = string;
1 change: 1 addition & 0 deletions tests/e2e/test-cases/cts-extension/file.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export interface Interface {}
6 changes: 6 additions & 0 deletions tests/e2e/test-cases/cts-extension/input.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Interface } from './file.cjs';
import { Decl } from './decl.cjs';

export interface ExportedInterface extends Interface {
foo: Decl;
}
8 changes: 8 additions & 0 deletions tests/e2e/test-cases/cts-extension/output.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface Interface {
}
export type Decl = string;
export interface ExportedInterface extends Interface {
foo: Decl;
}

export {};
5 changes: 5 additions & 0 deletions tests/e2e/test-cases/mts-extension/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TestCaseConfig } from '../../test-cases/test-case-config';

const config: TestCaseConfig = {};

export = config;
1 change: 1 addition & 0 deletions tests/e2e/test-cases/mts-extension/decl.d.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Decl = string;
1 change: 1 addition & 0 deletions tests/e2e/test-cases/mts-extension/file.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export interface Interface {}
6 changes: 6 additions & 0 deletions tests/e2e/test-cases/mts-extension/input.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Interface } from './file.mjs';
import { Decl } from './decl.mjs';

export interface ExportedInterface extends Interface {
foo: Decl;
}
8 changes: 8 additions & 0 deletions tests/e2e/test-cases/mts-extension/output.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface Interface {
}
export type Decl = string;
export interface ExportedInterface extends Interface {
foo: Decl;
}

export {};

0 comments on commit 9f346f9

Please sign in to comment.