Alistair Smith f674d582bc
feat: support bun plugin (#539)
* loose start for bun plugin

* implement bun

* support emitFile()

* fix Bun cases in integration test

* add bun to other test files

* remove bun-types-no-globals from github

* restore bun-types-no-globals from npm @^1.2

* bun does not yet support .onEnd, so for now we shouldn't fake it with brittle workarounds

* add Bun in the documentation

* some missing bun references in docs

* support multiple plugins

* use Bun namespace instead of importing module that won't necessarily exist

* Bun is a cute pink color!

* fix the transform hook

* fix for virtual modules

* tidy up

* setup bun in ci

* revert unplugin require path

* ignore bun in test-out folders

* update tests

* support onEnd

* remove

* implement guessLoader(), bun also now supports onEnd()

* don't eat errors/warnings

* we dont need to outdir for bun in this test

* bun writebundle test

* Update to bun@1.2.22 (supports onEnd and onResolve)

* use onStart()

* define onStart() in mocks

* onStart

* ci: run vitest in Bun so we can run bun's tests

* Bun error message if building outside of Bun

* skip bun specific tests when not running in bun

* refactor

* allow only

* ci: fix typecheck

---------

Co-authored-by: Kevin Deng <sxzz@sxzz.moe>
2025-11-03 18:30:00 +08:00

68 lines
1.7 KiB
JavaScript

const MagicString = require('magic-string')
const { createUnplugin } = require('unplugin')
module.exports = createUnplugin((options, meta) => {
return [
{
name: 'transform-fixture-pre',
resolveId(id) {
// Rollup and Bun don't know how to import module with query string so we ignore the module
if (id.includes('?query-param=query-value') && (meta.framework === 'rollup' || meta.framework === 'bun')) {
return {
id,
external: true,
}
}
},
transformInclude(id) {
return id.match(/[/\\]target\.js$/) || id.includes('?query-param=query-value')
},
transform(code, id) {
const s = new MagicString(code)
const index = code.indexOf('__UNPLUGIN__')
if (index === -1)
return null
const injectedCode = `[Injected ${options.msg}]`
if (id.includes(injectedCode))
throw new Error('File was already transformed')
s.overwrite(index, index + '__UNPLUGIN__'.length, injectedCode)
return {
code: s.toString(),
map: s.generateMap({
source: id,
includeContent: true,
}),
}
},
},
{
name: 'transform-fixture-post',
transformInclude(id) {
return id.match(/[/\\]target\.js$/) || id.includes('?query-param=query-value')
},
transform(code, id) {
if (!code.includes('Injected'))
return null
const s = new MagicString(code)
s.replace(
'Injected',
'Injected Post',
)
return {
code: s.toString(),
map: s.generateMap({
source: id,
includeContent: true,
}),
}
},
},
]
})