Skip to content

Commit

Permalink
feat: Allow regex for include and exclude options (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
timfish authored Jul 22, 2024
1 parent 632802f commit 697b0d2
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 13 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ node --import=./my-loader.mjs ./my-code.mjs
```
When registering the loader hook programmatically, it's possible to pass a list
of modules or file URLs to either exclude or specifically include which modules
are intercepted. This is useful if a module is not compatible with the loader
hook.
of modules, file URLs or regular expressions to either exclude or specifically
include which modules are intercepted. This is useful if a module is not
compatible with the loader hook.
```js
import * as module from 'module'

Expand Down
32 changes: 22 additions & 10 deletions hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ function isBareSpecifier (specifier) {
}
}

function isBareSpecifierOrFileUrl (input) {
function isBareSpecifierFileUrlOrRegex (input) {
if (input instanceof RegExp) {
return true
}

// Relative and absolute paths
if (
input.startsWith('.') ||
Expand All @@ -134,15 +138,15 @@ function isBareSpecifierOrFileUrl (input) {
}
}

function ensureArrayWithBareSpecifiersAndFileUrls (array, type) {
function ensureArrayWithBareSpecifiersFileUrlsAndRegex (array, type) {
if (!Array.isArray(array)) {
return undefined
}

const invalid = array.filter(s => !isBareSpecifierOrFileUrl(s))
const invalid = array.filter(s => !isBareSpecifierFileUrlOrRegex(s))

if (invalid.length) {
throw new Error(`'${type}' option only supports bare specifiers and file URLs. Invalid entries: ${inspect(invalid)}`)
throw new Error(`'${type}' option only supports bare specifiers, file URLs or regular expressions. Invalid entries: ${inspect(invalid)}`)
}

return array
Expand Down Expand Up @@ -253,8 +257,8 @@ function createHook (meta) {

async function initialize (data) {
if (data) {
includeModules = ensureArrayWithBareSpecifiersAndFileUrls(data.include, 'include')
excludeModules = ensureArrayWithBareSpecifiersAndFileUrls(data.exclude, 'exclude')
includeModules = ensureArrayWithBareSpecifiersFileUrlsAndRegex(data.include, 'include')
excludeModules = ensureArrayWithBareSpecifiersFileUrlsAndRegex(data.exclude, 'exclude')
}
}

Expand Down Expand Up @@ -283,13 +287,21 @@ function createHook (meta) {
// For included/excluded modules, we check the specifier to match libraries
// that are loaded with bare specifiers from node_modules.
//
// For non-bare specifier imports, we only support matching file URL strings
// because using relative paths would be very error prone!
if (includeModules && !includeModules.some(lib => lib === specifier || lib === result.url.url)) {
// For non-bare specifier imports, we match to the full file URL because
// using relative paths would be very error prone!
function match (each) {
if (each instanceof RegExp) {
return each.test(result.url)
}

return each === specifier || each === result.url
}

if (includeModules && !includeModules.some(match)) {
return result
}

if (excludeModules && excludeModules.some(lib => lib === specifier || lib === result.url.url)) {
if (excludeModules && excludeModules.some(match)) {
return result
}

Expand Down
16 changes: 16 additions & 0 deletions test/register/v18.19-exclude-regex.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { register } from 'module'
import Hook from '../../index.js'
import { strictEqual } from 'assert'

register('../../hook.mjs', import.meta.url, { data: { exclude: [/openai/] } })

const hooked = new Set()

Hook((_, name) => {
hooked.add(name)
})

await import('openai')

strictEqual(hooked.has('openai'), false)
strictEqual(hooked.has('fs'), true)

0 comments on commit 697b0d2

Please sign in to comment.