kindstore
v0.3.7
Published
A lightweight, typed document store on SQLite with Zod schemas, indexed queries, and explicit migrations.
Maintainers
Readme
kindstore
kindstore is a registry-driven document store for Bun and SQLite. You define document kinds with Zod, declare which top-level fields are queryable, and keep payload and schema migrations explicit.
Requires Bun at runtime because kindstore uses bun:sqlite.
bun add kindstore zodThe skills.sh command line tool makes it easy to teach your favorite coding agent how to use Kindstore:
npx skills add alloc/kindstoreimport { z } from "zod";
import {
kind,
kindstore,
type KindInput,
type KindOutput,
} from "kindstore";
const Post = z.object({
authorId: z.string(),
slug: z.string(),
title: z.string(),
status: z.enum(["draft", "published"]),
});
const db = kindstore({
filename: ":memory:",
schema: {
posts: kind("pst", Post)
.updatedAt()
.index("authorId")
.index("slug")
.index("status")
.index("updatedAt"),
},
});
const id = db.posts.newId();
db.posts.put(id, {
authorId: "usr_1",
slug: "hello-kindstore",
title: "Hello, kindstore",
status: "published",
});
const publishedPosts = db.posts.findMany({
where: { status: "published" },
orderBy: { updatedAt: "desc" },
});
const firstPage = db.posts.findPage({
where: { status: "published" },
orderBy: { updatedAt: "desc" },
limit: 20,
});
type PostInput = KindInput<typeof db.schema.posts>;
type PostOutput = KindOutput<typeof db.schema.posts>;That example covers the happy path, but kindstore also supports:
- one-step document creation with
create()when you want kindstore to allocate the ID - full-document replacement and targeted updates with
get(),put(),update(), anddelete()in the same typed collection API - lazy query iteration with
iterate()when you want incremental processing instead of materializing every result - compound indexes with
.multi(...)for query shapes likestatus + updatedAtoruserId + id - access to the declared kind builders through
db.schema - typed store-level metadata via
db.metadata - atomic multi-write workflows with
db.batch(...) - raw SQLite access through
db.rawwhen you need an escape hatch - eager payload migrations with kind-level
.migrate(version, steps) - explicit structural migrations for renames, drops, and tag changes with top-level
migrate(...)
Next:
- Start with the intermediate guides in docs/course/README.md
- Read the maintainer-facing system docs in docs/architecture-overview.md
