Skip to content

refactor(util): let a collection cast its own ids (#821 spike) - #917

Draft
rmdes wants to merge 1 commit into
mainfrom
spike/sqlite-collection
Draft

refactor(util): let a collection cast its own ids (#821 spike)#917
rmdes wants to merge 1 commit into
mainfrom
spike/sqlite-collection

Conversation

@rmdes

@rmdes rmdes commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Draft, as offered in #821 — opened so the branch is easier to read than a
tree link. Not a proposal to merge, and not a schema proposal.

What it shows

util/lib/sqlite.js implements the collection interface on node:sqlite,
and upstream's getCursor runs against it unmodified. The collection
interface holds: insertOne, find, findOne, countDocuments and
cursor pagination all work without changes to their callers.

The one seam needed is id casting:

const castId = collection.castId ?? getObjectId;

MongoDB collections have no castId, so they coerce to an ObjectId
exactly as before; the SQLite one supplies Number. No existing caller
changes.

A test gap it uncovered

Deleting the getObjectId calls outright left the whole util suite and
145/145 in endpoint-micropub passing. The existing cursor tests pass
after._id — a live ObjectId — and getObjectId(anObjectId) is a no-op,
so nothing could detect the removal. Over HTTP ?after= is always a
string, which is where the coercion does its work. The suite could not
tell working pagination from broken. The missing case is added here.

Not covered

aggregate — the two $toDate/$addFields count pipelines. Everything
else in the spike is exercised by tests.

This does not touch the _id-in-URLs question, which I still think is the
actual decision to make.

Rebased onto main so the lint step reflects this branch rather than the
endpoint-share README formatting fixed in #910/#914.

Answers one question: does `addCollection` hold as a storage seam?

`lib/sqlite.js` implements the subset of the MongoDB collection interface
Indiekit uses, on `node:sqlite`. `find`, `findOne`, `countDocuments`,
`insertOne` and `deleteOne` all port over without touching their callers.

`getCursor` did not, because it calls `getObjectId` — it names a MongoDB
type inside code that is meant to be storage-neutral. `collection.castId`
lets a collection say how to read its own ids; MongoDB collections have no
such property, so they keep coercing to an ObjectId exactly as before.

Also adds the cursor test that was missing: the existing ones pass
`after._id`, a live ObjectId, so `getObjectId` is a no-op there and its
removal went undetected by the whole suite. Over HTTP the id is always a
string.

Not a migration, and not a schema proposal.
@paulrobertlloyd
paulrobertlloyd force-pushed the main branch 2 times, most recently from 67b3847 to fa1d368 Compare August 27, 2026 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant