Skip to content

Commit e9dcaad

Browse files
committed
fix(dts): check for existence of target path when redirect.dts.extension is enabled
1 parent c2df99c commit e9dcaad

19 files changed

Lines changed: 143 additions & 29 deletions

File tree

packages/plugin-dts/src/utils.ts

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -237,26 +237,40 @@ async function addExtension(
237237
redirect: DtsRedirect,
238238
dtsFile: string,
239239
path: string,
240-
extension: string,
240+
jsExtension: string,
241+
dtsExtension: string,
241242
): Promise<string> {
242243
if (!redirect.extension) {
243244
return path;
244245
}
245246

246-
let redirectPath = path;
247-
248-
// Only add extension if redirectPath is an absolute or relative path
249-
if (!isAbsolute(redirectPath) && !redirectPath.startsWith('.')) {
250-
return redirectPath;
247+
// Only add extension if path is an absolute or relative path
248+
if (!isAbsolute(path) && !path.startsWith('.')) {
249+
return path;
251250
}
252251

252+
const candidatePaths = [];
253+
253254
// If the import path refers to a directory, it most likely actually refers to a `index.*` file due to Node's module resolution
254-
if (await isDirectory(join(dirname(dtsFile), redirectPath))) {
255+
if (await isDirectory(join(dirname(dtsFile), path))) {
255256
// This uses `/` instead of `path.join` here because `join` removes potential "./" prefixes
256-
redirectPath = `${redirectPath.replace(/\/+$/, '')}/index`;
257+
candidatePaths.push(`${path.replace(/\/+$/, '')}/index`);
258+
}
259+
260+
candidatePaths.push(path);
261+
262+
// make sure the candidatePath exists, otherwise we may break the import, e.g. import 'foo.svg', import '../compile/prebundle-types'
263+
for (const candidatePath of candidatePaths) {
264+
if (
265+
await pathExists(
266+
join(dirname(dtsFile), `${candidatePath}${dtsExtension}`),
267+
)
268+
) {
269+
return `${candidatePath}${jsExtension}`;
270+
}
257271
}
258272

259-
return `${redirectPath}${extension}`;
273+
return path;
260274
}
261275

262276
export async function redirectDtsImports(
@@ -334,7 +348,7 @@ export async function redirectDtsImports(
334348
e: matchNode.range().end.index,
335349
};
336350
});
337-
const extension = dtsExtension
351+
const jsExtension = dtsExtension
338352
.replace(/\.d\.ts$/, '.js')
339353
.replace(/\.d\.cts$/, '.cjs')
340354
.replace(/\.d\.mts$/, '.mjs');
@@ -393,28 +407,18 @@ export async function redirectDtsImports(
393407
if (redirect.extension) {
394408
redirectImportPath = redirectImportPath.replace(
395409
/\.[^.]+$/,
396-
extension,
410+
jsExtension,
397411
);
398412
}
399413
} else {
400414
// handle the case importPath is like './foo.bar', we need to check if './foo.bar.d.ts' exists
401-
const candidatePath = await addExtension(
415+
redirectImportPath = await addExtension(
402416
redirect,
403417
dtsFile,
404418
redirectImportPath,
405-
extension,
419+
jsExtension,
420+
dtsExtension,
406421
);
407-
// make sure the candidatePath exists, otherwise we may break the import, e.g. import 'foo.svg'
408-
if (
409-
await pathExists(
410-
path.join(
411-
dirname(dtsFile),
412-
candidatePath.replace(/\.[^.]+$/, dtsExtension),
413-
),
414-
)
415-
) {
416-
redirectImportPath = candidatePath;
417-
}
418422
}
419423
} else {
420424
if (
@@ -425,7 +429,8 @@ export async function redirectDtsImports(
425429
redirect,
426430
dtsFile,
427431
redirectImportPath,
428-
extension,
432+
jsExtension,
433+
dtsExtension,
429434
);
430435
}
431436

@@ -434,7 +439,8 @@ export async function redirectDtsImports(
434439
redirect,
435440
dtsFile,
436441
redirectImportPath,
437-
extension,
442+
jsExtension,
443+
dtsExtension,
438444
);
439445
}
440446
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const a = 1;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "prebundle-types",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module",
6+
"module": "index.js",
7+
"types": "types/index.d.ts"
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface PluginInstance {
2+
apply: (compiler: any) => void;
3+
[index: string]: any;
4+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './config/load';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const loadConfig = () => {};

tests/integration/redirect/dts-tsgo/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ export {
1818
export * from '@src/foo';
1919
export * from '@src/logger';
2020
export type { Foo } from '@src/types';
21-
// export { Router } from 'express';
2221
export * from 'prebundle-pkg';
22+
// export { Router } from 'express';
23+
export type * from 'prebundle-types';
2324
export type { Bar } from 'types';
2425
export * from './.hidden';
2526
export * from './.hidden-folder';
2627
export * from './a.b';
2728
export * from './bar.baz';
29+
export * from './config';
2830
export * from './foo';
2931
export * from './types';

tests/integration/redirect/dts-tsgo/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"paths": {
66
"@src/*": ["./src/*"],
77
"prebundle-pkg": ["./compile/prebundle-pkg"],
8+
"prebundle-types": ["./compile/prebundle-types"],
89
"self-entry": ["./src"],
910
"express": ["./node_modules/express"],
1011
"*": ["./src/*"]

tests/integration/redirect/dts.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ test('redirect.dts.path: true with redirect.dts.extension: false - default', asy
1919
"<ROOT>/tests/integration/redirect/dts/dist/default/esm/a.b/index.d.ts": "export declare const ab = "a.b";
2020
",
2121
"<ROOT>/tests/integration/redirect/dts/dist/default/esm/bar.baz.d.ts": "export declare const bar = "bar-baz";
22+
",
23+
"<ROOT>/tests/integration/redirect/dts/dist/default/esm/config.d.ts": "export * from './config/load';
24+
",
25+
"<ROOT>/tests/integration/redirect/dts/dist/default/esm/config/load.d.ts": "export declare const loadConfig: () => void;
2226
",
2327
"<ROOT>/tests/integration/redirect/dts/dist/default/esm/foo/foo.d.ts": "import { logRequest } from '../logger';
2428
import { logger } from '../../../../compile/prebundle-pkg';
@@ -39,11 +43,13 @@ test('redirect.dts.path: true with redirect.dts.extension: false - default', asy
3943
export type { Foo } from './types';
4044
export { Router } from 'express';
4145
export * from '../../../compile/prebundle-pkg';
46+
export type * from '../../../compile/prebundle-types';
4247
export type { Bar } from './types';
4348
export * from './.hidden';
4449
export * from './.hidden-folder';
4550
export * from './a.b';
4651
export * from './bar.baz';
52+
export * from './config';
4753
export * from './foo';
4854
export * from './types';
4955
",
@@ -80,6 +86,10 @@ test('redirect.dts.path: false with redirect.dts.extension: false', async () =>
8086
"<ROOT>/tests/integration/redirect/dts/dist/path-false/esm/a.b/index.d.ts": "export declare const ab = "a.b";
8187
",
8288
"<ROOT>/tests/integration/redirect/dts/dist/path-false/esm/bar.baz.d.ts": "export declare const bar = "bar-baz";
89+
",
90+
"<ROOT>/tests/integration/redirect/dts/dist/path-false/esm/config.d.ts": "export * from './config/load';
91+
",
92+
"<ROOT>/tests/integration/redirect/dts/dist/path-false/esm/config/load.d.ts": "export declare const loadConfig: () => void;
8393
",
8494
"<ROOT>/tests/integration/redirect/dts/dist/path-false/esm/foo/foo.d.ts": "import { logRequest } from '@src/logger';
8595
import { logger } from 'prebundle-pkg';
@@ -100,11 +110,13 @@ test('redirect.dts.path: false with redirect.dts.extension: false', async () =>
100110
export type { Foo } from '@src/types';
101111
export { Router } from 'express';
102112
export * from 'prebundle-pkg';
113+
export type * from 'prebundle-types';
103114
export type { Bar } from 'types';
104115
export * from './.hidden';
105116
export * from './.hidden-folder';
106117
export * from './a.b';
107118
export * from './bar.baz';
119+
export * from './config';
108120
export * from './foo';
109121
export * from './types';
110122
",
@@ -141,6 +153,10 @@ test('redirect.dts.path: true with redirect.dts.extension: true', async () => {
141153
"<ROOT>/tests/integration/redirect/dts/dist/extension-true/esm/a.b/index.d.ts": "export declare const ab = "a.b";
142154
",
143155
"<ROOT>/tests/integration/redirect/dts/dist/extension-true/esm/bar.baz.d.ts": "export declare const bar = "bar-baz";
156+
",
157+
"<ROOT>/tests/integration/redirect/dts/dist/extension-true/esm/config.d.ts": "export * from './config/load.js';
158+
",
159+
"<ROOT>/tests/integration/redirect/dts/dist/extension-true/esm/config/load.d.ts": "export declare const loadConfig: () => void;
144160
",
145161
"<ROOT>/tests/integration/redirect/dts/dist/extension-true/esm/foo/foo.d.ts": "import { logRequest } from '../logger.js';
146162
import { logger } from '../../../../compile/prebundle-pkg';
@@ -161,11 +177,13 @@ test('redirect.dts.path: true with redirect.dts.extension: true', async () => {
161177
export type { Foo } from './types.js';
162178
export { Router } from 'express';
163179
export * from '../../../compile/prebundle-pkg';
180+
export type * from '../../../compile/prebundle-types';
164181
export type { Bar } from './types.js';
165182
export * from './.hidden.js';
166183
export * from './.hidden-folder/index.js';
167184
export * from './a.b/index.js';
168185
export * from './bar.baz.js';
186+
export * from './config.js';
169187
export * from './foo/index.js';
170188
export * from './types.js';
171189
",
@@ -202,6 +220,10 @@ test('redirect.dts.path: false with dts.redirect.extension: true', async () => {
202220
"<ROOT>/tests/integration/redirect/dts/dist/path-false-extension-true/esm/a.b/index.d.ts": "export declare const ab = "a.b";
203221
",
204222
"<ROOT>/tests/integration/redirect/dts/dist/path-false-extension-true/esm/bar.baz.d.ts": "export declare const bar = "bar-baz";
223+
",
224+
"<ROOT>/tests/integration/redirect/dts/dist/path-false-extension-true/esm/config.d.ts": "export * from './config/load.js';
225+
",
226+
"<ROOT>/tests/integration/redirect/dts/dist/path-false-extension-true/esm/config/load.d.ts": "export declare const loadConfig: () => void;
205227
",
206228
"<ROOT>/tests/integration/redirect/dts/dist/path-false-extension-true/esm/foo/foo.d.ts": "import { logRequest } from '@src/logger';
207229
import { logger } from 'prebundle-pkg';
@@ -222,11 +244,13 @@ test('redirect.dts.path: false with dts.redirect.extension: true', async () => {
222244
export type { Foo } from '@src/types';
223245
export { Router } from 'express';
224246
export * from 'prebundle-pkg';
247+
export type * from 'prebundle-types';
225248
export type { Bar } from 'types';
226249
export * from './.hidden.js';
227250
export * from './.hidden-folder/index.js';
228251
export * from './a.b/index.js';
229252
export * from './bar.baz.js';
253+
export * from './config.js';
230254
export * from './foo/index.js';
231255
export * from './types.js';
232256
",
@@ -271,6 +295,14 @@ test('redirect.dts.extension: true with dts.autoExtension: true', async () => {
271295
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/bar.baz.d.mts": "export declare const bar = "bar-baz";
272296
",
273297
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/bar.baz.d.ts": "export declare const bar = "bar-baz";
298+
",
299+
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/config.d.mts": "export * from './config/load.mjs';
300+
",
301+
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/config.d.ts": "export * from './config/load.js';
302+
",
303+
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/config/load.d.mts": "export declare const loadConfig: () => void;
304+
",
305+
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/config/load.d.ts": "export declare const loadConfig: () => void;
274306
",
275307
"<ROOT>/tests/integration/redirect/dts/dist/auto-extension-true/foo/foo.d.mts": "import { logRequest } from '../logger.mjs';
276308
import { logger } from '../../../compile/prebundle-pkg';
@@ -298,11 +330,13 @@ test('redirect.dts.extension: true with dts.autoExtension: true', async () => {
298330
export type { Foo } from './types.mjs';
299331
export { Router } from 'express';
300332
export * from '../../compile/prebundle-pkg';
333+
export type * from '../../compile/prebundle-types';
301334
export type { Bar } from './types.mjs';
302335
export * from './.hidden.mjs';
303336
export * from './.hidden-folder/index.mjs';
304337
export * from './a.b/index.mjs';
305338
export * from './bar.baz.mjs';
339+
export * from './config.mjs';
306340
export * from './foo/index.mjs';
307341
export * from './types.mjs';
308342
",
@@ -318,11 +352,13 @@ test('redirect.dts.extension: true with dts.autoExtension: true', async () => {
318352
export type { Foo } from './types.js';
319353
export { Router } from 'express';
320354
export * from '../../compile/prebundle-pkg';
355+
export type * from '../../compile/prebundle-types';
321356
export type { Bar } from './types.js';
322357
export * from './.hidden.js';
323358
export * from './.hidden-folder/index.js';
324359
export * from './a.b/index.js';
325360
export * from './bar.baz.js';
361+
export * from './config.js';
326362
export * from './foo/index.js';
327363
export * from './types.js';
328364
",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const a = 1;

0 commit comments

Comments
 (0)