Skip to content

Commit 77e890f

Browse files
committed
Allow non-module resolves
1 parent a65c39a commit 77e890f

File tree

7 files changed

+109
-40
lines changed

7 files changed

+109
-40
lines changed

src/mapPath.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import defaultResolvePath from './resolvePath';
22

3-
export default function mapPathString(nodePath, state) {
3+
export default function mapPathString(nodePath, state, resolveOpts) {
44
if (!state.types.isStringLiteral(nodePath)) {
55
return;
66
}
@@ -9,7 +9,7 @@ export default function mapPathString(nodePath, state) {
99
const currentFile = state.file.opts.filename;
1010
const resolvePath = state.normalizedOpts.customResolvePath || defaultResolvePath;
1111

12-
const modulePath = resolvePath(sourcePath, currentFile, state.opts);
12+
const modulePath = resolvePath(sourcePath, currentFile, state.opts, resolveOpts);
1313
if (modulePath) {
1414
if (nodePath.node.pathResolved) {
1515
return;

src/normalizeOptions.js

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ import pkgUp from 'pkg-up';
99
import { escapeRegExp } from './utils';
1010

1111
const defaultExtensions = ['.js', '.jsx', '.es', '.es6', '.mjs'];
12-
const defaultTransformedFunctions = [
13-
'require',
14-
'require.resolve',
15-
'System.import',
12+
const defaultTransformFunctions = [
13+
{ pattern: 'require', isModulePath: true },
14+
{ pattern: 'require.resolve', isModulePath: true },
15+
{ pattern: 'System.import', isModulePath: true },
1616

1717
// Jest methods
18-
'jest.genMockFromModule',
19-
'jest.mock',
20-
'jest.unmock',
21-
'jest.doMock',
22-
'jest.dontMock',
23-
'jest.setMock',
24-
'require.requireActual',
25-
'require.requireMock',
18+
{ pattern: 'jest.genMockFromModule', isModulePath: true },
19+
{ pattern: 'jest.mock', isModulePath: true },
20+
{ pattern: 'jest.unmock', isModulePath: true },
21+
{ pattern: 'jest.doMock', isModulePath: true },
22+
{ pattern: 'jest.dontMock', isModulePath: true },
23+
{ pattern: 'jest.setMock', isModulePath: true },
24+
{ pattern: 'require.requireActual', isModulePath: true },
25+
{ pattern: 'require.requireMock', isModulePath: true },
2626
];
2727

2828
function isRegExp(string) {
@@ -122,12 +122,30 @@ function normalizeAlias(optsAlias) {
122122
}, []);
123123
}
124124

125-
function normalizeTransformedFunctions(optsTransformFunctions) {
125+
function normalizeTransformFunctionsElement(optsTransformFunction) {
126+
let pattern;
127+
let opts;
128+
if (Array.isArray(optsTransformFunction)) {
129+
[pattern, opts] = optsTransformFunction;
130+
} else {
131+
[pattern, opts] = [optsTransformFunction, {}];
132+
}
133+
134+
const finalOpts = { pattern, isModulePath: true };
135+
if ('isModulePath' in opts) {
136+
finalOpts.isModulePath = opts.isModulePath;
137+
}
138+
139+
return finalOpts;
140+
}
141+
142+
function normalizeTransformFunctions(optsTransformFunctions) {
126143
if (!optsTransformFunctions) {
127-
return defaultTransformedFunctions;
144+
return defaultTransformFunctions;
128145
}
129146

130-
return [...defaultTransformedFunctions, ...optsTransformFunctions];
147+
return [...defaultTransformFunctions,
148+
...optsTransformFunctions.map(normalizeTransformFunctionsElement)];
131149
}
132150

133151
function normalizeLoglevel(optsLoglevel) {
@@ -143,7 +161,7 @@ export default createSelector(
143161
const root = normalizeRoot(opts.root, cwd);
144162
const alias = normalizeAlias(opts.alias);
145163
const loglevel = normalizeLoglevel(opts.loglevel);
146-
const transformFunctions = normalizeTransformedFunctions(opts.transformFunctions);
164+
const transformFunctions = normalizeTransformFunctions(opts.transformFunctions);
147165
const extensions = opts.extensions || defaultExtensions;
148166
const stripExtensions = opts.stripExtensions || extensions;
149167

src/resolvePath.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,24 @@ function getRelativePath(sourcePath, currentFile, absFileInRoot, opts) {
1717
return toLocalPath(toPosixPath(relativePath));
1818
}
1919

20-
function findPathInRoots(sourcePath, { extensions, root }) {
20+
function findPathInRoots(sourcePath, { extensions, root }, { isModulePath }) {
2121
// Search the source path inside every custom root directory
2222
let resolvedSourceFile;
2323

2424
root.some((basedir) => {
25-
resolvedSourceFile = nodeResolvePath(`./${sourcePath}`, basedir, extensions);
25+
if (isModulePath) {
26+
resolvedSourceFile = nodeResolvePath(`./${sourcePath}`, basedir, extensions);
27+
} else {
28+
resolvedSourceFile = path.resolve(basedir, `./${sourcePath}`);
29+
}
2630
return resolvedSourceFile !== null;
2731
});
2832

2933
return resolvedSourceFile;
3034
}
3135

32-
function resolvePathFromRootConfig(sourcePath, currentFile, opts) {
33-
const absFileInRoot = findPathInRoots(sourcePath, opts);
36+
function resolvePathFromRootConfig(sourcePath, currentFile, opts, resolveOpts) {
37+
const absFileInRoot = findPathInRoots(sourcePath, opts, resolveOpts);
3438

3539
if (!absFileInRoot) {
3640
return null;
@@ -46,7 +50,7 @@ function checkIfPackageExists(modulePath, currentFile, extensions, loglevel) {
4650
}
4751
}
4852

49-
function resolvePathFromAliasConfig(sourcePath, currentFile, opts) {
53+
function resolvePathFromAliasConfig(sourcePath, currentFile, opts, { isModulePath = true } = {}) {
5054
let aliasedSourceFile;
5155

5256
opts.alias.find(([regExp, substitute]) => {
@@ -73,7 +77,10 @@ function resolvePathFromAliasConfig(sourcePath, currentFile, opts) {
7377
}
7478
return asf;
7579
})
76-
.find(src => nodeResolvePath(src, path.dirname(currentFile), opts.extensions));
80+
.find(src => {
81+
return !isModulePath
82+
|| nodeResolvePath(src, path.dirname(currentFile), opts.extensions);
83+
});
7784
}
7885

7986
if (isRelativePath(aliasedSourceFile)) {
@@ -82,7 +89,7 @@ function resolvePathFromAliasConfig(sourcePath, currentFile, opts) {
8289
);
8390
}
8491

85-
if (process.env.NODE_ENV !== 'production') {
92+
if (isModulePath && process.env.NODE_ENV !== 'production') {
8693
checkIfPackageExists(aliasedSourceFile, currentFile, opts.extensions, opts.loglevel);
8794
}
8895

@@ -94,7 +101,9 @@ const resolvers = [
94101
resolvePathFromRootConfig,
95102
];
96103

97-
export default function resolvePath(sourcePath, currentFile, opts) {
104+
export default function resolvePath(
105+
sourcePath, currentFile, opts, { isModulePath = true } = {},
106+
) {
98107
if (isRelativePath(sourcePath)) {
99108
return sourcePath;
100109
}
@@ -107,7 +116,8 @@ export default function resolvePath(sourcePath, currentFile, opts) {
107116
let resolvedPath = null;
108117

109118
resolvers.some((resolver) => {
110-
resolvedPath = resolver(sourcePath, absoluteCurrentFile, normalizedOpts);
119+
resolvedPath = resolver(
120+
sourcePath, absoluteCurrentFile, normalizedOpts, { isModulePath });
111121
return resolvedPath !== null;
112122
});
113123

src/transformers/call.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ export default function transformCall(nodePath, state) {
77
}
88

99
const calleePath = nodePath.get('callee');
10-
const isNormalCall = state.normalizedOpts.transformFunctions.some(pattern =>
10+
const transformFunction = state.normalizedOpts.transformFunctions.find(({ pattern }) =>
1111
matchesPattern(state.types, calleePath, pattern)
1212
);
1313

14-
if (isNormalCall || isImportCall(state.types, nodePath)) {
14+
if (transformFunction) {
1515
state.moduleResolverVisited.add(nodePath);
16-
mapPathString(nodePath.get('arguments.0'), state);
16+
const { isModulePath } = transformFunction;
17+
mapPathString(nodePath.get('arguments.0'), state, { isModulePath });
18+
} else if (isImportCall(state.types, nodePath)) {
19+
state.moduleResolverVisited.add(nodePath);
20+
mapPathString(nodePath.get('arguments.0'), state, { isModulePath: true });
1721
}
1822
}

src/transformers/import.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ export default function transformImport(nodePath, state) {
66
}
77
state.moduleResolverVisited.add(nodePath);
88

9-
mapPathString(nodePath.get('source'), state);
9+
mapPathString(nodePath.get('source'), state, { isModulePath: true });
1010
}

test/custom-call.test.js

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import plugin from '../src';
33

44

55
const calls = [
6-
'customMethod.something',
6+
'customMethod.Module',
7+
'customMethod.NonModule',
78
];
89

910
describe('custom calls', () => {
@@ -16,7 +17,8 @@ describe('custom calls', () => {
1617
test: './test/testproject/test',
1718
},
1819
transformFunctions: [
19-
'customMethod.something',
20+
'customMethod.Module',
21+
['customMethod.NonModule', { isModulePath: false }],
2022
],
2123
}],
2224
],
@@ -59,13 +61,6 @@ describe('custom calls', () => {
5961
expect(result.code).toBe(`${name}(path, ...args);`);
6062
});
6163

62-
it('should handle an empty path', () => {
63-
const code = `${name}('', ...args);`;
64-
const result = transform(code, transformerOpts);
65-
66-
expect(result.code).toBe(`${name}('', ...args);`);
67-
});
68-
6964
it('should ignore the call if the method name is not fully matched (suffix)', () => {
7065
const code = `${name}.after("components/Sidebar/Footer", ...args);`;
7166
const result = transform(code, transformerOpts);
@@ -81,4 +76,24 @@ describe('custom calls', () => {
8176
});
8277
});
8378
});
79+
80+
describe('customMethod.Module', () => {
81+
const name = 'customMethod.Module';
82+
it('should handle an empty path', () => {
83+
const code = `${name}('', ...args);`;
84+
const result = transform(code, transformerOpts);
85+
86+
expect(result.code).toBe(`${name}('', ...args);`);
87+
});
88+
});
89+
90+
describe('customMethod.NonModule', () => {
91+
const name = 'customMethod.NonModule';
92+
it('should handle an empty path', () => {
93+
const code = `${name}('', ...args);`;
94+
const result = transform(code, transformerOpts);
95+
96+
expect(result.code).toBe(`${name}("./test/testproject/src", ...args);`);
97+
});
98+
});
8499
});

test/index.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ describe('module-resolver', () => {
1212
expect(result.code).toBe(`import something from "${output}";`);
1313
}
1414

15+
function testWithFunction(functionName, source, output, transformerOpts) {
16+
const code = `${functionName}("${source}");`;
17+
const result = transform(code, transformerOpts);
18+
19+
expect(result.code).toBe(`${functionName}("${output}");`);
20+
}
21+
1522
describe('exports', () => {
1623
describe('resolvePath', () => {
1724
it('should be a function', () => {
@@ -636,9 +643,13 @@ describe('module-resolver', () => {
636643
plugins: [
637644
[pluginWithMock, {
638645
alias: {
646+
'~': './test/testproject/src',
639647
legacy: 'npm:legacy',
640648
'non-existing': 'this-package-does-not-exist',
641649
},
650+
transformFunctions: [
651+
['customResolvePath', { isModulePath: false }],
652+
],
642653
}],
643654
],
644655
};
@@ -670,6 +681,17 @@ describe('module-resolver', () => {
670681
expect(mockWarn).toBeCalledWith(`Could not resolve "this-package-does-not-exist/lib" in file ${fileName}.`);
671682
});
672683

684+
it("shouldn't print a warning for a non-module resolve", () => {
685+
testWithFunction(
686+
'customResolvePath',
687+
'~/libs',
688+
'./test/testproject/src/libs',
689+
missingAliasTransformerOpts,
690+
);
691+
692+
expect(mockWarn.mock.calls.length).toBe(0);
693+
});
694+
673695
describe('production environment', () => {
674696
beforeEach(() => {
675697
process.env.NODE_ENV = 'production';

0 commit comments

Comments
 (0)