Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions packages/plugin-dts/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import path, {
basename,
dirname,
extname,
isAbsolute,
join,
normalize,
relative,
Expand Down Expand Up @@ -185,10 +186,15 @@ async function addExtension(

let redirectPath = path;

// Only add extension if redirectPath is an absolute or relative path
if (!isAbsolute(redirectPath) && !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}`;
Expand Down Expand Up @@ -277,9 +283,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);
Expand Down
87 changes: 77 additions & 10 deletions tests/integration/redirect/dts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ let contents: Awaited<ReturnType<typeof buildAndGetResults>>['contents'];
beforeAll(async () => {
const fixturePath = path.resolve(__dirname, './dts');
contents = (await buildAndGetResults({ fixturePath, type: 'dts' })).contents;
});
}, 15000);

test('redirect.dts default', async () => {
test('redirect.dts.path: true with redirect.dts.extension: false - default', async () => {
expect(contents.esm0).toMatchInlineSnapshot(`
{
"<ROOT>/tests/integration/redirect/dts/dist/default/esm/foo/foo.d.ts": "import { logRequest } from '../logger';
Expand All @@ -21,9 +21,10 @@ test('redirect.dts default', async () => {
",
"<ROOT>/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';
Expand All @@ -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(`
{
"<ROOT>/tests/integration/redirect/dts/dist/path-false/esm/foo/foo.d.ts": "import { logRequest } from '@src/logger';
Expand All @@ -64,9 +68,10 @@ test('redirect.dts.path false', async () => {
",
"<ROOT>/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';
Expand All @@ -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(`
{
"<ROOT>/tests/integration/redirect/dts/dist/extension-true/esm/foo/foo.d.ts": "import { logRequest } from '../logger.js';
Expand All @@ -107,9 +115,10 @@ test('redirect.dts.extension true', async () => {
",
"<ROOT>/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';
Expand All @@ -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(`
{
"<ROOT>/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 };
",
"<ROOT>/tests/integration/redirect/dts/dist/path-false-extension-true/esm/foo/index.d.ts": "export type Barrel = string;
",
"<ROOT>/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';
",
"<ROOT>/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;
",
"<ROOT>/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(`
{
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/foo/foo.d.mts": "import { logRequest } from '../logger.mjs';
import { logger } from '../../../compile/rslog';
Expand All @@ -157,9 +216,10 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => {
",
"<ROOT>/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';
Expand All @@ -170,9 +230,10 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => {
",
"<ROOT>/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';
Expand Down Expand Up @@ -200,6 +261,9 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => {
export interface Bar {
bar: string;
}
export interface Baz {
baz: string;
}
",
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/types.d.ts": "export interface LoggerOptions {
logLevel: 'info' | 'debug' | 'warn' | 'error';
Expand All @@ -212,6 +276,9 @@ test('redirect.dts.extension true with dts.autoExtension true', async () => {
export interface Bar {
bar: string;
}
export interface Baz {
baz: string;
}
",
}
`);
Expand Down
25 changes: 20 additions & 5 deletions tests/integration/redirect/dts/rslib.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -12,7 +12,7 @@ export default defineConfig({
},
},
}),
// 1 - path: false
// 1 - path: false extension: false
generateBundleEsmConfig({
dts: true,
output: {
Expand All @@ -26,7 +26,7 @@ export default defineConfig({
},
},
}),
// 2 - extension: true
// 2 - path: true extension: true
generateBundleEsmConfig({
dts: true,
output: {
Expand All @@ -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,
Expand All @@ -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,
Expand Down
9 changes: 8 additions & 1 deletion tests/integration/redirect/dts/src/index.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
4 changes: 4 additions & 0 deletions tests/integration/redirect/dts/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ export interface Foo {
export interface Bar {
bar: string;
}

export interface Baz {
baz: string;
}
3 changes: 2 additions & 1 deletion tests/integration/redirect/dts/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"paths": {
"*": ["./src/*"],
"@src/*": ["./src/*"],
"rslog": ["./compile/rslog"]
"rslog": ["./compile/rslog"],
"self-entry": ["./src"]
}
},
"include": ["src/**/*"]
Expand Down
Loading