docs(skills): prisma-next-queries — Postgres surface is always namespace-qualified#917
docs(skills): prisma-next-queries — Postgres surface is always namespace-qualified#917ankur-arch wants to merge 3 commits into
Conversation
…s namespace-qualified Corrections verified against @prisma-next 0.14.0 and current main while writing the Prisma Next Fundamentals docs (prisma/web#8011): - The flat `db.orm.User` / `db.sql.user` form does not exist on Postgres. #778 removed the flat fallback; the orm() proxy resolves only namespace keys, so bare model access returns `undefined` at runtime. All Postgres examples now use `db.orm.public.<Model>` / `db.sql.public.<table>`, and the "flat form still works for single-namespace contracts" claim is replaced with the tested behavior. - `.count()` is not a collection terminal (it throws "count() is only available inside include() refinement callbacks"). Counting goes through `.aggregate((a) => ({ n: a.count() }))`; the terminal list is corrected. - SQL-builder inserts must pass rows as an array. The single-object `.insert({...})` form fails at result decoding on 0.14.0; the example now uses `.insert([{...}])` and notes the constraint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughDocumentation updates across ChangesNamespace-qualified accessor documentation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@skills/prisma-next-queries/postgres.md`:
- Around line 111-117: The pagination example builds the next cursor from
page1[page1.length - 1] in the Post query flow, which will fail when the first
page is empty. Update the Post pagination snippet to guard the empty result from
db.orm.public.Post.orderBy(...).take(20).all() before deriving last or
constructing page2, and only continue to the next page when page1 has at least
one item.
In `@skills/prisma-next-queries/SKILL.md`:
- Around line 124-126: The Postgres short-script example is not self-contained
because the `users` iterable is missing, so the snippet cannot be copied and run
as shown. Update the example around the `for (const u of users)` and
`db.orm.public.User.create` usage by adding a concrete `users` binding or an
inline seed source in the same snippet so the loop has defined input.
- Around line 79-84: The buffered query example uses the projected shape from
User.select('id', 'email'), so the type annotation should match the returned row
shape instead of the full entity type. Update the Promise<User[]> annotation in
the buffered example to Promise<Row[]> and keep the surrounding prose/examples
consistent with the Row[] terminology used by
db.orm.public.User.select(...).all().toArray().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 18448aa6-cceb-44ae-a59f-adc5980ca23e
📒 Files selected for processing (2)
skills/prisma-next-queries/SKILL.mdskills/prisma-next-queries/postgres.md
| ``` | ||
|
|
||
| The flat `db.sql.users` / `db.orm.User` form still works when bare names are unique across all namespaces. When the same bare name appears in more than one namespace, use the coordinate form — both the type system and the runtime require it to resolve to the right table. | ||
| There is no flat `db.sql.users` / `db.orm.User` form: the namespace coordinate is always required on Postgres. The runtime proxy resolves only namespace keys, so a bare model access returns `undefined` (verified against 0.14.0 and current `main`; the flat fallback was removed in #778). |
There was a problem hiding this comment.
Do we need this historical fun fact in the skill?
There was a problem hiding this comment.
Agreed, dropped. It now states the rule plainly: the namespace coordinate is always required on Postgres, and a bare model access returns undefined so the first chained call throws. Same cleanup applied to the equivalent sentence in SKILL.md. Fixed in c9cf152.
|
|
||
| - **`db.orm.<Model>`** — ORM, PascalCase model name (`db.orm.User`). Fluent `.where(...).select(...).orderBy(...).all()`, fully typed against `Contract`. Default lane for CRUD with relations. | ||
| - **`db.sql.<table>`** — SQL builder, lowercase storage name (`db.sql.user`). Produces a *plan* executed via `db.runtime().execute(plan)`. Use when the ORM is too high-level — explicit `JOIN`, computed projections, set operations, window functions. | ||
| - **`db.orm.<ns>.<Model>`** — ORM, namespace-qualified PascalCase model name (`db.orm.public.User`). Fluent `.where(...).select(...).orderBy(...).all()`, fully typed against `Contract`. Default lane for CRUD with relations. |
There was a problem hiding this comment.
I think we need to mention a bit on how ns relates to PSL and contract. We always use either public or placeholder <ns> throughout the doc. We should mention somewhere that public is default (for the models declarated outside of namespace block in PSL) and <ns> stand for a namespace model have been explicitly defined in.
There was a problem hiding this comment.
Good call. Added a paragraph to the Key Concepts section (and mirrored it in SKILL.md's namespace section): models declared at the top level of the PSL live in the default public namespace, and models declared inside a namespace <name> { ... } block are addressed by that namespace; the examples use public and readers substitute their own. Fixed in c9cf152.
SevInf
left a comment
There was a problem hiding this comment.
Preemtively approve, but there are few things I'd like to change before we merge it
- Explain where the namespace coordinate comes from: top-level PSL
models live in the default public namespace, models inside a
namespace <name> { } block are addressed by that namespace (SevInf).
- Drop the historical note about the flat fallback's removal; state
the rule plainly (SevInf).
- Guard the empty first page before deriving the cursor in the
pagination example (CodeRabbit).
- Promise<User[]> -> Promise<Row[]> for consistency with the
surrounding Row[] text (CodeRabbit).
- Make the short-script seed example self-contained by defining the
users array it iterates (CodeRabbit).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
What this fixes
The
prisma-next-queriesskill teaches agents (and people) how to query Prisma Next. Three things it teaches no longer match how the released packages behave. Anyone following the skill on a Postgres project today writes code that crashes on its first query.This PR updates the skill to the tested behavior. Every correction was verified by running real queries against
@prisma-next0.14.0 on a live Postgres database, and cross-checked against the source onmain.The major change: Postgres access is always namespace-qualified
Since #778, the ORM and SQL builder resolve models through the schema namespace only:
The flat form does not error helpfully.
db.orm.Userisundefined, so the first chained call throwsCannot read properties of undefined (reading 'where'). The skill said the flat form "still works for single-namespace contracts", which is exactly the setup every new project has, so the guidance broke the most common case.Impact: every Postgres example in the skill produced crashing code. This also affects the
create-prismascaffold templates (seed.ts,index.ts,users.tsstill use the flat form, sonpm run db:seedcrashes on a fresh scaffold). That template fix is separate from this PR and still needed.Two smaller corrections
.count()is not a query terminal. Calling it throwscount() is only available inside include() refinement callbacks. Counting goes through.aggregate((a) => ({ n: a.count() })), which the skill's aggregate section already documents. The terminal list now reads.all() / .first() / .aggregate(...).SQL builder inserts need the array form.
.insert({ email })fails inside result decoding on 0.14.0 (this[#rows].map is not a function)..insert([{ email }])works, including.returning(...)and generated-id defaults. The example now uses the array form and notes the constraint.How this was verified
The same validation run surfaced a few adjacent issues that are out of scope here but worth tracking: the scaffold templates above, MongoDB
@default(now())not being applied at create time, and pipeline.matchon ObjectId fields matching nothing. Happy to file them separately.🤖 Generated with Claude Code
Summary by CodeRabbit
undefined.