Boat.Sandbox reference
ConnectSandbox
Section titled “ConnectSandbox”Source:
packages/boat/src/ConnectSandbox.ts
Work with one Sandbox declared in the stack, from a Worker,
Function or any other host: run commands, read and write files, call its
ports, stop, resume or snapshot it. The handle has the same operations
as the sandboxes CreateSandbox returns, except fork and delete; its
sandboxId is an Effect, read at runtime.
A declared sandbox stops after its autoStop. Calls into it then fail
with SandboxNotRunning until you resume() it.
The host gets its own Boat API key, minted at deploy and revoked when the host is destroyed. The key reaches only this sandbox.
ConnectSandbox: Running commands in a dev box
Section titled “ConnectSandbox: Running commands in a dev box”const devBox = yield* Boat.ConnectSandbox(DevBox);return { fetch: Effect.gen(function* () { yield* devBox.resume({ autoStop: "10 minutes" }); const test = yield* devBox.exec("git pull && npm test", { cwd: "/home/user/repo" }); return yield* HttpServerResponse.json(test); }),};ConnectSandbox: Calling a program in the sandbox
Section titled “ConnectSandbox: Calling a program in the sandbox”Call port 3000
const port = yield* devBox.getTcpPort(3000);const response = yield* port.fetch(HttpClientRequest.get("/health"));Proxy the Worker’s request to port 3000
const port = yield* devBox.getTcpPort(3000);return yield* port.fetch(yield* HttpServerRequest);ConnectSandbox: Stopping it early
Section titled “ConnectSandbox: Stopping it early”yield* devBox.stop();ConnectSandboxHttp
Section titled “ConnectSandboxHttp”Source:
packages/boat/src/ConnectSandboxHttp.tsKind: Layer · Provides:Boat.ConnectSandbox
HTTP implementation of ConnectSandbox: Boat’s REST API with a key
that reaches only the bound sandbox. Works on any host.
ConnectSandboxHttp: Provide the layer
Section titled “ConnectSandboxHttp: Provide the layer”Effect.gen(function* () { const devBox = yield* Boat.ConnectSandbox(DevBox); // ...}).pipe(Effect.provide(Boat.ConnectSandboxHttp))CreateSandbox
Section titled “CreateSandbox”Source:
packages/boat/src/CreateSandbox.ts
Create and manage Boat sandboxes from a Worker, Function or any other host.
Boat.CreateSandbox(snapshot) creates sandboxes from a snapshot declared
in the stack; Boat.CreateSandbox() creates them from scratch, or from
the from each call passes. Both return the same client, whose calls take
Boat’s own parameters.
Sandboxes created at run time are labelled with the stack, stage and
host (alchemy.stack, alchemy.stage, alchemy.id) and are not deleted
when the stack is destroyed. List them by those labels to clean them up:
sandboxes.list({ labels: { "alchemy.stack": "my-app", "alchemy.stage": "prod" } }).
Labels you pass to create merge underneath; they never replace the
alchemy.* ones.
The host gets its own Boat API key, minted at deploy and revoked when the host is destroyed. It may create sandboxes and work in them, and delete only the sandboxes it created; it can’t touch the account’s other sandboxes, environments, keys or billing.
CreateSandbox: Creating sandboxes
Section titled “CreateSandbox: Creating sandboxes”One sandbox per request, deleted when the request ends
const sandboxes = yield* Boat.CreateSandbox();// in fetch:const sandbox = yield* Effect.acquireRelease( sandboxes.create({ type: "small", noEnv: true, autoStop: "10 minutes" }), (sandbox) => Effect.ignore(sandbox.delete()),);const result = yield* sandbox.exec("node --version");From a snapshot declared in the stack
const sandboxes = yield* Boat.CreateSandbox(Golden);const sandbox = yield* sandboxes.create();A long-lived sandbox per task, found by label
const [existing] = yield* sandboxes.list({ labels: { task } });const sandbox = existing ? yield* sandboxes.connect(existing.id) : yield* sandboxes.create({ labels: { task }, autoStop: "30 minutes" });CreateSandbox: Running commands
Section titled “CreateSandbox: Running commands”exec runs to completion and returns { exitCode, stdout, stderr }; a
non-zero exit is returned, not failed. A string runs in a shell, an
array runs its arguments quoted.
A shell line, an argument vector, stdin and a timeout
const test = yield* sandbox.exec("npm test", { cwd: "/home/user/app" });const version = yield* sandbox.exec(["node", "--version"]);const sorted = yield* sandbox.exec("sort", { stdin: "b\na\n" });const slow = yield* sandbox.exec("make", { timeout: "2 minutes" }); // Boat.ExecTimedOutStart a server in the background and stream its output
const server = yield* sandbox.start("npm run dev", { cwd: "/home/user/app" });yield* server.output.pipe( Stream.take(5), Stream.runForEach((chunk) => Effect.log(new TextDecoder().decode(chunk.data))),);CreateSandbox: Calling a port
Section titled “CreateSandbox: Calling a port”const port = yield* sandbox.getTcpPort(3000);return yield* port.fetch(yield* HttpServerRequest);CreateSandbox: Forking and snapshots
Section titled “CreateSandbox: Forking and snapshots”yield* sandbox.stop(); // stopping snapshots itconst copy = yield* sandbox.fork({ autoStop: "10 minutes" });yield* sandbox.resume();CreateSandboxHttp
Section titled “CreateSandboxHttp”Source:
packages/boat/src/CreateSandboxHttp.tsKind: Layer · Provides:Boat.CreateSandbox
HTTP implementation of CreateSandbox: Boat’s REST API with the
host’s own key. Works on any host.
CreateSandboxHttp: Provide the layer
Section titled “CreateSandboxHttp: Provide the layer”Effect.gen(function* () { const sandboxes = yield* Boat.CreateSandbox(); // ...}).pipe(Effect.provide(Boat.CreateSandboxHttp))