TML-2653: Remove capabilities from defineContract; components contribute them#574
Conversation
|
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 (24)
✅ Files skipped from review due to trivial changes (18)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughDerive contract capabilities from targets and extension packs via a new capability-matrix merge utility; remove author-declared capabilities from contract inputs; add adapter-level foreign-key capabilities; and regenerate extension, app, example, and test fixture contracts to reflect merged capability metadata. ChangesCapability Matrix Infrastructure and Contract Capability Authoring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/extension-cipherstash
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/emitter
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
|
Can't we infer defaults from adapter instead? |
There was a problem hiding this comment.
Totally wrong approach. Any framework component may provide capabilities, not just the family, and you can't hardcode a list of them, nor can you couple the framework domain to SQL
Additionally: this work should have no effect on the generated contract assets already in the repo. Regenerated assets should be identical.
1c1558f to
8a6e9ef
Compare
|
Force-pushed a correction after operator feedback: the previous force-push ( New commit chain on this branch:
Key changes vs the prior push:
Diff vs
The 5 |
e1e7320 to
6ba5691
Compare
capabilities from defineContract; components contribute them
…ith a generic merge helper
The old `resolveAuthoringCapabilities` injected hardcoded `sql.{returning, defaultInInsert, foreignKeys}` from the framework-level `@prisma-next/contract-authoring` package, which is supposed to stay target-agnostic. It also forced `defaultInInsert: true` onto every SQL target, which is wrong for SQLite.
Replace it with `mergeCapabilityMatrices(...sources)`, a pure structural deep-merge over the matrix shape with zero family or target knowledge. The SQL contract-ts builder now aggregates `definition.target.capabilities`, each `definition.extensionPacks[*].capabilities`, and the author-declared `definition.capabilities` through this helper. CLI-time `enrichContract` continues to layer in adapter/driver capabilities — this is the two-stage capability contribution model.
The SQL contract-ts result type derives `capabilities` from the same three sources via type-level intersection rather than embedding a hardcoded framework-wide shape, so authoring-time types and runtime values agree without per-family special-casing.
Tests now drive contribution semantics directly: the framework helper test exercises generic merge; the SQL test declares capabilities on target/extension pack refs and asserts they show up; the PSL interpreter test asserts that no capabilities are synthesised when the target contributes none, and that target-declared caps flow through.
Closes part of TML-2653.
Signed-off-by: Will Madden <madden@prisma.io>
The SQLite adapter always supports FOREIGN KEY constraints. Declaring `sql.foreignKeys: true` on its descriptor lets CLI-time `enrichContract` surface the capability into every contract that picks up the adapter, so authors no longer need to enumerate it. With the capability sourced from the adapter, the example contracts drop the corresponding hand-enumerated flags: the SQLite demo no longer declares `sql.returning` or `sql.foreignKeys`, and the Postgres demos no longer declare `postgres.returning` (the Postgres adapter has always contributed it). Author-declared opt-outs still win because authoring-time capabilities are layered last in the merge. The Postgres adapter is intentionally left untouched: `foreignKeys` was never previously declared on it nor on any Postgres example, and the goal is to plumb existing capability declarations through a single contribution mechanism rather than introduce new ones for symmetry. Closes part of TML-2653. Signed-off-by: Will Madden <madden@prisma.io>
…tion rework Author-declared capability sets shrunk for the five contracts whose example `contract.ts` dropped redundant declarations now contributed by the adapter: - `examples/paradedb-demo` (dropped `postgres.returning`) - `examples/prisma-next-demo-sqlite` (dropped `sql.returning` and `sql.foreignKeys`) - `packages/2-sql/4-lanes/sql-builder/test/fixtures/generated` (Postgres test fixture, dropped `postgres.returning` upstream) - `packages/3-extensions/sql-orm-client/test/fixtures/generated` (dropped `postgres.returning` upstream) - `test/integration/test/sql-builder/fixtures/generated` (dropped `postgres.returning` upstream) The serialized `.capabilities` block of every regenerated contract is byte-identical to the pre-rework asset (the dropped declarations are now supplied by the adapter at CLI emit time). Only the `profileHash` field — which fingerprints the author-declared capability subset — bumps to reflect the new author input. Signed-off-by: Will Madden <madden@prisma.io>
Picks up the new profileHash produced by the generic mergeCapabilityMatrices helper for the postgres-target sql-builder and sql-orm-client fixtures, which were missed in the previous fixture regen pass. Signed-off-by: Will Madden <madden@prisma.io>
…nput
The SQL and Mongo `defineContract` factories no longer accept a
`capabilities` block. Capability flags now flow exclusively from the
configured component descriptors (target / extension packs at build
time; adapter / driver / extension layered in by `enrichContract` at
CLI emit time).
The `profileHash` computation is unchanged from `origin/main`: it
still fingerprints the author-declared capability subset. With that
input always empty after this change, the hash collapses to the
empty-author hash (`hash({})`) for every contract; the value differs
per target because `target` and `targetFamily` are also part of the
fingerprint.
Refresh the SQL `capability-defaults` test suite:
- Drop the two cases that exercised author-declared overrides (no
longer reachable through the public surface).
- Add a `@ts-expect-error` negative-type assertion that the input
shape rejects a `capabilities` field.
- Add a regression assertion that the build-time `profileHash` is
stable across contracts with no author input.
Drop the now-unused `Capabilities` type parameter from the
`defineTestContract` helper in `contract-builder.constraints.test.ts`
to follow the input-shape change.
Signed-off-by: Will Madden <madden@prisma.io>
The Postgres adapter descriptor now contributes two flags it always implies: - `postgres.distinctOn` — gates `SelectQuery.distinctOn(...)` in the SQL builder runtime; previously declared by example contracts. - `sql.lateral` — gates `lateralJoin(...)` / `outerLateralJoin(...)` in the SQL builder runtime; previously declared by example contracts. The Postgres adapter already contributes `postgres.lateral`; the family-namespace flag belongs on the same descriptor so SQL-builder gates resolve consistently for any Postgres-targeted contract. After dropping `capabilities` from the `defineContract` input, the two flags need to come from a component descriptor rather than the example. They are honest Postgres adapter capabilities, so this is the right home for them. Signed-off-by: Will Madden <madden@prisma.io>
…tracts
Author-declared `capabilities: { ... }` blocks on every TS
`defineContract` call site are now removed (examples, apps,
fixtures, projects). With the field gone from the input shape, the
build-time matrix is the merge of the configured component
descriptors only.
Regenerate every emitted `contract.{json,d.ts}`:
- `profileHash` collapses to the empty-author hash for that target
(Postgres → `1a8dbe04…`, SQLite → `c336398c…`). Same fingerprinted
shape as before; the input subset is just always empty now.
- `capabilities` matrices reflect the merged set contributed by the
target, adapter, driver, and any extension packs. Where examples
had previously declared phantom flags that no component owns
(e.g. `pgvector.hnsw`, `postgres.partialIndex`), those drop out
of the matrix; the runtime never gated on them.
The two flags the SQL builder runtime does gate on
(`postgres.distinctOn`, `sql.lateral`) are now contributed by the
Postgres adapter descriptor in a separate commit; this regen picks
those up automatically.
Signed-off-by: Will Madden <madden@prisma.io>
Rebase onto main left ContractInput at five type parameters; align wrapped defineContract overloads and negative tests with E1 authoring. Signed-off-by: Will Madden <madden@prisma.io>
6ba5691 to
2af0d19
Compare
…or postgres adapter caps Signed-off-by: Will Madden <madden@prisma.io>
…ix and enrich in-memory contract The Postgres adapter descriptor advertises `postgres.distinctOn` and `sql.lateral` (added when those flags moved from author-declared to component-contributed). The runtime `defaultCapabilities` constant shadowed that set and lost both flags; sync the two so `adapter.profile.capabilities` matches what the descriptor emits into the contract (per the README invariant). Independently, the SQL builder integration test setup builds its contract in-memory via `defineContract` and bypasses the CLI emit pipeline that normally folds adapter and driver capabilities in via `enrichContract`. Run the same enrichment step in the setup so the runtime capability gates see the merged matrix. Signed-off-by: Will Madden <madden@prisma.io>
…es removal
Append `remove-capabilities-from-define-contract` to the user-skill 0.11-to-0.12 instructions: delete the `capabilities: { ... }` block from every `defineContract` call site and re-emit so the contributor-declared capabilities (incl. new `postgres.distinctOn` and `sql.lateral`) land in `contract.{json,d.ts}`.
Append `define-contract-drop-capabilities-generic` to the extension-skill 0.11-to-0.12 instructions: facade-style extensions drop the `Capabilities` type parameter from their `defineContract` overloads and supporting type aliases; fixture-only extensions re-emit to pick up the same auto-contributed capability keys.
Signed-off-by: Will Madden <madden@prisma.io>
At a glance
The
capabilitiesargument is gone. The set of capabilities available to a contract is now derived from the components it's built on — target, extension packs, adapter, driver — instead of being enumerated by the author.Fixes TML-2653.
The decision
defineContractno longer accepts acapabilitiesfield. The same goes for the PSL interpreter's contract definition. Capabilities are now contributed by the framework components in the contract's stack and merged into a single matrix at build time.Concretely:
ContractDefinition(both SQL and Mongo) dropscapabilities. Passing it is a TypeScript error.defineContractcall site (examples/**,apps/**, fixtures) drops itscapabilities: { … }block.Why
defineContractpreviously required authors to enumerate every framework capability their contract relied on, even ones the framework can always provide on a given target. First-time authors hit "requires capability" errors on flags likesql.returningthat have no meaningful "off" state for a Postgres adapter, and the boilerplate added nothing the framework couldn't infer.It was also the wrong ownership boundary. A capability is a property of the component that implements it: the Postgres adapter knows whether it supports
DISTINCT ON; the pgvector extension pack knows it provides HNSW indexes; the author shouldn't need to mirror those decisions in the contract.What this means for users
capabilities: { … }block is gone.contract.{json,d.ts}reflect this: thecapabilitiesblock grows where the example previously declared fewer flags than its components contribute, and shrinks for phantom flags no component owns.profileHashstabilises. PreviouslyprofileHashwashash(definition.capabilities)— a fingerprint of the author-typed subset. With the author input gone, the hash semantics are unchanged but the input is empty, soprofileHashstabilises atsha256:1a8dbe04…(Postgres-target) /sha256:c336398c…(SQLite-target) across all contracts.What changes in the framework
mergeCapabilityMatricesin@prisma-next/contract-authoringperforms structural deep-merge over capability matrices. Zero SQL or target-family knowledge. Sits inpackages/1-framework/.buildSqlContractFromDefinition(the path both the TS builder and the PSL interpreter lower through) mergesdefinition.target.capabilitiesand everydefinition.extensionPacks[*].capabilitiesvia the helper. The CLI's existingenrichContractcontinues to layer in adapter/driver contributions at emit time.postgres.distinctOnandsql.lateral— flags the SQL builder's runtime gates on that no component previously owned.pnpm lint:depsis clean: no@prisma-next/target-*references insidepackages/1-framework/.What changes in generated artifacts
Every
contract.{json,d.ts}acrossexamples/**,apps/**,packages/3-extensions/*/src/contract.*, and the test/fixture trees is regenerated:profileHashsettles at the empty-author hash per target.capabilitiesblock reflects the merged component contributions — wider than the prior author-typed subset in most cases, narrower where the author previously declared flags nothing currently owns.Upgrade instructions
Adds entries to
skills/upgrade/prisma-next-upgrade/upgrades/0.11-to-0.12/andskills/extension-author/prisma-next-extension-upgrade/upgrades/0.11-to-0.12/.Test plan
pnpm typecheck(full monorepo) — clean.pnpm lint:deps— clean; no@prisma-next/target-*references insidepackages/1-framework/.@prisma-next/sql-contract-ts,@prisma-next/mongo-contract-ts,@prisma-next/sql-contract-psl,@prisma-next/mongo-contract-psl,@prisma-next/sql-builder,@prisma-next/sql-orm-client,@prisma-next/contract,@prisma-next/sql-contract,@prisma-next/mongo-contract,@prisma-next/cli,@prisma-next/emitter,@prisma-next/e2e-tests— all green.capability-defaults.test.tsconfirmsdefineContract({ …, capabilities: { … } })is a TypeScript error.pnpm fixtures:check— regenerated assets reflect the merged-matrix shape.Alternatives considered
FRAMEWORK_WIDE_SQL_CAPABILITY_DEFAULTS) inpackages/1-framework/. Rejected: it embeds SQL knowledge in the target-agnostic framework layer, violates the dependency direction enforced bypnpm lint:deps, and bakes in incorrect assumptions for individual targets (sql.defaultInInsert: trueisn't true for SQLite).profileHashover the merged matrix inenrichContractto preserve byte-identical output. Rejected: changes the hash's semantics for no user-visible benefit. The simpler shape — keep the hash computation as-is and accept that an empty author input produces a stable hash — was preferred.Summary by CodeRabbit
New Features
Refactor
Tests
Documentation