@folsom/fuse
v0.0.1
Published
TypeScript SDK for the Fuse microVM control plane
Downloads
158
Readme
@folsom/fuse
TypeScript SDK for Fuse — the control plane for agents that deploys and drives Firecracker microVMs over a REST API.
A typed, zero-dependency, ESM client that mirrors the
Go SDK one-to-one. It uses
the platform fetch/streams, so it runs on Node 18+, Deno, Bun, edge runtimes,
and the browser.
Install
npm install @folsom/fuseRequires Node 18+ (for built-in fetch and web streams) or any runtime with
a standard fetch. The package is ESM-only.
TypeScript consumers need the web platform types in scope — either "lib": ["DOM"]
(browsers/bundlers) or @types/node (Node). Any project that uses fetch already
has one of these.
Quickstart
import { FuseClient, isNotFound } from "@folsom/fuse";
const client = new FuseClient({
baseUrl: "https://fuse.example.com",
token: process.env.FUSE_TOKEN, // Authorization: Bearer <token>
});
// Provision a microVM (blocks until running or failed).
const env = await client.environments.create({
task_id: "task-1",
spec: { cpus: 1, ram_mb: 512, storage_gb: 10 },
});
console.log(env.id, env.state, env.url);
// Tail its lifecycle over SSE — the loop ends after a terminal state.
for await (const event of await client.environments.events(env.id)) {
console.log(event.state);
}
// Tear it down.
await client.environments.drain(env.id);
await client.environments.destroy(env.id);Client options
new FuseClient({
baseUrl, // required
token, // optional bearer token
fetch, // optional custom fetch
userAgent, // default: "fuse-ts/<version>" (ignored by browsers)
requestId: () => "...", // optional X-Request-ID generator (per request)
timeoutMs: 60_000, // optional default timeout (NOT applied to events())
headers: { "x-extra": "1" },
});Services
| Service | Methods |
| --------------------- | -------------------------------------------------------------------- |
| client.environments | list, get, create, drain, rotateToken, destroy, events |
| client.snapshots | create, list, get, delete, restore |
| client.hosts | register, list, get, cordon, uncordon, deregister |
| client.apiKeys | create, list, revoke |
Every method accepts a trailing { signal } for cancellation, e.g.
client.environments.list({}, { signal }). Request/response field names are
snake_case, matching the API wire format and the Go SDK.
Errors
Non-2xx responses throw a FuseApiError with status, code, message,
details, and requestId. Use the code helpers instead of comparing strings:
import { isNotFound, isConflict, FuseApiError } from "@folsom/fuse";
try {
await client.environments.get("missing");
} catch (err) {
if (isNotFound(err)) {
// handle 404
} else if (err instanceof FuseApiError) {
console.error(err.code, err.status, err.requestId);
}
}Transport, configuration, and decoding failures throw a FuseError (with a
cause). Helpers: isNotFound, isConflict, isUnauthorized,
isInvalidArgument, isUnavailable, and the isFuseApiError type guard.
Events (SSE)
environments.events(id) returns a promise that rejects on a connect-time error
(e.g. not_found) and otherwise resolves to an AsyncIterable<Event>. The
stream yields the current state first, then each transition, and ends after a
terminal-state event (destroyed/failed). There is no built-in timeout —
pass a signal to cancel:
const ac = new AbortController();
const stream = await client.environments.events(id, { signal: ac.signal });
for await (const event of stream) {
if (event.state === "running") ac.abort();
}API reference
The full REST surface is documented in the repository's OpenAPI spec:
api/openapi.yaml.
License
MIT © Andrew Nijmeh
