diff --git a/packages/plugin-dts/src/utils.ts b/packages/plugin-dts/src/utils.ts index 2a90cd524..e01e7c5fa 100644 --- a/packages/plugin-dts/src/utils.ts +++ b/packages/plugin-dts/src/utils.ts @@ -74,6 +74,15 @@ export async function pathExists(path: string): Promise { .catch(() => false); } +export async function isDirectory(filePath: string): Promise { + try { + const stat = await fsP.stat(filePath); + return stat.isDirectory(); + } catch { + return false; + } +} + export async function emptyDir(dir: string): Promise { if (!(await pathExists(dir))) { return; @@ -164,6 +173,27 @@ export async function addBannerAndFooter( } } +async function addExtension( + redirect: DtsRedirect, + dtsFile: string, + path: string, + extension: string, +): Promise { + if (!redirect.extension) { + return path; + } + + let redirectPath = path; + + // If the import path refers to a directory, it most likely actually refers to a `index.*` file due to Node's module resolution + if (await isDirectory(join(dirname(dtsFile), redirectPath))) { + // This uses `/` instead of `path.join` here because `join` removes potential "./" prefixes + redirectPath = `${redirectPath}/index`; + } + + return `${redirectPath}${extension}`; +} + export async function redirectDtsImports( dtsFile: string, dtsExtension: string, @@ -218,7 +248,7 @@ export async function redirectDtsImports( e: matchNode.range().end.index, }; }); - const extensions = dtsExtension + const extension = dtsExtension .replace(/\.d\.ts$/, '.js') .replace(/\.d\.cts$/, '.cjs') .replace(/\.d\.mts$/, '.mjs'); @@ -269,7 +299,7 @@ export async function redirectDtsImports( if (redirect.extension) { redirectImportPath = redirectImportPath.replace( /\.[^.]+$/, - extensions, + extension, ); } } @@ -278,15 +308,21 @@ export async function redirectDtsImports( absoluteImportPath && normalize(absoluteImportPath).startsWith(normalize(rootDir)) ) { - if (redirect.extension) { - redirectImportPath = `${redirectImportPath}${extensions}`; - } + redirectImportPath = await addExtension( + redirect, + dtsFile, + redirectImportPath, + extension, + ); } if (!absoluteImportPath && importPath.startsWith('.')) { - if (redirect.extension) { - redirectImportPath = `${redirectImportPath}${extensions}`; - } + redirectImportPath = await addExtension( + redirect, + dtsFile, + redirectImportPath, + extension, + ); } } diff --git a/tests/integration/redirect/dts.test.ts b/tests/integration/redirect/dts.test.ts index 6633c1c30..9ddf0dcde 100644 --- a/tests/integration/redirect/dts.test.ts +++ b/tests/integration/redirect/dts.test.ts @@ -16,6 +16,8 @@ test('redirect.dts default', async () => { import { logger } from '../../../../compile/rslog'; import { logRequest as logRequest2 } from '../logger'; export { logRequest, logRequest2, logger }; + ", + "/tests/integration/redirect/dts/dist/default/esm/foo/index.d.ts": "export type Barrel = string; ", "/tests/integration/redirect/dts/dist/default/esm/index.d.ts": "import { logRequest } from './logger'; import { logger } from '../../../compile/rslog'; @@ -24,6 +26,8 @@ test('redirect.dts default', async () => { export { logRequest, logger, type LoggerOptions, defaultOptions }; export type { Foo } from './types'; export type { Bar } from './types'; + export * from './foo'; + export * from './foo'; export * from './types'; export * from '../../../compile/rslog'; export * from './logger'; @@ -55,6 +59,8 @@ test('redirect.dts.path false', async () => { import { logger } from 'rslog'; import { logRequest as logRequest2 } from '../logger'; export { logRequest, logRequest2, logger }; + ", + "/tests/integration/redirect/dts/dist/path-false/esm/foo/index.d.ts": "export type Barrel = string; ", "/tests/integration/redirect/dts/dist/path-false/esm/index.d.ts": "import { logRequest } from '@src/logger'; import { logger } from 'rslog'; @@ -63,6 +69,8 @@ test('redirect.dts.path false', async () => { export { logRequest, logger, type LoggerOptions, defaultOptions }; export type { Foo } from '@src/types'; export type { Bar } from 'types'; + export * from './foo'; + export * from '@src/foo'; export * from './types'; export * from 'rslog'; export * from '@src/logger'; @@ -94,6 +102,8 @@ test('redirect.dts.extension true', async () => { import { logger } from '../../../../compile/rslog'; import { logRequest as logRequest2 } from '../logger.js'; export { logRequest, logRequest2, logger }; + ", + "/tests/integration/redirect/dts/dist/extension-true/esm/foo/index.d.ts": "export type Barrel = string; ", "/tests/integration/redirect/dts/dist/extension-true/esm/index.d.ts": "import { logRequest } from './logger.js'; import { logger } from '../../../compile/rslog'; @@ -102,6 +112,8 @@ test('redirect.dts.extension true', async () => { export { logRequest, logger, type LoggerOptions, defaultOptions }; export type { Foo } from './types.js'; export type { Bar } from './types.js'; + export * from './foo/index.js'; + export * from './foo/index.js'; export * from './types.js'; export * from '../../../compile/rslog'; export * from './logger.js'; @@ -133,6 +145,8 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => { import { logger } from '../../../../compile/rslog'; import { logRequest as logRequest2 } from '../logger.mjs'; export { logRequest, logRequest2, logger }; + ", + "/tests/integration/redirect/dts/dist/auto-extension-true/esm/foo/index.d.mts": "export type Barrel = string; ", "/tests/integration/redirect/dts/dist/auto-extension-true/esm/index.d.mts": "import { logRequest } from './logger.mjs'; import { logger } from '../../../compile/rslog'; @@ -141,6 +155,8 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => { export { logRequest, logger, type LoggerOptions, defaultOptions }; export type { Foo } from './types.mjs'; export type { Bar } from './types.mjs'; + export * from './foo/index.mjs'; + export * from './foo/index.mjs'; export * from './types.mjs'; export * from '../../../compile/rslog'; export * from './logger.mjs'; diff --git a/tests/integration/redirect/dts/src/foo/index.ts b/tests/integration/redirect/dts/src/foo/index.ts new file mode 100644 index 000000000..77a95f681 --- /dev/null +++ b/tests/integration/redirect/dts/src/foo/index.ts @@ -0,0 +1 @@ +export type Barrel = string; diff --git a/tests/integration/redirect/dts/src/index.ts b/tests/integration/redirect/dts/src/index.ts index a0a31097b..b4402c115 100644 --- a/tests/integration/redirect/dts/src/index.ts +++ b/tests/integration/redirect/dts/src/index.ts @@ -7,6 +7,8 @@ export { logRequest, logger, type LoggerOptions, defaultOptions }; export type { Foo } from '@src/types'; export type { Bar } from 'types'; +export * from './foo'; +export * from '@src/foo'; export * from './types'; export * from 'rslog'; export * from '@src/logger';