Client SDKs

The generated REST client SDKs — TypeScript, Python, Rust, and Go. Typed CRUD over the REST API with a matching ListResult envelope, per-model Create inputs, and typed errors. Pick your ecosystem.

forgedb generate <node|python|rust|go> --sdk emits a typed REST client that mirrors the generated REST contract exactly — the same methods and shapes in every language, because each one wraps the identical HTTP API. node covers Node.js and Bun (they share the generated TypeScript client). Pick your ecosystem with the toggle above; the .forge schema and the REST contract underneath never change.

forgedb generate node --sdk     # → generated/types.ts   (bun --sdk is equivalent)

CRUD methods#

Every SDK exposes a single client with flat, model-suffixed methods — there is no per-model sub-object. For a model Post, each maps one-to-one onto a REST call:

OperationREST callReturns
getGET /api/post/{id}the record, or a null / None / nil miss on 404
listGET /api/posta ListResult envelope
createPOST /api/postthe new id (typed error on 409/422)
updatePUT /api/post/{id}true, or false on 404
deleteDELETE /api/post/{id}true, or false on 404

The method names follow each language's convention:

camelCase, verb-prefixed — getPost / listPost / createPost / updatePost / deletePost — on a ForgeDBClient:

import { ForgeDBClient } from "./generated/types";
 
const db = new ForgeDBClient("http://localhost:3000");
 
const { data, total } = await db.listPost({ limit: 20, sort: "views", order: "desc" });
const id = await db.createPost({ title: "Hello", views: 0 });
const post = await db.getPost(id);            // Post | null
await db.updatePost(id, { ...post!, views: 1 });
await db.deletePost(id);                       // boolean

The list envelope#

list<Model> returns a paginated envelope matching the REST list shape — data, total (the match count before pagination), limit, and offset:

interface ListResult<T> { data: T[]; total: number; limit: number; offset: number; }

The list options accept pagination (limit/offset), sort + order (asc/desc), and a per-field exact-match filter, mapped onto the REST query parameters (see Generated REST API).

Create inputs#

Each model gets a create-input type that omits the server-assigned id; create<Model> takes it and returns the new id (the REST create responds { id }, not the full record):

type PostCreate = Omit<Post, "id">;

Typed errors#

A write failure surfaces as a typed error carrying the HTTP status and the parsed body, so you can branch on 409 (unique / dangling-FK conflict) versus 422 (field constraint). A get / update / delete 404 maps to a null / None / false result instead of raising.

try {
  await db.createPost(input);
} catch (e) {
  if (e instanceof ForgeDBError && e.status === 422) {
    // validation failure — inspect e.body
  }
}

Vendoring & publishing#

The SDK is generated code you vendor into your app, not a registry dependency — regenerating overwrites the client but never the packaging file next to it:

generate node --sdk also emits package.json + tsconfig.json next to types.ts, only if absent — regenerating (even with --force) never clobbers them, so your package metadata is safe to edit. The output is strict tsc --noEmit clean and npm-publishable.

Honest limits (all four SDKs)

Ids are typed as a string uniformly (URL paths are strings — integer-PK callers pass the stringified value); create returns the id, not the full record; and there is no WebSocket / subscription client yet — every SDK is REST-only. For realtime, use the raw WebSocket routes directly.

Search documentation

Find pages across the ForgeDB docs