From 8354088614c0b0b9bb2f37d1d08fcd2e4234a781 Mon Sep 17 00:00:00 2001 From: Timeless0911 <1604889533@qq.com> Date: Mon, 21 Apr 2025 16:16:52 +0800 Subject: [PATCH 1/4] fix: dts redirect extension should add correctly --- packages/plugin-dts/src/utils.ts | 19 ++++- tests/integration/redirect/dts.test.ts | 85 +++++++++++++++++-- .../integration/redirect/dts/rslib.config.ts | 25 ++++-- tests/integration/redirect/dts/src/index.ts | 9 +- tests/integration/redirect/dts/src/types.ts | 4 + tests/integration/redirect/dts/tsconfig.json | 3 +- 6 files changed, 126 insertions(+), 19 deletions(-) diff --git a/packages/plugin-dts/src/utils.ts b/packages/plugin-dts/src/utils.ts index 703e55c3c..99eac3d9b 100644 --- a/packages/plugin-dts/src/utils.ts +++ b/packages/plugin-dts/src/utils.ts @@ -5,6 +5,7 @@ import path, { basename, dirname, extname, + isAbsolute, join, normalize, relative, @@ -185,10 +186,19 @@ async function addExtension( let redirectPath = path; + // Only add extension if redirectPath is an absolute or relative path + if ( + !isAbsolute(redirectPath) && + !redirectPath.startsWith('./') && + !redirectPath.startsWith('../') + ) { + return redirectPath; + } + // 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`; + redirectPath = `${redirectPath.replace(/\/+$/, '')}/index`; } return `${redirectPath}${extension}`; @@ -277,9 +287,12 @@ export async function redirectDtsImports( let redirectImportPath = importPath; if (absoluteImportPath && redirect.path) { - const isOutsideRootdir = !normalize(absoluteImportPath).startsWith( - normalize(rootDir) + path.sep, + const relativeRootDir = path.relative( + normalize(rootDir), + normalize(absoluteImportPath), ); + const isOutsideRootdir = + relativeRootDir.startsWith('..') || path.isAbsolute(relativeRootDir); if (isOutsideRootdir) { const relativePath = relative(dirname(dtsFile), absoluteImportPath); diff --git a/tests/integration/redirect/dts.test.ts b/tests/integration/redirect/dts.test.ts index 6450bc342..4b142c8dd 100644 --- a/tests/integration/redirect/dts.test.ts +++ b/tests/integration/redirect/dts.test.ts @@ -9,7 +9,7 @@ beforeAll(async () => { contents = (await buildAndGetResults({ fixturePath, type: 'dts' })).contents; }); -test('redirect.dts default', async () => { +test('redirect.dts default - redirect.dts.path: true with redirect.dts.extension: false', async () => { expect(contents.esm0).toMatchInlineSnapshot(` { "/tests/integration/redirect/dts/dist/default/esm/foo/foo.d.ts": "import { logRequest } from '../logger'; @@ -21,9 +21,10 @@ test('redirect.dts default', async () => { ", "/tests/integration/redirect/dts/dist/default/esm/index.d.ts": "import { logRequest } from './logger'; import { logger } from '../../../compile/rslog'; + import type { Baz } from './'; import type { LoggerOptions } from './types'; import { defaultOptions } from './types.js'; - export { logRequest, logger, type LoggerOptions, defaultOptions }; + export { type Baz as self, logRequest, logger, type LoggerOptions, defaultOptions, }; export type { Foo } from './types'; export type { Bar } from './types'; export * from './foo'; @@ -47,12 +48,15 @@ test('redirect.dts default', async () => { export interface Bar { bar: string; } + export interface Baz { + baz: string; + } ", } `); }); -test('redirect.dts.path false', async () => { +test('redirect.dts.path: false with redirect.dts.extension: false', async () => { expect(contents.esm1).toMatchInlineSnapshot(` { "/tests/integration/redirect/dts/dist/path-false/esm/foo/foo.d.ts": "import { logRequest } from '@src/logger'; @@ -64,9 +68,10 @@ test('redirect.dts.path false', async () => { ", "/tests/integration/redirect/dts/dist/path-false/esm/index.d.ts": "import { logRequest } from '@src/logger'; import { logger } from 'rslog'; + import type { Baz } from 'self-entry'; import type { LoggerOptions } from './types'; import { defaultOptions } from './types.js'; - export { logRequest, logger, type LoggerOptions, defaultOptions }; + export { type Baz as self, logRequest, logger, type LoggerOptions, defaultOptions, }; export type { Foo } from '@src/types'; export type { Bar } from 'types'; export * from './foo'; @@ -90,12 +95,15 @@ test('redirect.dts.path false', async () => { export interface Bar { bar: string; } + export interface Baz { + baz: string; + } ", } `); }); -test('redirect.dts.extension true', async () => { +test('redirect.dts.path: true with redirect.dts.extension: true', async () => { expect(contents.esm2).toMatchInlineSnapshot(` { "/tests/integration/redirect/dts/dist/extension-true/esm/foo/foo.d.ts": "import { logRequest } from '../logger.js'; @@ -107,9 +115,10 @@ test('redirect.dts.extension true', async () => { ", "/tests/integration/redirect/dts/dist/extension-true/esm/index.d.ts": "import { logRequest } from './logger.js'; import { logger } from '../../../compile/rslog'; + import type { Baz } from './index.js'; import type { LoggerOptions } from './types.js'; import { defaultOptions } from './types.js'; - export { logRequest, logger, type LoggerOptions, defaultOptions }; + export { type Baz as self, logRequest, logger, type LoggerOptions, defaultOptions, }; export type { Foo } from './types.js'; export type { Bar } from './types.js'; export * from './foo/index.js'; @@ -133,13 +142,63 @@ test('redirect.dts.extension true', async () => { export interface Bar { bar: string; } + export interface Baz { + baz: string; + } ", } `); }); -test('redirect.dts.extension true with dts.autoExtension true', async () => { +test('redirect.dts.path: false with dts.redirect.extension: true', async () => { expect(contents.esm3).toMatchInlineSnapshot(` + { + "/tests/integration/redirect/dts/dist/path-false-extension-true/esm/foo/foo.d.ts": "import { logRequest } from '@src/logger'; + import { logger } from 'rslog'; + import { logRequest as logRequest2 } from '../logger.js'; + export { logRequest, logRequest2, logger }; + ", + "/tests/integration/redirect/dts/dist/path-false-extension-true/esm/foo/index.d.ts": "export type Barrel = string; + ", + "/tests/integration/redirect/dts/dist/path-false-extension-true/esm/index.d.ts": "import { logRequest } from '@src/logger'; + import { logger } from 'rslog'; + import type { Baz } from 'self-entry'; + import type { LoggerOptions } from './types.js'; + import { defaultOptions } from './types.js'; + export { type Baz as self, logRequest, logger, type LoggerOptions, defaultOptions, }; + export type { Foo } from '@src/types'; + export type { Bar } from 'types'; + export * from './foo/index.js'; + export * from '@src/foo'; + export * from './types.js'; + export * from 'rslog'; + export * from '@src/logger'; + ", + "/tests/integration/redirect/dts/dist/path-false-extension-true/esm/logger.d.ts": "import type { Request } from 'express'; + import type { LoggerOptions } from './types.js'; + export declare function logRequest(req: Request, options: LoggerOptions): void; + ", + "/tests/integration/redirect/dts/dist/path-false-extension-true/esm/types.d.ts": "export interface LoggerOptions { + logLevel: 'info' | 'debug' | 'warn' | 'error'; + logBody: boolean; + } + export declare const defaultOptions: LoggerOptions; + export interface Foo { + foo: string; + } + export interface Bar { + bar: string; + } + export interface Baz { + baz: string; + } + ", + } + `); +}); + +test('redirect.dts.extension: true with dts.autoExtension: true', async () => { + expect(contents.esm4).toMatchInlineSnapshot(` { "/tests/integration/redirect/dts/dist/auto-extension-true/foo/foo.d.mts": "import { logRequest } from '../logger.mjs'; import { logger } from '../../../compile/rslog'; @@ -157,9 +216,10 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => { ", "/tests/integration/redirect/dts/dist/auto-extension-true/index.d.mts": "import { logRequest } from './logger.mjs'; import { logger } from '../../compile/rslog'; + import type { Baz } from './index.mjs'; import type { LoggerOptions } from './types.mjs'; import { defaultOptions } from './types.mjs'; - export { logRequest, logger, type LoggerOptions, defaultOptions }; + export { type Baz as self, logRequest, logger, type LoggerOptions, defaultOptions, }; export type { Foo } from './types.mjs'; export type { Bar } from './types.mjs'; export * from './foo/index.mjs'; @@ -170,9 +230,10 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => { ", "/tests/integration/redirect/dts/dist/auto-extension-true/index.d.ts": "import { logRequest } from './logger.js'; import { logger } from '../../compile/rslog'; + import type { Baz } from './index.js'; import type { LoggerOptions } from './types.js'; import { defaultOptions } from './types.js'; - export { logRequest, logger, type LoggerOptions, defaultOptions }; + export { type Baz as self, logRequest, logger, type LoggerOptions, defaultOptions, }; export type { Foo } from './types.js'; export type { Bar } from './types.js'; export * from './foo/index.js'; @@ -200,6 +261,9 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => { export interface Bar { bar: string; } + export interface Baz { + baz: string; + } ", "/tests/integration/redirect/dts/dist/auto-extension-true/types.d.ts": "export interface LoggerOptions { logLevel: 'info' | 'debug' | 'warn' | 'error'; @@ -212,6 +276,9 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => { export interface Bar { bar: string; } + export interface Baz { + baz: string; + } ", } `); diff --git a/tests/integration/redirect/dts/rslib.config.ts b/tests/integration/redirect/dts/rslib.config.ts index 80114ae48..6cf190290 100644 --- a/tests/integration/redirect/dts/rslib.config.ts +++ b/tests/integration/redirect/dts/rslib.config.ts @@ -3,7 +3,7 @@ import { generateBundleCjsConfig, generateBundleEsmConfig } from 'test-helper'; export default defineConfig({ lib: [ - // 0 - default + // 0 - default - path: true extension: false generateBundleEsmConfig({ dts: true, output: { @@ -12,7 +12,7 @@ export default defineConfig({ }, }, }), - // 1 - path: false + // 1 - path: false extension: false generateBundleEsmConfig({ dts: true, output: { @@ -26,7 +26,7 @@ export default defineConfig({ }, }, }), - // 2 - extension: true + // 2 - path: true extension: true generateBundleEsmConfig({ dts: true, output: { @@ -40,7 +40,22 @@ export default defineConfig({ }, }, }), - // 3 - extension: true with dts.autoExtension true + // 3 - path: false extension: true + generateBundleEsmConfig({ + dts: true, + output: { + distPath: { + root: './dist/path-false-extension-true/esm', + }, + }, + redirect: { + dts: { + path: false, + extension: true, + }, + }, + }), + // 4 - extension: true with dts.autoExtension true generateBundleEsmConfig({ dts: { autoExtension: true, @@ -56,7 +71,7 @@ export default defineConfig({ }, }, }), - // 4 - extension: true with dts.autoExtension true + // 5 - extension: true with dts.autoExtension true generateBundleCjsConfig({ dts: { autoExtension: true, diff --git a/tests/integration/redirect/dts/src/index.ts b/tests/integration/redirect/dts/src/index.ts index b4402c115..ef376e58a 100644 --- a/tests/integration/redirect/dts/src/index.ts +++ b/tests/integration/redirect/dts/src/index.ts @@ -1,9 +1,16 @@ import { logRequest } from '@src/logger'; import { logger } from 'rslog'; +import type { Baz } from 'self-entry'; import type { LoggerOptions } from './types'; import { defaultOptions } from './types.js'; -export { logRequest, logger, type LoggerOptions, defaultOptions }; +export { + type Baz as self, + logRequest, + logger, + type LoggerOptions, + defaultOptions, +}; export type { Foo } from '@src/types'; export type { Bar } from 'types'; diff --git a/tests/integration/redirect/dts/src/types.ts b/tests/integration/redirect/dts/src/types.ts index cc9ccac52..ef6a9bf2b 100644 --- a/tests/integration/redirect/dts/src/types.ts +++ b/tests/integration/redirect/dts/src/types.ts @@ -15,3 +15,7 @@ export interface Foo { export interface Bar { bar: string; } + +export interface Baz { + baz: string; +} diff --git a/tests/integration/redirect/dts/tsconfig.json b/tests/integration/redirect/dts/tsconfig.json index c86ca44d8..d70d332f2 100644 --- a/tests/integration/redirect/dts/tsconfig.json +++ b/tests/integration/redirect/dts/tsconfig.json @@ -5,7 +5,8 @@ "paths": { "*": ["./src/*"], "@src/*": ["./src/*"], - "rslog": ["./compile/rslog"] + "rslog": ["./compile/rslog"], + "self-entry": ["./src"] } }, "include": ["src/**/*"] From ae4164a6adeada344845e13f184f48b91ef4e2f2 Mon Sep 17 00:00:00 2001 From: Timeless0911 <1604889533@qq.com> Date: Mon, 21 Apr 2025 17:10:49 +0800 Subject: [PATCH 2/4] chore: update --- tests/integration/redirect/dts.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/redirect/dts.test.ts b/tests/integration/redirect/dts.test.ts index 4b142c8dd..2286a29a1 100644 --- a/tests/integration/redirect/dts.test.ts +++ b/tests/integration/redirect/dts.test.ts @@ -9,7 +9,7 @@ beforeAll(async () => { contents = (await buildAndGetResults({ fixturePath, type: 'dts' })).contents; }); -test('redirect.dts default - redirect.dts.path: true with redirect.dts.extension: false', async () => { +test('redirect.dts.path: true with redirect.dts.extension: false - default', async () => { expect(contents.esm0).toMatchInlineSnapshot(` { "/tests/integration/redirect/dts/dist/default/esm/foo/foo.d.ts": "import { logRequest } from '../logger'; From 49c012909874c7d4267019f346efe772899a8fcc Mon Sep 17 00:00:00 2001 From: Timeless0911 <1604889533@qq.com> Date: Mon, 21 Apr 2025 17:45:30 +0800 Subject: [PATCH 3/4] chore: update --- tests/integration/redirect/dts.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/redirect/dts.test.ts b/tests/integration/redirect/dts.test.ts index 2286a29a1..fe3d66d7c 100644 --- a/tests/integration/redirect/dts.test.ts +++ b/tests/integration/redirect/dts.test.ts @@ -7,7 +7,7 @@ let contents: Awaited>['contents']; beforeAll(async () => { const fixturePath = path.resolve(__dirname, './dts'); contents = (await buildAndGetResults({ fixturePath, type: 'dts' })).contents; -}); +}, 15000); test('redirect.dts.path: true with redirect.dts.extension: false - default', async () => { expect(contents.esm0).toMatchInlineSnapshot(` From 9c919294938f1783c54e7b2ad043a15e03009163 Mon Sep 17 00:00:00 2001 From: Timeless0911 <1604889533@qq.com> Date: Mon, 21 Apr 2025 20:27:20 +0800 Subject: [PATCH 4/4] chore: update --- packages/plugin-dts/src/utils.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/plugin-dts/src/utils.ts b/packages/plugin-dts/src/utils.ts index 99eac3d9b..c24b1d8d3 100644 --- a/packages/plugin-dts/src/utils.ts +++ b/packages/plugin-dts/src/utils.ts @@ -187,11 +187,7 @@ async function addExtension( let redirectPath = path; // Only add extension if redirectPath is an absolute or relative path - if ( - !isAbsolute(redirectPath) && - !redirectPath.startsWith('./') && - !redirectPath.startsWith('../') - ) { + if (!isAbsolute(redirectPath) && !redirectPath.startsWith('.')) { return redirectPath; }