Bun compatibility

Cruft implements a small Bun-compatible slice: the `Bun.serve` HTTP server and the `bun:sqlite` module. Both work. The rest of the Bun API namespace is not implemented, so treat Bun support as those two surfaces, not the whole runtime.

Cruft ships a Bun global and a bun: module scheme so code that uses the two most common Bun entry points can run on Cruft's engine. The surface is deliberately small: Bun.serve and the bun:sqlite module. Both work. Nothing else in the Bun API namespace is implemented, so read Bun support as those two features rather than as the Bun runtime.

The Bun global is a plain object with a single member:

Object.getOwnPropertyNames(Bun); // ["serve"]

Bun.serve

Bun.serve starts an HTTP server that routes each request through a fetch(request) => Response handler:

const server = Bun.serve({
  port: 3000,
  hostname: "127.0.0.1",
  fetch(req) {
    return new Response("hello from cruft");
  },
});
server.address(); // { address: "127.0.0.1", family: "IPv4", port: 3000 }

The handler runs per request and its Response is written back to the client. It is backed by Cruft's node:http server, and that shapes how you interact with the returned handle: it is a Node http.Server, not a Bun Server. In practice:

  • Read the bound port from server.address().port, not server.port (which is undefined).
  • Stop it with server.close(), not server.stop().
  • port and hostname are honored; port: 0 binds an OS-assigned port. Because it is a Node server, server.on("request", ...) also works.
  • The server keeps the process alive; call server.close() or process.exit() to end.

As with the Deno server, a fetch() to the server from its own process does not complete; serve to an external client.

bun:sqlite

The bun:sqlite module implements Bun's SQLite surface:

import { Database } from "bun:sqlite";

const db = new Database(":memory:");
db.run("create table t (a)");
db.run("insert into t values (1), (2)");
db.query("select * from t").all(); // [ { a: 1 }, { a: 2 } ]

Database supports .run() and .query(), and a query exposes .all(). This is a distinct surface from Cruft's other SQLite entry points: node:sqlite exports DatabaseSync/StatementSync, and cruft:sqlite exports open. All three run on the same embedded engine; see the SQL stack.

Limitations

  • Bun.serve and bun:sqlite are the whole surface. Every other Bun.* API is absent (accessing it returns undefined, it does not throw): Bun.file, Bun.write, Bun.spawn, Bun.spawnSync, the Bun.$ shell, Bun.env, Bun.version, Bun.hash, Bun.password, Bun.gzipSync, Bun.Transpiler, Bun.Glob, Bun.SQL, and the rest.
  • Bun.serve returns a Node server, so Bun-native accessors are not present: no server.port, no server.stop(), and no evidence of the websocket, tls, or unix options.
  • Only bun:sqlite resolves under the bun: scheme. bun:ffi, bun:test, bun:jsc, and bun:wrap are not implemented and fail to resolve.

For file access, subprocesses, and the wider host surface, use Cruft's node:* modules or the cruft:* tier, which are the supported paths.