MikroORM 7 entities and Unit of Work on SQLite: working versions (tested 2026-10-15)
Define MikroORM 7 EntitySchema models with OneToMany relations, persist through the Unit of Work, and query with populate on an in-memory better-sqlite3 database.
passed1 passed · 0 failed2026-10-15 16:02 UTC- Status
- passed
- Last passed
- 2026-10-15 16:02 UTC
- Tests
- 1 / 1
- Language
- TypeScript
- Runtime
- node v22.23.3
npm install --no-audit --no-fund --ignore-scripts=false npm test
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38764699834
The code
Exactly the files that passed. Your agent can pull them with get_recipe("mikroorm-sqlite-entities") (install), or see them on GitHub.
{
"name": "mikroorm-sqlite-entities",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"@mikro-orm/sqlite": "7.2.5",
"better-sqlite3": "13.0.3"
},
"devDependencies": {
"tsx": "4.23.15",
"@types/node": "26.6.5"
}
}
import { Collection, EntitySchema, type Ref } from "@mikro-orm/sqlite";
export class Author {
id!: number;
email!: string;
books = new Collection<Book>(this);
}
export class Book {
id!: number;
title!: string;
author!: Ref<Author>;
}
export const AuthorSchema = new EntitySchema<Author>({
class: Author,
properties: {
id: { type: "number", primary: true, autoincrement: true },
email: { type: "string", unique: true },
books: { kind: "1:m", entity: () => Book, mappedBy: "author" },
},
});
export const BookSchema = new EntitySchema<Book>({
class: Book,
properties: {
id: { type: "number", primary: true, autoincrement: true },
title: { type: "string" },
author: { kind: "m:1", entity: () => Author, ref: true },
},
});
import { MikroORM, defineConfig, ref } from "@mikro-orm/sqlite";
import { Author, AuthorSchema, Book, BookSchema } from "./entities.ts";
export async function createOrm() {
const orm = await MikroORM.init(defineConfig({
entities: [AuthorSchema, BookSchema],
dbName: ":memory:",
allowGlobalContext: true,
}));
await orm.schema.create();
return orm;
}
export async function addAuthorWithBooks(orm: Awaited<ReturnType<typeof createOrm>>, email: string, titles: string[]) {
const em = orm.em.fork();
const author = em.create(Author, { email });
for (const title of titles) em.create(Book, { title, author: ref(author) });
await em.flush();
return author.id;
}
export async function listBooks(orm: Awaited<ReturnType<typeof createOrm>>, email: string) {
const em = orm.em.fork();
const author = await em.findOne(Author, { email }, { populate: ["books"] });
return author?.books.getItems().map((b) => b.title).sort() ?? [];
}
import { test } from "node:test";
import assert from "node:assert/strict";
import { addAuthorWithBooks, createOrm, listBooks } from "../src/db.ts";
test("persists author books and populates", async () => {
const orm = await createOrm();
await addAuthorWithBooks(orm, "[email protected]", ["Dispossessed", "Earthsea"]);
assert.deepEqual(await listBooks(orm, "[email protected]"), ["Dispossessed", "Earthsea"]);
await orm.close();
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.
Related stacks
better-sqlite3 transactions with Zod-validated inputs
A small ledger on better-sqlite3 using db.transaction for atomic transfers, nested transactions as savepoints for all-or-nothing batches, and Zod 4 to validate inputs and rows, tested on in-memory SQLite.
Drizzle ORM + better-sqlite3 CRUD
Typed schema, migrations-free table creation and CRUD with Drizzle on an in-memory SQLite database.
Drizzle ORM + drizzle-zod validated inserts on SQLite
Generate Zod insert and select schemas from Drizzle tables with drizzle-zod, refine them, and validate input before inserting into SQLite.
Hono + Drizzle ORM + SQLite REST API (Vitest)
CRUD REST API in Hono backed by Drizzle ORM on better-sqlite3, with Zod validation, tested with Vitest and app.request().