Bun
Add Bun runtime to your VMs.
The Bun integration installs Bun, a fast JavaScript runtime and toolkit, and provides helper methods for running code and installing packages.
Installation
npm install @freestyle-sh/with-bun freestyleUsage
import { freestyle, VmSpec } from "freestyle";
import { VmBun } from "@freestyle-sh/with-bun";
const { vm } = await freestyle.vms.create(
new VmSpec().with("js", new VmBun()),
);
const res = await vm.js.runCode({
code: "console.log(JSON.stringify({ hello: 'world' }));"
});
console.log(res);
// { result: { hello: 'world' }, stdout: '{"hello":"world"}\n', statusCode: 0 }Options
new VmBun({
version: "1.1.0", // Optional: specific Bun version (default: latest)
})| Option | Type | Default | Description |
|---|---|---|---|
version | string | undefined | Bun version to install. If not specified, installs the latest version. |
API
vm.js.runCode({ code })
Executes JavaScript/TypeScript code in the Bun runtime.
const res = await vm.js.runCode({
code: `
const data = { sum: 1 + 2, timestamp: Date.now() };
console.log(JSON.stringify(data));
`
});
console.log(res.result); // { sum: 3, timestamp: 1234567890 }Returns: Promise<RunCodeResponse>
type RunCodeResponse<Result> = {
result: Result; // Parsed JSON from stdout (if valid JSON)
stdout?: string; // Raw stdout output
stderr?: string; // Raw stderr output
statusCode?: number; // Exit code
};vm.js.install(options?)
Installs packages using Bun.
// Install from package.json in current directory
await vm.js.install();
// Install from package.json in specific directory
await vm.js.install({ directory: "/app" });
// Install specific packages
await vm.js.install({ deps: ["lodash", "express"] });
// Install with specific versions
await vm.js.install({ deps: { "lodash": "^4.0.0", "express": "~5.0.0" } });
// Install as dev dependencies
await vm.js.install({ deps: ["typescript"], dev: true });
// Install globally
await vm.js.install({ global: true, deps: ["typescript"] });Returns: Promise<InstallResult>
type InstallResult = {
success: boolean;
stdout?: string;
stderr?: string;
};Workspaces and Tasks
Workspaces declaratively define Bun environments so they can be snapshotted and cached for instant startup.
import { freestyle, VmSpec } from "freestyle";
import { VmBun } from "@freestyle-sh/with-bun";
const bun = new VmBun();
const workspace = bun.workspace({ path: "/root/app", install: true });
const devServer = workspace.task("dev", {
env: { HOST: "0.0.0.0", PORT: "3000" },
});
const { vm } = await freestyle.vms.create(
new VmSpec()
.with("bun", bun)
.repo("https://github.com/my-org/my-app", "/root/app")
.with("workspace", workspace)
.with("app", devServer),
);
// Read logs from the running dev server
console.log(await vm.app.logs());Workspace API
const workspace = bun.workspace({
path: "/root/app",
install: true,
});| Option | Type | Default | Description |
|---|---|---|---|
path | string | — | Working directory for bun install and task execution. |
install | boolean | false | When true, runs bun install in the workspace during VM startup. |
Task API
const task = workspace.task("dev", {
env: {
HOST: "0.0.0.0",
PORT: "3000",
},
serviceName: "my-bun-app",
});| Option | Type | Default | Description |
|---|---|---|---|
name | string | — | Script name from package.json (first argument to workspace.task()). |
env | Record<string, string> | undefined | Environment variables for the task service. |
serviceName | string | undefined | Explicit systemd service name. |
When added to the spec with .with("app", task), you can access task logs with vm.app.logs().
Why Bun?
Bun is significantly faster than Node.js for many operations:
- Faster startup - Bun starts up to 4x faster than Node.js
- Faster installs -
bun installis much faster thannpm install - Built-in bundler - No need for webpack or esbuild
- TypeScript support - Run
.tsfiles directly without compilation
Example: Run Code and Get Result
import { freestyle, VmSpec } from "freestyle";
import { VmBun } from "@freestyle-sh/with-bun";
const { vm } = await freestyle.vms.create(
new VmSpec().with("js", new VmBun()),
);
// Run TypeScript code directly
const res = await vm.js.runCode({
code: `
interface User { name: string; age: number }
const user: User = { name: "Alice", age: 30 };
console.log(JSON.stringify(user));
`
});
console.log(res.result); // { name: "Alice", age: 30 }