From ab3faa95146576e59eb3f70bfe2733ef0284950e Mon Sep 17 00:00:00 2001 From: Dunqing Date: Sat, 2 Sep 2023 20:13:20 +0800 Subject: [PATCH 1/3] feat: support `bun` plugin --- package.json | 2 + pnpm-lock.yaml | 73 +++++++++++++++++++++++++ src/bun/index.ts | 134 ++++++++++++++++++++++++++++++++++++++++++++++ src/bun/utils.ts | 135 +++++++++++++++++++++++++++++++++++++++++++++++ src/define.ts | 11 ++++ src/types.ts | 13 +++++ tsconfig.json | 3 +- tsup.config.ts | 1 + 8 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 src/bun/index.ts create mode 100644 src/bun/utils.ts diff --git a/package.json b/package.json index bcf060a6..9caf4b2f 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,8 @@ "@types/node": "^20.5.7", "@types/webpack-sources": "^3.2.0", "bumpp": "^9.2.0", + "bun": "^0.8.1", + "bun-types": "^0.8.1", "conventional-changelog-cli": "^3.0.0", "esbuild": "^0.19.2", "eslint": "^8.48.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 43f43b53..397e228d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,6 +46,12 @@ devDependencies: bumpp: specifier: ^9.2.0 version: 9.2.0 + bun: + specifier: ^0.8.1 + version: 0.8.1 + bun-types: + specifier: ^0.8.1 + version: 0.8.1 conventional-changelog-cli: specifier: ^3.0.0 version: 3.0.0 @@ -786,6 +792,54 @@ packages: fastq: 1.13.0 dev: true + /@oven/bun-darwin-aarch64@0.8.1: + resolution: {integrity: sha512-rdZ4vqDckP/vKjpz5TIEcj45KxIizS6k5dYO6KUOu2nlMwy+JRAE1wfrKY8qAelQ+nE96VYurD8BjkgKQiR4Iw==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@oven/bun-darwin-x64-baseline@0.8.1: + resolution: {integrity: sha512-dSKtbLJ543EqKXgtwKW0h2IjKeInCbpp71GBNKch2azlIl/OSiUDH8xX1XBPq77BjOKSvTv+Morz8TQIFmkXAw==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@oven/bun-darwin-x64@0.8.1: + resolution: {integrity: sha512-/pys7zKcb9A8uTXXZP08iH+0RzHBTqnuBOoG7jtwIOiGwVYbXk47KhEUoAjnexxa+rOL2EuDk8uGeo5YQHe19Q==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@oven/bun-linux-aarch64@0.8.1: + resolution: {integrity: sha512-7jTOMZOfWqBm7x4wreh1y9qW9zelUKXNMI+lQRym47LTaHzNs0bSQlfQuARrMaDFjfCsfOP5ks5ALAWwLVxcsw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@oven/bun-linux-x64-baseline@0.8.1: + resolution: {integrity: sha512-6wYxr+UD/4vH0r3/weoXaJt4LndcCx9PHNeMlPSDJj+xCytQwkSSz5TCSPTlrs6a4iURs8N5+YJAb1kJ71uG5w==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@oven/bun-linux-x64@0.8.1: + resolution: {integrity: sha512-rSYtKj8yxXHzpZ4u8jclHLsbeqldaN1coLjOzs+1q+4mYJXqY5NiJRriPLya3fsSDXnZ9k2h9w0LWvW9ASnUtg==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@pmmmwh/react-refresh-webpack-plugin@0.5.10(react-refresh@0.14.0)(webpack-dev-server@4.13.1)(webpack@5.76.0): resolution: {integrity: sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==} engines: {node: '>= 10.13'} @@ -2058,6 +2112,25 @@ packages: - supports-color dev: true + /bun-types@0.8.1: + resolution: {integrity: sha512-VuCBox66P/3a8gVOffLCWIS6vdpXq4y3eJuF3VnsyC5HpykmIjkcr5wYDn22qQdeTUmOfCcBy1SZmtrZCeUr3A==} + dev: true + + /bun@0.8.1: + resolution: {integrity: sha512-bWVEO9ipiG00dSOtCd/iGZ+LyxuO8l1SBE9uExg/npUQpC0B/ZQlK3whnV05grOd5gQ0wY4oxO75Csdt+g3VZA==} + cpu: [arm64, x64] + os: [darwin, linux] + hasBin: true + requiresBuild: true + optionalDependencies: + '@oven/bun-darwin-aarch64': 0.8.1 + '@oven/bun-darwin-x64': 0.8.1 + '@oven/bun-darwin-x64-baseline': 0.8.1 + '@oven/bun-linux-aarch64': 0.8.1 + '@oven/bun-linux-x64': 0.8.1 + '@oven/bun-linux-x64-baseline': 0.8.1 + dev: true + /bundle-require@4.0.1(esbuild@0.18.11): resolution: {integrity: sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} diff --git a/src/bun/index.ts b/src/bun/index.ts new file mode 100644 index 00000000..9b88c821 --- /dev/null +++ b/src/bun/index.ts @@ -0,0 +1,134 @@ +import fs from 'fs' +import type { SourceMap } from 'rollup' +import type { RawSourceMap } from '@ampproject/remapping' +import type { BunPlugin, UnpluginBuildContext, UnpluginContext, UnpluginContextMeta, UnpluginFactory, UnpluginInstance, UnpluginOptions } from '../types' +import { combineSourcemaps, createBunContext, guessLoader, processCodeWithSourceMap, toArray } from './utils' + +let i = 0 + +export function getBunPlugin>( + factory: UnpluginFactory, +): UnpluginInstance['bun'] { + return (userOptions?: UserOptions): BunPlugin => { + const meta: UnpluginContextMeta = { + framework: 'bun', + } + const plugins = toArray(factory(userOptions!, meta)) + + const setup = (plugin: UnpluginOptions): BunPlugin['setup'] => + plugin.bun?.setup + ?? ((build) => { + meta.build = build + const { onResolve, onLoad, config: initialOptions } = build + + const onResolveFilter = plugin.esbuild?.onResolveFilter ?? /.*/ + const onLoadFilter = plugin.esbuild?.onLoadFilter ?? /.*/ + + const context: UnpluginBuildContext = createBunContext(initialOptions) + + if (plugin.resolveId) { + onResolve({ filter: onResolveFilter }, async (args) => { + if (initialOptions.external?.includes(args.path)) { + // We don't want to call the `resolveId` hook for external modules, since rollup doesn't do + // that and we want to have consistent behaviour across bundlers + return undefined + } + + const isEntry = args.kind === 'entry-point' + const result = await plugin.resolveId!( + args.path, + // We explicitly have this if statement here for consistency with the integration of other bundelers. + // Here, `args.importer` is just an empty string on entry files whereas the euqivalent on other bundlers is `undefined.` + isEntry ? undefined : args.importer, + { isEntry }, + ) + if (typeof result === 'string') + return { path: result, namespace: plugin.name } + else if (typeof result === 'object' && result !== null) + return { path: result.id, external: result.external, namespace: plugin.name } + }) + } + + if (plugin.load || plugin.transform) { + onLoad({ filter: onLoadFilter }, async (args) => { + const id = args.path + + let code: string | undefined, map: SourceMap | null | undefined + + if (plugin.load && (!plugin.loadInclude || plugin.loadInclude(id))) { + const result = await plugin.load.call(context as UnpluginBuildContext & UnpluginContext, id) + if (typeof result === 'string') { + code = result + } + else if (typeof result === 'object' && result !== null) { + code = result.code + map = result.map as any + } + } + + if (!plugin.transform) { + if (code === undefined) { + return { + contents: '', + } + } + + if (map) + code = processCodeWithSourceMap(map, code) + + return { contents: code, loader: guessLoader(args.path) } + } + + if (!plugin.transformInclude || plugin.transformInclude(id)) { + if (!code) { + // caution: 'utf8' assumes the input file is not in binary. + // if you want your plugin handle binary files, make sure to + // `plugin.load()` them first. + code = await fs.promises.readFile(args.path, 'utf8') + } + + const result = await plugin.transform.call(context as UnpluginBuildContext & UnpluginContext, code, id) + if (typeof result === 'string') { + code = result + } + else if (typeof result === 'object' && result !== null) { + code = result.code + // if we already got sourcemap from `load()`, + // combine the two sourcemaps + if (map && result.map) { + map = combineSourcemaps(args.path, [ + result.map as RawSourceMap, + map as RawSourceMap, + ]) as SourceMap + } + else { + // otherwise, we always keep the last one, even if it's empty + map = result.map as any + } + } + } + + if (code) { + if (map) + code = processCodeWithSourceMap(map, code) + return { contents: code, loader: guessLoader(args.path) } + } + + return { + contents: '', + } + }) + } + }) + + const setupMultiplePlugins = (): BunPlugin['setup'] => + (build) => { + for (const plugin of plugins) + setup(plugin)(build) + } + + return plugins.length === 1 + ? { name: plugins[0].name, setup: setup(plugins[0]) } + : { name: meta.bunHostName ?? `unplugin-host-${i++}`, setup: setupMultiplePlugins() } + } +} diff --git a/src/bun/utils.ts b/src/bun/utils.ts new file mode 100644 index 00000000..7df8c781 --- /dev/null +++ b/src/bun/utils.ts @@ -0,0 +1,135 @@ +import fs from 'fs' +import path from 'path' +import { Buffer } from 'buffer' +import remapping from '@ampproject/remapping' +import { Parser } from 'acorn' +import type { DecodedSourceMap, EncodedSourceMap } from '@ampproject/remapping' +import type { Loader, PluginBuilder } from 'bun' +import type { SourceMap } from 'rollup' +import type { UnpluginBuildContext } from '../types' + +export * from '../utils' + +const ExtToLoader: Record = { + '.js': 'js', + '.mjs': 'js', + '.cjs': 'js', + '.jsx': 'jsx', + '.ts': 'ts', + '.cts': 'ts', + '.mts': 'ts', + '.tsx': 'tsx', + '.json': 'json', + '.txt': 'text', + '.toml': 'toml', + '.node': 'napi', +} + +export function guessLoader(id: string): Loader { + return ExtToLoader[path.extname(id).toLowerCase()] || 'file' +} + +// `load` and `transform` may return a sourcemap without toString and toUrl, +// but esbuild needs them, we fix the two methods +export function fixSourceMap(map: EncodedSourceMap): SourceMap { + if (!('toString' in map)) { + Object.defineProperty(map, 'toString', { + enumerable: false, + value: function toString() { + return JSON.stringify(this) + }, + }) + } + if (!('toUrl' in map)) { + Object.defineProperty(map, 'toUrl', { + enumerable: false, + value: function toUrl() { + return `data:application/json;charset=utf-8;base64,${Buffer.from(this.toString()).toString('base64')}` + }, + }) + } + return map as SourceMap +} + +// taken from https://github.com/vitejs/vite/blob/71868579058512b51991718655e089a78b99d39c/packages/vite/src/node/utils.ts#L525 +const nullSourceMap: EncodedSourceMap = { + names: [], + sources: [], + mappings: '', + version: 3, +} +export function combineSourcemaps( + filename: string, + sourcemapList: Array, +): EncodedSourceMap { + sourcemapList = sourcemapList.filter(m => m.sources) + + if ( + sourcemapList.length === 0 + || sourcemapList.every(m => m.sources.length === 0) + ) + return { ...nullSourceMap } + + // We don't declare type here so we can convert/fake/map as EncodedSourceMap + let map // : SourceMap + let mapIndex = 1 + const useArrayInterface + = sourcemapList.slice(0, -1).find(m => m.sources.length !== 1) === undefined + if (useArrayInterface) { + map = remapping(sourcemapList, () => null, true) + } + else { + map = remapping( + sourcemapList[0], + (sourcefile) => { + if (sourcefile === filename && sourcemapList[mapIndex]) + return sourcemapList[mapIndex++] + else + return { ...nullSourceMap } + }, + true, + ) + } + if (!map.file) + delete map.file + + return map as EncodedSourceMap +} + +export function createBunContext(initialOptions: PluginBuilder['config']): UnpluginBuildContext { + return { + parse(code: string, opts: any = {}) { + return Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }) + }, + addWatchFile() { + }, + emitFile(emittedFile) { + // Ensure output directory exists for this.emitFile + if (initialOptions.outdir && !fs.existsSync(initialOptions.outdir)) + fs.mkdirSync(initialOptions.outdir, { recursive: true }) + + const outFileName = emittedFile.fileName || emittedFile.name + if (initialOptions.outdir && emittedFile.source && outFileName) + fs.writeFileSync(path.resolve(initialOptions.outdir, outFileName), emittedFile.source) + }, + getWatchFiles() { + return [] + }, + } +} + +export function processCodeWithSourceMap(map: SourceMap | null | undefined, code: string) { + if (map) { + if (!map.sourcesContent || map.sourcesContent.length === 0) + map.sourcesContent = [code] + + map = fixSourceMap(map as EncodedSourceMap) + code += `\n//# sourceMappingURL=${map.toUrl()}` + } + return code +} diff --git a/src/define.ts b/src/define.ts index 4b7e73cf..c6d73be8 100644 --- a/src/define.ts +++ b/src/define.ts @@ -1,3 +1,4 @@ +import { getBunPlugin } from './bun' import { getEsbuildPlugin } from './esbuild' import { getRollupPlugin } from './rollup' import { getRspackPlugin } from './rspack' @@ -25,6 +26,10 @@ export function createUnplugin( get rspack() { return getRspackPlugin(factory) }, + /** @experimental do not use it in production */ + get bun() { + return getBunPlugin(factory) + }, get raw() { return factory }, @@ -37,6 +42,12 @@ export function createEsbuildPlugin( + factory: UnpluginFactory, +) { + return getBunPlugin(factory) +} + export function createRollupPlugin( factory: UnpluginFactory, ) { diff --git a/src/types.ts b/src/types.ts index 8f7e5d5b..16329ef6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,9 +4,11 @@ import type { Plugin as VitePlugin } from 'vite' import type { Plugin as EsbuildPlugin, PluginBuild } from 'esbuild' import type { Compiler as RspackCompiler, RspackPluginInstance } from '@rspack/core' import type VirtualModulesPlugin from 'webpack-virtual-modules' +import type { BunPlugin, PluginBuilder } from 'bun' export { EsbuildPlugin, + BunPlugin, RollupPlugin, VitePlugin, WebpackPluginInstance, @@ -76,6 +78,11 @@ export interface UnpluginOptions { onLoadFilter?: RegExp setup?: EsbuildPlugin['setup'] } + bun?: { + onResolveFilter?: RegExp + onLoadFilter?: RegExp + setup?: BunPlugin['setup'] + } } export interface ResolvedUnpluginOptions extends UnpluginOptions { @@ -99,6 +106,7 @@ export interface UnpluginInstance webpack: UnpluginFactoryOutput rspack: UnpluginFactoryOutput esbuild: UnpluginFactoryOutput + bun: UnpluginFactoryOutput raw: UnpluginFactory } @@ -114,6 +122,11 @@ export type UnpluginContextMeta = Partial & ({ build?: PluginBuild /** Set the host plugin name of esbuild when returning multiple plugins */ esbuildHostName?: string +} | { + framework: 'bun' + build?: PluginBuilder + /** Set the host plugin name of esbuild when returning multiple plugins */ + bunHostName?: string } | { framework: 'rspack' rspack: { diff --git a/tsconfig.json b/tsconfig.json index 34c5b8ad..34a8cdca 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,8 @@ "declaration": true, "resolveJsonModule": true, "types": [ - "node" + "node", + "bun-types" ], "paths": { "unplugin": [ diff --git a/tsup.config.ts b/tsup.config.ts index 8fafdd81..dad137d9 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -19,6 +19,7 @@ export const tsup: Options = { 'webpack', 'rollup', 'esbuild', + 'bun', ], define: { __DEV__: 'false', From 07173c9a4d322d76748459be6652755f1cce653a Mon Sep 17 00:00:00 2001 From: Dunqing Date: Sat, 9 Sep 2023 08:32:14 +0800 Subject: [PATCH 2/3] chore: upgrade to 1.0 --- package.json | 4 ++-- pnpm-lock.yaml | 52 +++++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 9caf4b2f..ca7eb525 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,8 @@ "@types/node": "^20.5.7", "@types/webpack-sources": "^3.2.0", "bumpp": "^9.2.0", - "bun": "^0.8.1", - "bun-types": "^0.8.1", + "bun": "^1.0.0", + "bun-types": "^1.0.1", "conventional-changelog-cli": "^3.0.0", "esbuild": "^0.19.2", "eslint": "^8.48.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 397e228d..16da09f0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,11 +47,11 @@ devDependencies: specifier: ^9.2.0 version: 9.2.0 bun: - specifier: ^0.8.1 - version: 0.8.1 + specifier: ^1.0.0 + version: 1.0.0 bun-types: - specifier: ^0.8.1 - version: 0.8.1 + specifier: ^1.0.1 + version: 1.0.1 conventional-changelog-cli: specifier: ^3.0.0 version: 3.0.0 @@ -792,48 +792,48 @@ packages: fastq: 1.13.0 dev: true - /@oven/bun-darwin-aarch64@0.8.1: - resolution: {integrity: sha512-rdZ4vqDckP/vKjpz5TIEcj45KxIizS6k5dYO6KUOu2nlMwy+JRAE1wfrKY8qAelQ+nE96VYurD8BjkgKQiR4Iw==} + /@oven/bun-darwin-aarch64@1.0.0: + resolution: {integrity: sha512-aFwqiriquRp2+LOZfLP1sUMRO9ENRGEZuKdhGyd4MeHY9gHZTdPWLqY7ULv91G8jcIrBLGwik6LM28ntuEWodw==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@oven/bun-darwin-x64-baseline@0.8.1: - resolution: {integrity: sha512-dSKtbLJ543EqKXgtwKW0h2IjKeInCbpp71GBNKch2azlIl/OSiUDH8xX1XBPq77BjOKSvTv+Morz8TQIFmkXAw==} + /@oven/bun-darwin-x64-baseline@1.0.0: + resolution: {integrity: sha512-3TzDx34X+PnJJ6vBVhbJ0kNQBC3eeii1RJgHWxuOjLbtP3Jri8KEBoqsbIMGZz7E0hGnr/qzM+WDWf/QcOE3wg==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@oven/bun-darwin-x64@0.8.1: - resolution: {integrity: sha512-/pys7zKcb9A8uTXXZP08iH+0RzHBTqnuBOoG7jtwIOiGwVYbXk47KhEUoAjnexxa+rOL2EuDk8uGeo5YQHe19Q==} + /@oven/bun-darwin-x64@1.0.0: + resolution: {integrity: sha512-DrsSsN94iZPRZmreixDhudoekmDhayd5YF3QEfW8x6orkkHkGhso65AbIn2ZFl0dciuDOV9T7mx2vY03UWwgHA==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@oven/bun-linux-aarch64@0.8.1: - resolution: {integrity: sha512-7jTOMZOfWqBm7x4wreh1y9qW9zelUKXNMI+lQRym47LTaHzNs0bSQlfQuARrMaDFjfCsfOP5ks5ALAWwLVxcsw==} + /@oven/bun-linux-aarch64@1.0.0: + resolution: {integrity: sha512-sVnmDDenV6yx0ob3r06NI8+QvKYxjwGU8b2WGgz4sDnO5n5yt75vEAWOCyXQcfLFfaLgobsdqVCwUP1zRK/w9g==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@oven/bun-linux-x64-baseline@0.8.1: - resolution: {integrity: sha512-6wYxr+UD/4vH0r3/weoXaJt4LndcCx9PHNeMlPSDJj+xCytQwkSSz5TCSPTlrs6a4iURs8N5+YJAb1kJ71uG5w==} + /@oven/bun-linux-x64-baseline@1.0.0: + resolution: {integrity: sha512-McMbKzIaKbQfEcaVC1RYlLmjtrwDZQrmK2mcPyvefb8FOO8Uexk3VyjuNTSJkmJXgX/rqMHB4jGa8YQHxyHBBQ==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@oven/bun-linux-x64@0.8.1: - resolution: {integrity: sha512-rSYtKj8yxXHzpZ4u8jclHLsbeqldaN1coLjOzs+1q+4mYJXqY5NiJRriPLya3fsSDXnZ9k2h9w0LWvW9ASnUtg==} + /@oven/bun-linux-x64@1.0.0: + resolution: {integrity: sha512-mTSy9cerd2dlNgUDQ8fUVmB8fMyshr0KEEwT6hFsPi0ujaT4TVs7JRxbVftsAEb9/j825t3TxXS2O7NC36Di+Q==} cpu: [x64] os: [linux] requiresBuild: true @@ -2112,23 +2112,23 @@ packages: - supports-color dev: true - /bun-types@0.8.1: - resolution: {integrity: sha512-VuCBox66P/3a8gVOffLCWIS6vdpXq4y3eJuF3VnsyC5HpykmIjkcr5wYDn22qQdeTUmOfCcBy1SZmtrZCeUr3A==} + /bun-types@1.0.1: + resolution: {integrity: sha512-7NrXqhMIaNKmWn2dSWEQ50znMZqrN/5Z0NBMXvQTRu/+Y1CvoXRznFy0pnqLe024CeZgVdXoEpARNO1JZLAPGw==} dev: true - /bun@0.8.1: - resolution: {integrity: sha512-bWVEO9ipiG00dSOtCd/iGZ+LyxuO8l1SBE9uExg/npUQpC0B/ZQlK3whnV05grOd5gQ0wY4oxO75Csdt+g3VZA==} + /bun@1.0.0: + resolution: {integrity: sha512-LNqtzM5lg/dHfwORsOEqMNFQUIiYA+txJ8uBUjrgDCHzOPjOzpMQt4ifLEDGj50498WiCXiTdGZfC/BsTa6Pmg==} cpu: [arm64, x64] os: [darwin, linux] hasBin: true requiresBuild: true optionalDependencies: - '@oven/bun-darwin-aarch64': 0.8.1 - '@oven/bun-darwin-x64': 0.8.1 - '@oven/bun-darwin-x64-baseline': 0.8.1 - '@oven/bun-linux-aarch64': 0.8.1 - '@oven/bun-linux-x64': 0.8.1 - '@oven/bun-linux-x64-baseline': 0.8.1 + '@oven/bun-darwin-aarch64': 1.0.0 + '@oven/bun-darwin-x64': 1.0.0 + '@oven/bun-darwin-x64-baseline': 1.0.0 + '@oven/bun-linux-aarch64': 1.0.0 + '@oven/bun-linux-x64': 1.0.0 + '@oven/bun-linux-x64-baseline': 1.0.0 dev: true /bundle-require@4.0.1(esbuild@0.18.11): From 6cfe6aedfb9eda4624b4a510d4dc866f750774ca Mon Sep 17 00:00:00 2001 From: Dunqing Date: Mon, 18 Sep 2023 11:03:04 +0800 Subject: [PATCH 3/3] test: added --- .../id-consistency/id-consistency.test.ts | 27 ++++++++++++++++++- .../write-bundle/write-bundle.test.ts | 18 +++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/test/unit-tests/id-consistency/id-consistency.test.ts b/test/unit-tests/id-consistency/id-consistency.test.ts index 05b4df77..c9c90da9 100644 --- a/test/unit-tests/id-consistency/id-consistency.test.ts +++ b/test/unit-tests/id-consistency/id-consistency.test.ts @@ -3,6 +3,7 @@ import type { Mock } from 'vitest' import { afterEach, describe, expect, it, vi } from 'vitest' import type { UnpluginOptions, VitePlugin } from 'unplugin' import { createUnplugin } from 'unplugin' +import Bun from 'bun' import { build, toArray } from '../utils' const entryFilePath = path.resolve(__dirname, './test-src/entry.js') @@ -25,7 +26,7 @@ function createUnpluginWithCallback( // We extract this check because all bundlers should behave the same function checkHookCalls( - name: 'webpack' | 'rollup' | 'vite' | 'rspack' | 'esbuild', + name: 'webpack' | 'rollup' | 'vite' | 'rspack' | 'esbuild' | 'bun', resolveIdCallback: Mock, transformIncludeCallback: Mock, transformCallback: Mock, @@ -207,4 +208,28 @@ describe('id parameter should be consistent accross hooks and plugins', () => { checkHookCalls('esbuild', mockResolveIdHook, mockTransformIncludeHook, mockTransformHook, mockLoadHook) }) + + it('bun', async () => { + const mockResolveIdHook = vi.fn(() => undefined) + const mockTransformIncludeHook = vi.fn(() => true) + const mockTransformHook = vi.fn(() => undefined) + const mockLoadHook = vi.fn(() => undefined) + + const plugin = createUnpluginWithCallback( + mockResolveIdHook, + mockTransformIncludeHook, + mockTransformHook, + mockLoadHook, + ).bun + + await Bun.build({ + entrypoints: [entryFilePath], + plugins: [plugin()], + // @ts-expect-error - documentation mentions outdir can be false, but types don't allow it + outdir: false, + external: externals, + }) + + checkHookCalls('bun', mockResolveIdHook, mockTransformIncludeHook, mockTransformHook, mockLoadHook) + }) }) diff --git a/test/unit-tests/write-bundle/write-bundle.test.ts b/test/unit-tests/write-bundle/write-bundle.test.ts index 0bacb9f2..665bdbbc 100644 --- a/test/unit-tests/write-bundle/write-bundle.test.ts +++ b/test/unit-tests/write-bundle/write-bundle.test.ts @@ -5,6 +5,7 @@ import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest' import type { UnpluginOptions, VitePlugin } from 'unplugin' import { createUnplugin } from 'unplugin' import type { RspackOptions } from '@rspack/core' +import Bun from 'bun' import { build, toArray, webpackVersion } from '../utils' function createUnpluginWithCallback(writeBundleCallback: UnpluginOptions['writeBundle']) { @@ -168,4 +169,21 @@ describe('writeBundle hook', () => { checkWriteBundleHook(mockResolveIdHook) }) + + it('build', async () => { + expect.assertions(3) + const mockResolveIdHook = vi.fn(generateMockWriteBundleHook(path.resolve(__dirname, 'test-out/bun'))) + const plugin = createUnpluginWithCallback(mockResolveIdHook).bun + + await Bun.build({ + entrypoints: [path.resolve(__dirname, 'test-src/entry.js')], + plugins: [plugin()], + // @ts-expect-error - documentation mentions outfile can be passed, but types don't allow it + outfile: path.resolve(__dirname, 'test-out/bun/output.js'), + format: 'esm', + sourcemap: 'inline', + }) + + checkWriteBundleHook(mockResolveIdHook) + }) })