ReviewOS

also looking at this

stacks/bun-query-builder

fix(orm): an eager load that resolves nothing should say so

#1075
Merged glennmichael123 wants to merge fix/eager-load-unknown-relation into main
2 files +168 -1
10 days ago

Closes #1068.

eagerLoadRelation returned silently when it couldn't resolve a relation name. A misspelling loaded nothing and reported nothing — the property is simply absent from the result, no error anywhere, and the outcome is indistinguishable from a relation that genuinely has no rows. .with('psots') looked exactly like a post with no comments.

The same silence covered every relation kind the resolver doesn't implement. ModelDefinition accepts morphOne, morphMany, morphTo, morphToMany, morphedByMany, hasOneThrough and hasManyThrough; resolveRelation handles four — hasMany, hasOne, belongsTo, belongsToMany. Declaring any of the rest type-checks, autocompletes, and does nothing at runtime.

Two mistakes, two messages

[orm] 'Author' has no relation 'boks'. Available: books.

[orm] 'Author' declares 'annotations' as morphMany, which eager loading does not
support yet. Supported kinds: hasMany, hasOne, belongsTo, belongsToMany. Load it
with a manual query for now — see #1068.

The distinction is the point. Telling someone "no such relation" when the relation is right there in their model — just of a kind this library never implemented — sends them hunting for a typo that doesn't exist. A model with no relations at all says that outright instead of printing an empty list.

The throw sits after the per-model+name resolution cache, so a repeat call behaves like the first rather than quietly succeeding on a cached null.

Tests

Five cases: misspelling throws, the message lists what does exist, a relation-less model says so, a declared-but-unsupported kind gets the other message (and explicitly not the "no relation" wording), and the supported path still loads.

Verified they discriminate: against the unfixed orm.ts, 4 of 5 fail.

Typecheck 0, lint 0 errors, suite 1704 pass / 4 skip / 0 fail.

Noticed while testing, not fixed here

resolveRelation derives the related table from the model name rather than its declared table, so a model named URBook with table: 'ur_books' sends the loader looking for u_r_books. I renamed my fixtures around it rather than widening this PR — worth its own issue if you agree it's wrong.

This is also a behaviour change worth a deliberate look: code that today relies on .with() quietly ignoring an unknown name will now throw. That's the intent, but it could surface in an app that had a typo it never noticed.

🤖 Generated with Claude Code

2 changed files on the files tab, with 0 review threads.

Sign in to comment on this pull request.