From 118863ecc4490bb861f030e1702405449da31d62 Mon Sep 17 00:00:00 2001 From: Kevin Deng Date: Sun, 21 Dec 2025 19:37:30 +0800 Subject: [PATCH] feat: add `skipNodeModules` option --- .vscode/settings.json | 3 ++- README.md | 5 ++++- src/index.ts | 11 ++++++++++- tests/index.test.js | 25 ++++++++++++++++++++----- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ad92582..def119e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "editor.formatOnSave": true + "editor.formatOnSave": true, + "typescript.experimental.useTsgo": false } diff --git a/README.md b/README.md index 03387e4..c0319f4 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,10 @@ if (!isSupported) { throw new Error('import-without-cache is not supported in this environment.') } -const deregister = init() +const deregister = init({ + // Optional + skipNodeModules: false, +}) const mod = await import('some-module', { with: { cache: 'no' } }) diff --git a/src/index.ts b/src/index.ts index b7936b7..3653c39 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,8 +6,14 @@ const namespaceLength = namespace.length export const isSupported: boolean = !!module.registerHooks +export interface Options { + skipNodeModules?: boolean +} + +const RE_NODE_MODULES = /[/\\]node_modules[/\\]/ + let deregister: (() => void) | undefined -export function init(): () => void { +export function init({ skipNodeModules }: Options = {}): () => void { if (process.versions.bun) { throw new Error( 'init is unnecessary in Bun, use clearRequireCache() instead.', @@ -28,6 +34,9 @@ export function init(): () => void { } const resolved = nextResolve(specifier, context) + if (skipNodeModules && RE_NODE_MODULES.test(resolved.url)) { + return resolved + } if (!resolved.url.startsWith('file://')) return resolved const parentUUID = getParentUUID(context.parentURL) diff --git a/tests/index.test.js b/tests/index.test.js index 6cee2b7..4344319 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -1,8 +1,14 @@ // @ts-check import assert from 'node:assert' -import { test } from 'node:test' -import { clearRequireCache, init } from '../dist/index.mjs' +import { afterEach, test } from 'node:test' +import { clearRequireCache, init, unregister } from '../dist/index.mjs' + +afterEach(() => { + unregister() +}) + +const RE_NO_CACHE = /\?no-cache=[0-9a-f-]{36}$/ test('import attributes', async () => { const deregister = init() @@ -34,7 +40,7 @@ test('import attributes', async () => { } ) - assert.match(url, /\?no-cache=[0-9a-f-]{36}$/) + assert.match(url, RE_NO_CACHE) // import + ESM assert.notEqual(uuid, uuid2) @@ -95,14 +101,23 @@ test('register twice', () => { deregister3() }) +test('skip node_modules', () => { + const deregister = init({ skipNodeModules: false }) + assert.match(import.meta.resolve('no-cache://tsdown'), RE_NO_CACHE) + deregister() + + const deregister2 = init({ skipNodeModules: true }) + assert.doesNotMatch(import.meta.resolve('no-cache://tsdown'), RE_NO_CACHE) + deregister2() +}) + test('data URL', async () => { const code = 'export const foo = 42' - const deregister = init() + init() const { foo } = await import(`data:text/javascript;base64,${btoa(code)}`, { with: { cache: 'no' }, }) - deregister() assert.equal(foo, 42) }) -- 2.51.2