Skip to content

Commit 0a45360

Browse files
authored
fix: correctly detect suffix for scoped packages with dots (#323)
1 parent 147df85 commit 0a45360

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

src/utils/VirtualModule.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { existsSync, mkdirSync, writeFile, writeFileSync } from 'fs';
2-
import { dirname, join, parse, resolve } from 'pathe';
2+
import { dirname, join, parse, resolve, basename } from 'pathe';
33
import { packageNameDecode, packageNameEncode } from '../utils/packageNameUtils';
44
import { getNormalizeModuleFederationOptions } from './normalizeModuleFederationOptions';
55

@@ -30,6 +30,17 @@ function getNodeModulesDir() {
3030
return cachedNodeModulesDir;
3131
}
3232

33+
export function getSuffix(name: string): string {
34+
const base = basename(name);
35+
const dotIndex = base.lastIndexOf('.');
36+
37+
if (dotIndex > 0 && dotIndex < base.length - 1) {
38+
return base.slice(dotIndex);
39+
}
40+
41+
return '.js';
42+
}
43+
3344
const patternMap: {
3445
[tag: string]: RegExp;
3546
} = {};
@@ -92,7 +103,7 @@ export default class VirtualModule {
92103
constructor(name: string, tag: string = '__mf_v__', suffix = '') {
93104
this.name = name;
94105
this.tag = tag;
95-
this.suffix = suffix || name.split('.').slice(1).pop()?.replace(/(.)/, '.$1') || '.js';
106+
this.suffix = suffix || getSuffix(name);
96107
if (!cacheMap[this.tag]) cacheMap[this.tag] = {};
97108
cacheMap[this.tag][this.name] = this;
98109
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { getSuffix } from '../VirtualModule';
2+
3+
describe('getSuffix', () => {
4+
it('returns .js for simple package without extension', () => {
5+
expect(getSuffix('react')).toBe('.js');
6+
});
7+
8+
it('returns .js for scoped package without extension', () => {
9+
expect(getSuffix('@scope/pkg')).toBe('.js');
10+
});
11+
12+
it('returns .js for scoped package with dots in namespace but no file', () => {
13+
expect(getSuffix('@company.name/pkg')).toBe('.js');
14+
});
15+
16+
it('detects correct suffix for file with extension', () => {
17+
expect(getSuffix('some/path/to/module.ts')).toBe('.ts');
18+
});
19+
20+
it('detects correct suffix for scoped package with nested file and extension', () => {
21+
expect(getSuffix('@scope/pkg/sub/file.jsx')).toBe('.jsx');
22+
});
23+
24+
it('handles scoped package with dots in namespace and extension in file', () => {
25+
expect(getSuffix('@company.name/pkg/utils/helper.tsx')).toBe('.tsx');
26+
});
27+
28+
it('returns .js if dot is before namespace', () => {
29+
expect(getSuffix('.bin/@scope/pkg')).toBe('.js');
30+
});
31+
32+
it('returns correct suffix when multiple dots after namespace', () => {
33+
expect(getSuffix('@scope/pkg/path.to/module.name.mjs')).toBe('.mjs');
34+
});
35+
36+
it('returns correct suffix for deep relative path with scoped namespace', () => {
37+
expect(getSuffix('@scope.with.dots/pkg/deep/util.spec.ts')).toBe('.ts');
38+
});
39+
});

0 commit comments

Comments
 (0)