Skip to content

Commit f561ec1

Browse files
feat(node-resolve): Add the ability to pass a function into resolveOnly (#1152)
* feat(node-resolve): Add the ability to pass a function into resolveOnly to resolve issue #1150 * Add a missing piece of text to the readme.
1 parent c24586a commit f561ec1

File tree

6 files changed

+57
-15
lines changed

6 files changed

+57
-15
lines changed

packages/node-resolve/README.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,17 @@ If `true`, inspect resolved files to assert that they are ES2015 modules.
140140

141141
### `resolveOnly`
142142

143-
Type: `Array[...String|RegExp]`<br>
143+
Type: `Array[...String|RegExp] | (module: string) => boolean`<br>
144144
Default: `null`
145145

146146
An `Array` which instructs the plugin to limit module resolution to those whose names match patterns in the array. _Note: Modules not matching any patterns will be marked as external._
147147

148-
Example: `resolveOnly: ['batman', /^@batcave\/.*$/]`
148+
Alternatively, you may pass in a function that returns a boolean to confirm whether the module should be included or not.
149+
150+
Examples:
151+
152+
- `resolveOnly: ['batman', /^@batcave\/.*$/]`
153+
- `resolveOnly: module => !module.includes('joker')`
149154

150155
### `rootDir`
151156

packages/node-resolve/src/index.js

+18-12
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,22 @@ export function nodeResolve(opts = {}) {
6363
options.dedupe.includes(importee) || options.dedupe.includes(getPackageName(importee));
6464
}
6565

66-
const resolveOnly = options.resolveOnly.map((pattern) => {
67-
if (pattern instanceof RegExp) {
68-
return pattern;
69-
}
70-
const normalized = pattern.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
71-
return new RegExp(`^${normalized}$`);
72-
});
66+
// creates a function from the patterns to test if a particular module should be bundled.
67+
const allowPatterns = (patterns) => {
68+
const regexPatterns = patterns.map((pattern) => {
69+
if (pattern instanceof RegExp) {
70+
return pattern;
71+
}
72+
const normalized = pattern.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
73+
return new RegExp(`^${normalized}$`);
74+
});
75+
return (id) => !regexPatterns.length || regexPatterns.some((pattern) => pattern.test(id));
76+
};
77+
78+
const resolveOnly =
79+
typeof options.resolveOnly === 'function'
80+
? options.resolveOnly
81+
: allowPatterns(options.resolveOnly);
7382

7483
const browserMapCache = new Map();
7584
let preserveSymlinks;
@@ -112,11 +121,8 @@ export function nodeResolve(opts = {}) {
112121
isRelativeImport = true;
113122
}
114123

115-
if (
116-
!isRelativeImport &&
117-
resolveOnly.length &&
118-
!resolveOnly.some((pattern) => pattern.test(id))
119-
) {
124+
// if it's not a relative import, and it's not requested, reject it.
125+
if (!isRelativeImport && !resolveOnly(id)) {
120126
if (normalizeInput(rollupOptions.input).includes(importee)) {
121127
return null;
122128
}

packages/node-resolve/test/only.js

+25
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,28 @@ test('regex', async (t) => {
6868
t.deepEqual(imports, ['test']);
6969
t.assert(Object.keys(modules).includes(resolve('only-local.js')));
7070
});
71+
72+
test('allows a function as the parameter', async (t) => {
73+
function allowed(...modules) {
74+
const set = new Set(modules);
75+
return (id) => set.has(id);
76+
}
77+
78+
const warnings = [];
79+
const bundle = await rollup({
80+
input: ['only.js'],
81+
onwarn: (warning) => warnings.push(warning),
82+
plugins: [
83+
nodeResolve({
84+
resolveOnly: allowed('test')
85+
})
86+
]
87+
});
88+
const imports = await getImports(bundle);
89+
const modules = await getResolvedModules(bundle);
90+
91+
t.is(warnings.length, 0);
92+
t.snapshot(warnings);
93+
t.deepEqual(imports, ['@scoped/foo', '@scoped/bar']);
94+
t.assert(Object.keys(modules).includes(resolve('only-local.js')));
95+
});

packages/node-resolve/test/snapshots/only.js.md

+6
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,9 @@ Generated by [AVA](https://avajs.dev).
2121
> Snapshot 1
2222
2323
[]
24+
25+
## allows a function as the parameter
26+
27+
> Snapshot 1
28+
29+
[]
23 Bytes
Binary file not shown.

packages/node-resolve/types/index.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface RollupNodeResolveOptions {
8181
* names match patterns in the array.
8282
* @default []
8383
*/
84-
resolveOnly?: ReadonlyArray<string | RegExp> | null;
84+
resolveOnly?: ReadonlyArray<string | RegExp> | null | ((module: string) => boolean);
8585

8686
/**
8787
* Specifies the root directory from which to resolve modules. Typically used when

0 commit comments

Comments
 (0)