Skip to content

Commit

Permalink
feat(node-resolve): Add the ability to pass a function into resolveOn…
Browse files Browse the repository at this point in the history
…ly (#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.
  • Loading branch information
TotalTechGeek committed Apr 11, 2022
1 parent c24586a commit f561ec1
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 15 deletions.
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));
};

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 &&
!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

0 comments on commit f561ec1

Please sign in to comment.