Skip to content

Commit 20f7ed2

Browse files
committed
Add ignore option to builtinsPrefix setting
1 parent c8bd534 commit 20f7ed2

File tree

8 files changed

+348
-295
lines changed

8 files changed

+348
-295
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export default {
5353
builtins?: boolean
5454

5555
// node: prefix handing for importing Node builtins. Default: 'add'.
56-
builtinsPrefix?: 'add' | 'strip'
56+
builtinsPrefix?: 'add' | 'strip' | 'ignore'
5757

5858
// The path(s) to your package.json. See below for default.
5959
packagePath?: string | string[]
@@ -83,10 +83,11 @@ export default {
8383
#### builtins?: boolean = true
8484
Set the `builtins` option to `false` if you'd like to use some shims/polyfills for those. You'll most certainly need [an other plugin](https://github.com/ionic-team/rollup-plugin-node-polyfills) for this.
8585

86-
#### builtinsPrefix?: 'add' | 'strip' = 'add'
86+
#### builtinsPrefix?: 'add' | 'strip' | 'ignore' = 'add'
8787
How to handle the `node:` scheme used in recent versions of Node (i.e., `import path from 'node:path'`).<br>
8888
- If `add` (the default), the `node:` prefix is always added. In effect, this homogenizes all your imports of node builtins to their prefixed version.
8989
- If `strip` (the default), the import is always resolved unprefixed. In effect, this homogenizes all your imports of node builtins to their unprefixed version.
90+
- `ignore` will simply leave all prefixes as written in your code.
9091
> _Note that prefix handling is independant of the `builtins` options being enabled or disabled._
9192
9293
#### packagePath?: string | string[] = []

package-lock.json

Lines changed: 242 additions & 226 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ export interface ExternalsOptions {
1919
* node: prefix handing for importing Node builtins:
2020
* - `'add'` turns `'path'` to `'node:path'`
2121
* - `'strip'` turns `'node:path'` to `'path'`
22+
* - `'ignore'` leave Node builtin names as-is
2223
*
2324
* Defaults to `add`.
2425
*/
25-
builtinsPrefix?: 'add' | 'strip'
26+
builtinsPrefix?: 'add' | 'strip' | 'ignore'
2627

2728
/**
2829
* Path/to/your/package.json file (or array of paths).
@@ -140,7 +141,7 @@ function externals(options: ExternalsOptions = {}): Plugin {
140141
async buildStart() {
141142
// Map the include and exclude options to arrays of regexes.
142143
[ include, exclude ] = ([ 'include', 'exclude' ] as const).map(option =>
143-
([] as (string | RegExp | null | undefined | false)[])
144+
([] as Array<string | RegExp | null | undefined | false>)
144145
.concat(config[option])
145146
.reduce((result, entry, index) => {
146147
if (entry) {
@@ -192,7 +193,7 @@ function externals(options: ExternalsOptions = {}): Plugin {
192193
try {
193194
const json = (await fs.readFile(packageFile)).toString()
194195
try {
195-
const pkg = JSON.parse(json) as PackageJson
196+
const pkg: PackageJson = JSON.parse(json)
196197
Object.assign(dependencies,
197198
config.deps ? pkg.dependencies : undefined,
198199
config.devDeps ? pkg.devDependencies : undefined,
@@ -229,23 +230,25 @@ function externals(options: ExternalsOptions = {}): Plugin {
229230
},
230231

231232
async resolveId(id) {
232-
// Ignore virtual modules and already resolved ids.
233-
if (id.charCodeAt(0) === 0 || path.isAbsolute(id))
233+
// Let Rollup handle already resolved ids, relative imports and virtual modules.
234+
if (path.isAbsolute(id) || /^(?:\0|\.{1,2}[\\/])/.test(id))
234235
return null
235236

236237
// Handle node builtins.
237238
if (id.startsWith(nodePrefix) || builtins.all.has(id)) {
238239
const stripped = id.replace(nodePrefixRx, '')
239240
return {
240-
id: config.builtinsPrefix === 'add' || builtins.alwaysPrefixed.has(id)
241-
? nodePrefix + stripped
242-
: stripped,
243-
external: (config.builtins || isIncluded(id)) && !isExcluded(id),
241+
id: config.builtinsPrefix === 'ignore'
242+
? id
243+
: config.builtinsPrefix === 'add' || builtins.alwaysPrefixed.has(id)
244+
? nodePrefix + stripped
245+
: stripped,
246+
external: config.builtins && !isExcluded(id),
244247
moduleSideEffects: false
245248
}
246249
}
247250

248-
// Handle other imports.
251+
// Handle npm dependencies.
249252
return isIncluded(id) && !isExcluded(id)
250253
? false // external
251254
: null // normal handling

test/_common.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ type ImplementedHooks =
2525
| 'buildStart'
2626
| 'resolveId'
2727

28+
// This config makes for empty include[] and exclude[] patterns.
29+
export const noDepsAtAllOptions: ExternalsOptions = {
30+
packagePath: path.join(__dirname, 'fixtures/no-deps.package.json'),
31+
builtins: false,
32+
deps: false,
33+
devDeps: false,
34+
optDeps: false,
35+
peerDeps: false
36+
}
37+
2838
export async function callHook(plugin: Plugin, hookName: ImplementedHooks, ...args: any[]) {
2939
const hook = plugin[hookName] as ObjectHook<(this: typeof fakePluginContext, ...args: any) => any>
3040
if (typeof hook === 'function')

test/builtins.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,17 @@ test("Removes 'node:' prefix when using builtinsPrefix='strip'", async t => {
2222
})
2323
}
2424
})
25+
26+
test("Ignores 'node:' prefix when using builtinsPrefix='ignore'", async t => {
27+
const { plugin } = await initPlugin({
28+
builtinsPrefix: 'ignore'
29+
})
30+
t.like(await callHook(plugin, 'resolveId', 'node:path'), {
31+
id: 'node:path',
32+
external: true
33+
})
34+
t.like(await callHook(plugin, 'resolveId', 'path'), {
35+
id: 'path',
36+
external: true
37+
})
38+
})

test/fixtures/no-deps.package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"workspaces": []
3+
}

test/relative.test.ts

Lines changed: 0 additions & 57 deletions
This file was deleted.

test/specifier.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import test from 'ava'
2+
import { initPlugin, callHook, noDepsAtAllOptions } from './_common'
3+
4+
test("Does NOT filter out relative specifiers by default", async t => {
5+
const relativeSpecifiers = [ './sibling.js', '../parent.js' ]
6+
const { plugin } = await initPlugin(noDepsAtAllOptions)
7+
for (const specifier of relativeSpecifiers) {
8+
t.is(await callHook(plugin, 'resolveId', specifier), null, `Failed id: ${specifier}`)
9+
}
10+
})
11+
12+
test("Does NOT filter out relative specifiers, even when asked to", async t => {
13+
const relativeSpecifiers = [ './sibling.js', '../parent.js' ]
14+
const { plugin } = await initPlugin({
15+
...noDepsAtAllOptions,
16+
include: relativeSpecifiers
17+
})
18+
for (const specifier of relativeSpecifiers) {
19+
t.is(await callHook(plugin, 'resolveId', specifier), null, `Failed id: ${specifier}`)
20+
}
21+
})
22+
23+
test("Does NOT filter out absolute specifiers by default", async t => {
24+
const absoluteSpecifiers = [ '/root.js' ]
25+
if (process.platform === 'win32')
26+
absoluteSpecifiers.push('\\root.js', 'C:\\root.js')
27+
const { plugin } = await initPlugin(noDepsAtAllOptions)
28+
for (const specifier of absoluteSpecifiers) {
29+
t.is(await callHook(plugin, 'resolveId', specifier), null, `Failed id: ${specifier}`)
30+
}
31+
})
32+
33+
test("Does NOT filter out absolute specifiers, even when asked to", async t => {
34+
const absoluteSpecifiers = [ '/root.js' ]
35+
if (process.platform === 'win32')
36+
absoluteSpecifiers.push('\\root.js', 'C:\\root.js')
37+
const { plugin } = await initPlugin({
38+
...noDepsAtAllOptions,
39+
include: absoluteSpecifiers
40+
})
41+
for (const specifier of absoluteSpecifiers) {
42+
t.is(await callHook(plugin, 'resolveId', specifier), null, `Failed id: ${specifier}`)
43+
}
44+
})
45+
46+
test("Does NOT filter out bare specifiers by default", async t => {
47+
const bareSpecifiers = [ 'dependency' ]
48+
const { plugin } = await initPlugin(noDepsAtAllOptions)
49+
for (const specifier of bareSpecifiers) {
50+
t.is(await callHook(plugin, 'resolveId', specifier), null, `Failed id: ${specifier}`)
51+
}
52+
})
53+
54+
test("Filters out bare specifiers when asked to", async t => {
55+
const bareSpecifiers = [ 'bare' ]
56+
const { plugin } = await initPlugin({
57+
...noDepsAtAllOptions,
58+
include: bareSpecifiers
59+
})
60+
for (const specifier of bareSpecifiers) {
61+
t.is(await callHook(plugin, 'resolveId', specifier), false, `Failed id: ${specifier}`)
62+
}
63+
})

0 commit comments

Comments
 (0)