Skip to content

Table API

The Table API is the ergonomic CRUD layer on top of Database. It is typed when the database has a schema.

Terminal window
const { results: posts } = await database
.table("posts")
.select(["id", "title", "createdAt"])
.where({ authorId })
.orderBy("createdAt", "desc")
.limit(20)
.all()

Calling select() with no arguments returns all columns.

Terminal window
const posts = await database
.table("posts")
.eq("authorId", authorId)
.neq("status", "archived")
.in("status", ["draft", "published"])
.like("title", "%database%")
.gte("createdAt", start)
.lt("createdAt", end)
.all()

Available filters:

  • where({ column: value })
  • eq(column, value)
  • neq(column, value)
  • in(column, values)
  • like(column, value)
  • gt(column, value)
  • gte(column, value)
  • lt(column, value)
  • lte(column, value)
  • isNull(column)
  • isNotNull(column)
Terminal window
const page = await database
.table("posts")
.orderBy("createdAt", "desc")
.limit(25)
.offset(50)
.all()

Cursor-style pagination uses a column, an after value, and an optional limit:

Terminal window
const page = await database
.table("posts")
.cursor({ column: "createdAt", after: cursor, limit: 25 })
.all()
Terminal window
const firstPost = await database.table("posts").first()
const post = await database.table("posts").where({ id }).one()
const maybePost = await database.table("posts").where({ id }).maybeOne()
  • .first() returns the first row or undefined.
  • .one() expects exactly one row.
  • .maybeOne() allows zero or one row.
Terminal window
await database.table("posts").insert({
id: crypto.randomUUID(),
title,
body,
authorId,
}).run()

Insert many rows with one statement:

Terminal window
await database.table("posts").insertMany([
{ id: "post_1", title: "One", body: "...", authorId },
{ id: "post_2", title: "Two", body: "...", authorId },
]).run()
Terminal window
await database
.table("posts")
.update({ title, body })
.where({ id })
.run()

Mutation filters support where(...) and eq(...).

Terminal window
await database.table("posts").upsert(
{
id,
title,
body,
authorId,
},
{
onConflict: ["id"],
},
).run()
Terminal window
await database.table("posts").delete().where({ id }).run()
Terminal window
const count = await database.table("posts").where({ authorId }).count()
const hasDrafts = await database
.table("posts")
.where({ authorId, status: "draft" })
.exists()
Terminal window
await database.transaction((tx) => [
tx.table("posts").update({ status: "published" }).where({ id }),
tx.table("post_events").insert({
id: crypto.randomUUID(),
postId: id,
type: "published",
}),
])

Table API statements and raw SQL statements can be mixed in the same transaction.