Work with data
Create, read, update, delete and subscribe to records with ds.entities.
Create, read, update, delete and subscribe to records with ds.entities.
// Create
const task = await ds.entities.Task.create({ title: "Ship it" });
await ds.entities.Task.bulkCreate([{ title: "A" }, { title: "B" }]);
// Read
const all = await ds.entities.Task.list(); // newest first
const sorted = await ds.entities.Task.list("-priority", 20);
const open = await ds.entities.Task.filter({ done: false }, "-created_date", 50);
const one = await ds.entities.Task.get(task.id);
const n = await ds.entities.Task.count({ done: true });
// Update
await ds.entities.Task.update(task.id, { done: true });
await ds.entities.Task.updateMany({ done: false }, { priority: "high" });
await ds.entities.Task.bulkUpdate([{ id: a.id, done: true }, { id: b.id, done: false }]);
// Delete
await ds.entities.Task.delete(task.id);
await ds.entities.Task.deleteMany({ done: true });
// Live list: called now and again the moment anyone changes a matching record.
// Returns an unsubscribe function (call it when the component unmounts).
const stop = ds.entities.Task.subscribe((tasks) => setTasks(tasks), { done: false });
// Single change events: { type: "create" | "update" | "delete", id, data, timestamp }
const off = ds.entities.Task.onChange((e) => console.log(`${e.id} was ${e.type}d`, e.data));
Signatures: list(sort?, limit?, skip?) and filter(query, sort?, limit?, skip?). Query syntax is described in Entities overview. Results only include records the current user may read; writes the user isn't allowed to make throw a 403 DraftshipError.
"use client";
import { useEffect, useState } from "react";
import { ds, type DsRecord } from "@/lib/draftship";
export function Tasks() {
const [tasks, setTasks] = useState<DsRecord[] | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
ds.entities.Task.list().then(setTasks).catch((e) => setError(e.message));
}, []);
if (error) return <p>{error}</p>;
if (!tasks) return <p>Loading…</p>;
return <ul>{tasks.map((t) => <li key={t.id}>{String(t.title)}</li>)}</ul>;
}
Live updates arrive over one shared connection per page (server-sent events from /_ds/realtime). Each person only receives changes to records they're allowed to read, with hidden fields removed, exactly like a normal read. The connection reconnects automatically and switches permissions when someone signs in or out.
Outside the SDK you can listen directly:
curl -N "https://<your-app>/_ds/realtime?entities=Task,Note" -H "Authorization: Bearer <token>"
delete and deleteMany move records to the trash, where they stay for 30 days. Owners can restore them from Dashboard → Backups & trash.