sapixdb
v0.1.0
Published
Official JavaScript/TypeScript SDK for SapixDB — the agent-native living database
Maintainers
Readme
SapixDB JavaScript / TypeScript SDK
Official SDK for SapixDB — the agent-native living database.
Zero dependencies. Works in Node.js 18+, Bun, Deno, and modern browsers.
Installation
npm install sapixdb
# or
bun add sapixdbQuick Start
import { SapixClient } from "sapixdb";
const db = new SapixClient({
url: "http://localhost:7475",
agent: "my-app",
});
// Write a record
const record = await db.collection("products").write({
name: "T-Shirt",
price: 29.99,
stock: 100,
});
console.log(record.id); // "nuc_abc123"
console.log(record.hash); // "sha3:e7f2a1..."
// Read latest records
const products = await db.collection("products").latest();
// Filter
const shirts = await db.collection("products").find({ category: "apparel" });
// Time travel — what did the DB look like yesterday?
const yesterday = await db
.collection("orders")
.asOf("2026-05-11T00:00:00Z")
.latest();API Reference
new SapixClient(config)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| url | string | — | SapixDB agent URL |
| agent | string | — | Agent ID (matches SAPIX_AGENT_ID) |
| headers | Record<string,string> | {} | Extra HTTP headers |
| timeout | number | 10000 | Request timeout (ms) |
db.collection(name)
Returns a CollectionClient for the given collection name.
.write(data) → WriteResult
Append a new record. Nothing is ever overwritten.
const result = await db.collection("orders").write({
customer_id: "cust_001",
total: 149.99,
status: "placed",
});
// result.id — nucleotide ID
// result.hash — cryptographic fingerprint
// result.timestamp — ISO 8601 timestamp.writeBatch(records[]) → WriteResult[]
Write multiple records in parallel.
await db.collection("products").writeBatch([
{ name: "T-Shirt", price: 29.99 },
{ name: "Sneakers", price: 89.99 },
]);.get(id) → NucleotideRecord
Fetch a single record by its nucleotide ID.
const record = await db.collection("orders").get("nuc_abc123");
console.log(record.data.status); // "placed".latest(options?) → NucleotideRecord[]
Fetch the latest version of every record in the collection.
.history(options?) → NucleotideRecord[]
Fetch ALL versions — the full append-only history.
.find(filter, options?) → NucleotideRecord[]
Find records matching a filter (latest version only).
const pending = await db.collection("orders").find({ status: "pending" });.findOne(filter) → NucleotideRecord | null
Find the first matching record, or null.
.asOf(timestamp) → CollectionQuery
Scope all subsequent reads to a specific point in time.
// What did Alice's record look like 2 hours ago?
const snapshot = await db
.collection("users")
.asOf("2026-05-12T08:00:00Z")
.find({ name: "Alice" });db.graph
.relate(src, dst, type, weight?) → void
Create a typed directed edge between two records.
await db.graph.relate(orderId, customerId, "placed_by");
await db.graph.relate(productId, categoryId, "belongs_to");
await db.graph.relate(managerId, reportId, "manages", 1.0);.addEdge(edge) → void
Full edge creation with all options.
await db.graph.addEdge({
src: "nuc_abc123",
dst: "nuc_def456",
edge_type: "manages",
weight: 1.0,
});.traverse(fromId, options?) → TraverseResult
Walk the graph from a starting node.
const { nodes, edges } = await db.graph.traverse("nuc_abc123", {
depth: 3,
direction: "outbound", // "outbound" | "inbound" | "both"
});.neighbors(id, direction?) → NucleotideRecord[]
Get direct neighbours of a node.
db.ingest(collection, data) → WriteResult
Write via the ingest endpoint — designed for AI agents, webhooks, and automated pipelines.
await db.ingest("ai_decisions", {
model: "gpt-4o",
action: "approve_loan",
confidence: 0.94,
reasoning: "Credit score 780, DTI 28%",
});db.health() / db.ping()
const { status, agent } = await db.health(); // throws on failure
const alive = await db.ping(); // returns true/false, never throwsTypeScript Generics
Pass your type as a generic to get full autocomplete and type checking:
interface Product {
name: string;
price: number;
stock: number;
category?: string;
}
const products = db.collection<Product>("products");
const result = await products.write({ name: "T-Shirt", price: 29.99, stock: 100 });
const items = await products.latest();
// items[0].data.price is typed as number ✓Error Handling
import { SapixError, SapixNetworkError, SapixNotFoundError } from "sapixdb";
try {
const record = await db.collection("orders").get("nuc_missing");
} catch (err) {
if (err instanceof SapixNotFoundError) {
console.log("Record does not exist");
} else if (err instanceof SapixNetworkError) {
console.log("Cannot reach SapixDB — is it running?");
} else if (err instanceof SapixError) {
console.log(`SapixDB error ${err.status}: ${err.message}`);
}
}Full Example: Online Store
import { SapixClient } from "sapixdb";
const db = new SapixClient({ url: "http://localhost:7475", agent: "store" });
// ── 1. Add products ───────────────────────────────────────────────
const shirt = await db.collection("products").write({
sku: "SHIRT-001", name: "Classic T-Shirt", price: 29.99, stock: 200,
});
const shoes = await db.collection("products").write({
sku: "SHOE-042", name: "Running Sneakers", price: 89.99, stock: 50,
});
// ── 2. Register a customer ────────────────────────────────────────
const customer = await db.collection("customers").write({
name: "Alice Johnson", email: "[email protected]", tier: "standard",
});
// ── 3. Place an order ─────────────────────────────────────────────
const order = await db.collection("orders").write({
customer_id: customer.id,
items: [
{ product_id: shirt.id, qty: 2, unit_price: 29.99 },
{ product_id: shoes.id, qty: 1, unit_price: 89.99 },
],
total: 149.97,
status: "placed",
});
// Link order → customer in the graph
await db.graph.relate(order.id, customer.id, "placed_by");
// ── 4. Ship the order (append, never overwrite) ───────────────────
await db.collection("orders").write({
...order, // same logical entity
status: "shipped",
tracking: "UPS-1Z999AA10123456784",
shipped_at: new Date().toISOString(),
});
// ── 5. Audit: what was the order status 10 minutes ago? ───────────
const tenMinutesAgo = new Date(Date.now() - 10 * 60_000).toISOString();
const snapshot = await db
.collection("orders")
.asOf(tenMinutesAgo)
.find({ customer_id: customer.id });
// → returns the "placed" version, before it was shipped
// ── 6. Graph: find everything this customer is connected to ───────
const { nodes } = await db.graph.traverse(customer.id, {
depth: 2, direction: "inbound",
});
// → returns the order records linked to this customer