Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(node-resolve): Add the ability to pass a function into resolveOnly #1152

Merged
merged 2 commits into from Apr 11, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/node-resolve/README.md
Expand Up @@ -140,12 +140,17 @@ If `true`, inspect resolved files to assert that they are ES2015 modules.

### `resolveOnly`

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

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._

Example: `resolveOnly: ['batman', /^@batcave\/.*$/]`
Alternatively, you may pass in a function that returns a boolean to confirm whether the module should be included or not.

Examples:

- `resolveOnly: ['batman', /^@batcave\/.*$/]`
- `resolveOnly: module => !module.includes('joker')`

### `rootDir`

Expand Down
30 changes: 18 additions & 12 deletions packages/node-resolve/src/index.js
Expand Up @@ -63,13 +63,22 @@ export function nodeResolve(opts = {}) {
options.dedupe.includes(importee) || options.dedupe.includes(getPackageName(importee));
}

const resolveOnly = options.resolveOnly.map((pattern) => {
if (pattern instanceof RegExp) {
return pattern;
}
const normalized = pattern.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
return new RegExp(`^${normalized}$`);
});
// creates a function from the patterns to test if a particular module should be bundled.
const allowPatterns = (patterns) => {
const regexPatterns = patterns.map((pattern) => {
if (pattern instanceof RegExp) {
return pattern;
}
const normalized = pattern.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
return new RegExp(`^${normalized}$`);
});
return (id) => !regexPatterns.length || regexPatterns.some((pattern) => pattern.test(id));
tjenkinson marked this conversation as resolved.
Show resolved Hide resolved
};

const resolveOnly =
typeof options.resolveOnly === 'function'
? options.resolveOnly
: allowPatterns(options.resolveOnly);

const browserMapCache = new Map();
let preserveSymlinks;
Expand Down Expand Up @@ -112,11 +121,8 @@ export function nodeResolve(opts = {}) {
isRelativeImport = true;
}

if (
!isRelativeImport &&
resolveOnly.length &&
tjenkinson marked this conversation as resolved.
Show resolved Hide resolved
!resolveOnly.some((pattern) => pattern.test(id))
) {
// if it's not a relative import, and it's not requested, reject it.
if (!isRelativeImport && !resolveOnly(id)) {
if (normalizeInput(rollupOptions.input).includes(importee)) {
return null;
}
Expand Down
25 changes: 25 additions & 0 deletions packages/node-resolve/test/only.js
Expand Up @@ -68,3 +68,28 @@ test('regex', async (t) => {
t.deepEqual(imports, ['test']);
t.assert(Object.keys(modules).includes(resolve('only-local.js')));
});

test('allows a function as the parameter', async (t) => {
function allowed(...modules) {
const set = new Set(modules);
return (id) => set.has(id);
}

const warnings = [];
const bundle = await rollup({
input: ['only.js'],
onwarn: (warning) => warnings.push(warning),
plugins: [
nodeResolve({
resolveOnly: allowed('test')
})
]
});
const imports = await getImports(bundle);
const modules = await getResolvedModules(bundle);

t.is(warnings.length, 0);
t.snapshot(warnings);
t.deepEqual(imports, ['@scoped/foo', '@scoped/bar']);
t.assert(Object.keys(modules).includes(resolve('only-local.js')));
});
6 changes: 6 additions & 0 deletions packages/node-resolve/test/snapshots/only.js.md
Expand Up @@ -21,3 +21,9 @@ Generated by [AVA](https://avajs.dev).
> Snapshot 1

[]

## allows a function as the parameter

> Snapshot 1

[]
Binary file modified packages/node-resolve/test/snapshots/only.js.snap
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/node-resolve/types/index.d.ts
Expand Up @@ -81,7 +81,7 @@ export interface RollupNodeResolveOptions {
* names match patterns in the array.
* @default []
*/
resolveOnly?: ReadonlyArray<string | RegExp> | null;
resolveOnly?: ReadonlyArray<string | RegExp> | null | ((module: string) => boolean);

/**
* Specifies the root directory from which to resolve modules. Typically used when
Expand Down