Build createORM(models) — a tiny in-memory database with one delegate per model, each exposing basic CRUD. This mirrors the shape of a real ORM like Prisma: you call db.user.create(...), db.post.findMany(...), and each model is reached through its own object hanging off db. There is no SQL and no disk — records are plain JavaScript objects held in arrays in memory.
// models: string[] | Record<string, object>
// Either a list of model names (['user', 'post']) or a definition
// object ({ user: {}, post: {} }) — you support both.
//
// createORM(models) returns an object with ONE delegate per model.
// Each delegate exposes:
// create(data) → stores data with a fresh auto-increment id; returns the record.
// findMany() → every record (an array).
// findMany({ where }) → records where each `where` field equals the record's field (AND).
// findById(id) → the matching record, or null.
// update(id, patch) → shallow-merges patch into the record; returns it, or null if missing.
// delete(id) → removes the record; returns it, or null if missing.
// count() → how many records the model holds.
function createORM(models): Record<string, Delegate>;
const db = createORM(['user', 'post']);
const ada = db.user.create({ name: 'Ada', city: 'London' });
// → { id: 1, name: 'Ada', city: 'London' } (id assigned for you)
db.user.create({ name: 'Grace', city: 'London' }); // → { id: 2, ... }
db.user.findMany({ where: { city: 'London' } });
// → [ { id: 1, name: 'Ada', ... }, { id: 2, name: 'Grace', ... } ]
db.user.update(1, { city: 'Paris' });
// → { id: 1, name: 'Ada', city: 'Paris' } (merged, not replaced)
// ids are per-model: creating users does not advance the post counter.
const db = createORM(['user', 'post']);
db.user.create({ name: 'Ada' }); // → id 1
db.post.create({ title: 'Hello' }); // → id 1 (its own counter)
db.post.count(); // → 1
db.user.count(); // → 1
createORM(['user', 'post']) returns { user, post }, where each value is an object with the seven methods above. Accept both the array form and the { user: {}, post: {} } object form.id: 1, the next id: 2, and so on. Each model counts independently — user ids and post ids do not share a sequence.where is equality only. A record matches when every field in where is strictly equal (===) to that field on the record. Multiple fields are combined with AND. No where (or findMany() with no argument) returns everything.update merges, it doesn't replace. update(1, { city: 'Paris' }) changes only city and leaves the other fields intact. Updating or deleting a missing id returns null rather than throwing.gt, lt, in, contains), no sorting, no field selection, no relations. Equality where and plain CRUD only.