ProvenPin Install

Kysely + better-sqlite3 typed queries: working versions (tested 2026-10-15)

Type-safe SQL with Kysely on SQLite, including a schema migration, joins and a transaction.

passed1 passed · 0 failed2026-10-15 13:00 UTC
Status
passed
Last passed
2026-10-15 13:00 UTC
Tests
1 / 1
Language
TypeScript
Runtime
node v22.23.3
pinned versions5
kysely@0.29.6better-sqlite3@12.11.1tsx@4.23.15@types/node@24.19.2@types/better-sqlite3@9.6.0
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38738622435

The code

Exactly the files that passed. Your agent can pull them with get_recipe("kysely-sqlite-queries") (install), or see them on GitHub.

package.json
{
  "name": "kysely-sqlite-queries",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --import tsx --test test/*.test.ts"
  },
  "dependencies": {
    "kysely": "0.29.6",
    "better-sqlite3": "12.11.1"
  },
  "devDependencies": {
    "tsx": "4.23.15",
    "@types/node": "24.19.2",
    "@types/better-sqlite3": "9.6.0"
  }
}
src/db.ts
import Database from "better-sqlite3";
import { Kysely, SqliteDialect, type Generated } from "kysely";

interface DB {
  author: { id: Generated<number>; name: string };
  book: { id: Generated<number>; author_id: number; title: string };
}

export async function createDb() {
  const db = new Kysely<DB>({ dialect: new SqliteDialect({ database: new Database(":memory:") }) });
  await db.schema.createTable("author").addColumn("id", "integer", (c) => c.primaryKey().autoIncrement()).addColumn("name", "text", (c) => c.notNull()).execute();
  await db.schema.createTable("book").addColumn("id", "integer", (c) => c.primaryKey().autoIncrement())
    .addColumn("author_id", "integer", (c) => c.notNull().references("author.id")).addColumn("title", "text", (c) => c.notNull()).execute();
  return db;
}

export async function addAuthorWithBooks(db: Kysely<DB>, name: string, titles: string[]) {
  return db.transaction().execute(async (trx) => {
    const { id } = await trx.insertInto("author").values({ name }).returning("id").executeTakeFirstOrThrow();
    for (const title of titles) await trx.insertInto("book").values({ author_id: id, title }).execute();
    return id;
  });
}

export const booksByAuthor = (db: Kysely<DB>, name: string) =>
  db.selectFrom("book").innerJoin("author", "author.id", "book.author_id").select(["book.title"]).where("author.name", "=", name).orderBy("book.title").execute();
test/db.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { createDb, addAuthorWithBooks, booksByAuthor } from "../src/db.ts";

test("transaction insert and join query", async () => {
  const db = await createDb();
  await addAuthorWithBooks(db, "Le Guin", ["The Dispossessed", "A Wizard of Earthsea"]);
  const rows = await booksByAuthor(db, "Le Guin");
  assert.deepEqual(rows.map((r) => r.title), ["A Wizard of Earthsea", "The Dispossessed"]);
  await db.destroy();
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.