Getting Started
Install, define your schema, and run your first queries.
Install
pnpm add async-idb-orm
# or npm / yarn / bun
Define schema and DB
// db.ts
import { idb, Collection, Selector } from "async-idb-orm"
type User = {
id: string
name: string
age: number
createdAt: number
updatedAt?: number
}
type UserDTO = {
name: string
age: number
}
const users = Collection.create<User, UserDTO>()
.withKeyPath("id") // optional — defaults to "id" if present
.withIndexes([
{ key: "age", name: "idx_age" },
{ key: ["name", "age"], name: "idx_name_id" },
])
.withTransformers({
create: (dto) => ({
...dto,
id: crypto.randomUUID(),
createdAt: Date.now(),
}),
update: (updatedRecord) => ({
...updatedRecord,
updatedAt: Date.now(),
}),
})
withKeyPath is optional when your record has an id field. Use it (and optionally autoIncrement: true) when the key is different or auto-generated:
type Post = { id: number; text: string; userId: string }
const posts = Collection.create<Post>().withKeyPath("id", { autoIncrement: true })
Wire schema (and optional relations/selectors) into the DB:
const schema = { users, posts }
const relations = {} // see Relations section
const userSummary = Selector.create<typeof schema, typeof relations>().as(async (ctx) => {
const allUsers = await ctx.users.all()
return {
totalUsers: allUsers.length,
averageAge: allUsers.reduce((sum, user) => sum + user.age, 0) / allUsers.length || 0,
userNames: allUsers.map((user) => user.name),
}
})
export const db = idb("users", {
schema,
relations,
selectors: { userSummary },
version: 1,
})
Basic usage
// app.ts
import { db } from "$/db"
const user = await db.collections.users.create({ name: "Bob Smith", age: 69 })
// ^? User
await db.collections.users.update({ ...user, age: 42 })
await db.collections.users.find(user.id)
await db.collections.users.find((user) => user.name === "Bob Smith")
await db.collections.users.delete(user.id)
await db.collections.users.deleteMany((user) => user.age < 25)
await db.collections.users.all()
await db.collections.users.findMany((user) => user.age > 25)
await db.collections.users.count()
await db.collections.users.latest()
const oldestUser = await db.collections.users.max("idx_age")
const youngestUser = await db.collections.users.min("idx_age")
import { range } from "async-idb-orm"
const usersYoungerThan30 = await db.collections.users.getIndexRange("idx_age", range`< ${30}`)
const summary = await db.selectors.userSummary.get()
const unsubscribe = db.selectors.userSummary.subscribe((summary) => {
console.log(`Total users: ${summary.totalUsers}, Average age: ${summary.averageAge}`)
})
From here you can add Key Ranges, Relations, Selectors, and the rest of the docs as needed.