Skip to Content

From Bun

3va and Bun overlap a lot: one binary for runtime, package manager, test runner and bundler, with TypeScript out of the box. The difference is the security model. Bun trusts everything by default; 3va denies everything by default.

Run on Bun’s node_modules

bun install 3va run server.js --allow-read=./node_modules --allow-net=127.0.0.1

Tested with Bun 1.3 and Express 4: the node_modules Bun writes runs unchanged under 3va.

What needs rewriting

Bun3va
Bun.serve({ fetch })http.createServer() (Node API)
Bun.file(path).text()fs.promises.readFile(path, "utf-8")
Bun.write(path, data)fs.promises.writeFile(path, data)
Bun.spawn()child_process.spawn() + --allow-child-process
bun:sqlitenode:sqlite (works under 3va)
bun:test imports3va test globals (describe, test, expect)
Bun.env.Xprocess.env.X + --allow-env=X

Bun isn’t defined in 3va: typeof Bun === "undefined". The Web APIs Bun code often uses are available: fetch, Request, Response, WebSocket, crypto.randomUUID(), structuredClone, web streams, URLPattern, import.meta.dirname, import.meta.main.

Lockfile

  • 3va migrate converts the text bun.lock (Bun ≥ 1.2): Would migrate bun.lock → 3va-lock.json (68 package(s)). The old binary bun.lockb can’t be converted. Run bun install --save-text-lockfile first to get a bun.lock.
  • The 3va <script> fallback only detects bun.lockb. With the text bun.lock, scripts are delegated to npm, not Bun.

Tests

bun test files that import from "bun:test" need that import removed. describe/test/expect/beforeEach are globals in 3va test. Snapshot files use a different format (.snap.json) and are regenerated.

Things to keep in mind

  • Top-level await works from 2.12.1. In 3va 2.9.0 (the version this guide was measured on), const x = await promise at module top level gave you the Promise itself, not its value, and a file with top-level await but no import/export failed to parse. Both are fixed in 2.12.1; on older versions wrap it in an async function.
  • bun build --compile has no equivalent. 3va bundle produces a single JS file, not a standalone executable.