Collections
client.collection<T>(name) returns a typed client for a single collection.
Define a type
Section titled “Define a type”interface Post { title: string; body: string; published: boolean; score?: number;}
const posts = client.collection<Post>("posts");Every record is intersected with BunBaseRecord — system fields (_id, _created_at, _updated_at, _owner_id, _deleted_at) are always present.
Create
Section titled “Create”const post = await posts.create({ title: "Hello BunBase", body: "...", published: true,});
console.log(post._id); // "01JKX..." — ULIDconsole.log(post._created_at); // Unix msCreate many in parallel:
const created = await posts.createMany([ { title: "Post 1", published: true }, { title: "Post 2", published: false },]);Rejects if any individual create fails.
const post = await posts.get("01JKX...");Update
Section titled “Update”const updated = await posts.update("01JKX...", { title: "Updated title" });Only provided fields are changed. System fields are ignored.
Delete (soft delete)
Section titled “Delete (soft delete)”await posts.delete("01JKX...");// Sets _deleted_at. Record is hidden from list/get by default.Restore
Section titled “Restore”const post = await posts.restore("01JKX...");const total = await posts.count();const published = await posts.count({ filter: { published: true } });const result = await posts.list({ filter: { published: true }, sort: "-_created_at", limit: 20, page: 1,});
result.items; // (Post & BunBaseRecord)[]result.total; // total matching recordsresult.next_cursor; // cursor for next page (null if last page)Filtering
Section titled “Filtering”Simple equality:
await posts.list({ filter: { published: true } });await posts.list({ filter: { score: 42 } });Operator filters:
await posts.list({ filter: { score: { gte: 10 }, title: { like: "%bunbase%" }, },});| Operator | Meaning |
|---|---|
eq | Equal |
ne | Not equal |
gt | Greater than |
lt | Less than |
gte | Greater than or equal |
lte | Less than or equal |
like | SQL LIKE — use % as wildcard |
in | In array: { status: { in: ["draft", "published"] } } |
Sorting
Section titled “Sorting”await posts.list({ sort: "-_created_at" }); // descendingawait posts.list({ sort: "score,-_created_at" }); // multiple fieldsPrefix - for descending.
Cursor pagination
Section titled “Cursor pagination”More efficient than offset pagination for large datasets:
// Page 1const page1 = await posts.list({ limit: 20 });
// Page 2if (page1.next_cursor) { const page2 = await posts.list({ limit: 20, after: page1.next_cursor });}When after is set, page is ignored.
Field projection
Section titled “Field projection”const result = await posts.list({ fields: ["_id", "title", "published"],});Expand (relations)
Section titled “Expand (relations)”Inline related records declared via the relations API:
// "one" relation — expand the foreign key fieldconst result = await posts.list({ expand: ["author_id"] });// Each post.author_id is now the full user object.
// "many" relation — expand the reverse sideconst user = await client.collection("users").get(id, { expand: ["posts"],});// user.posts is a Post[] array.Include soft-deleted records
Section titled “Include soft-deleted records”const all = await posts.list({ include_deleted: true });Full-text search
Section titled “Full-text search”const results = await posts.list({ search: "hello world" });
// Composable with filters, sort, and pagination:const results = await posts.list({ search: "bun native", filter: { published: true }, sort: "-_created_at", limit: 20,});The search param maps to the server’s FTS5 index. Prefix queries (bun*), phrase queries ("bun native"), and boolean operators (bun AND native) are supported.
Batch operations
Section titled “Batch operations”Run up to 100 create/update/delete operations atomically. All succeed or all roll back.
const results = await posts.batch([ { op: "create", data: { title: "Hello" } }, { op: "update", id: "01JKX...", data: { status: "published" } }, { op: "delete", id: "01JKW..." },]);
// results[0] → { op: "create", record: { _id: "01JKY...", ... } }// results[1] → { op: "update", record: { _id: "01JKX...", ... } }// results[2] → { op: "delete", id: "01JKW..." }If any operation fails, batch() throws a BunBaseError with a 400 status and a message indicating which operation failed.
Channel helpers
Section titled “Channel helpers”posts.channel // "collection:posts"posts.recordChannel(id) // "record:posts:01JKX..."Use with client.realtime.subscribe().
API surface
Section titled “API surface”| Method | Description |
|---|---|
list(query?) | List records with optional filter/sort/page/search |
get(id, options?) | Get a single record |
create(data) | Create a record |
createMany(items[]) | Create multiple records in parallel |
update(id, patch) | Partial update |
delete(id) | Soft-delete |
restore(id) | Restore a soft-deleted record |
count(query?) | Count matching records |
batch(operations[]) | Atomic batch create/update/delete |
channel | Returns the collection channel string |
recordChannel(id) | Returns the record channel string |