TML-2955: A client-safe static surface — @prisma-next/<target>/static#888
TML-2955: A client-safe static surface — @prisma-next/<target>/static#888wmadden-electric wants to merge 11 commits into
Conversation
|
Warning Review limit reached
Next review available in: 4 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (36)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Captures the design for surfacing the execution-plane ExecutionContext (contract + codecs + operations + types, driver-free) symmetrically on the Mongo and Postgres facades: build it upfront, expose db.context, type MongoExecutionContext<TContract>, and offer a client-safe per-target static factory that supersedes the interim mongoEnums/@prisma-next/mongo/enums shipped in PR #880. Planning artifact only; no code changes. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
The interim mongoEnums/@prisma-next/mongo/enums prototype was stripped from #880; the example now uses buildNamespacedEnums + a blindCast. Reword the spec so the slice replaces that example-level interim rather than retiring a shipped framework surface. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…dispatch plan The named consumer (retail-store/src/enums.ts) never existed on main and #880's enum machinery was pulled, so step 4 becomes "add a fresh client consumer" and the real blindCast leak (in the facades) is folded in. Adds a three-dispatch plan grounding the entrypoint + driverless-context boundaries. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…isma-next/mongo/static
Type MongoExecutionContext<TContract> (was contract: unknown), build it once
upfront from the driver-free stack, reuse it in buildRuntime, and expose it as
db.context. Add a client-safe @prisma-next/mongo/static entrypoint whose
mongoStatic({contractJson}) returns { context, contract, enums, query }; the
facade and the static path share one buildMongoStaticContext, removing the
per-facade enum blindCast. A source import-graph test asserts the /static graph
pulls in no mongodb/driver-mongo.
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…se db.contract
Mirror the Mongo static surface on the SQL side. Add driver-free
buildPostgres/SqliteStaticContext builders (adapter-only stack, no driver
import) exposed via @prisma-next/<target>/static as postgresStatic/sqliteStatic
returning { context, contract, enums, sql, raw }. The facades now derive their
static surface through the shared builder and expose readonly contract, removing
the per-facade enum blindCast. Source import-graph tests assert the /static
graphs pull in no pg/@prisma-next/driver-* packages. Building the context from a
driverless stack is behaviour-preserving: the facades never passed the driver as
a capability source to createExecutionContext.
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Reconcile #880 (raw/execute on the Mongo facade + retail-store enums) with the static-ExecutionContext work: the merged MongoClient exposes orm, query, raw, contract, enums, context, and execute. enums/query/context come from the shared buildMongoStaticContext; raw/execute are kept from #880. Mongo suites green (108 + 174 tests). Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…s driver-free The mongo adapter codec value-imported ObjectId from mongodb, so building the ExecutionContext (mongoStatic) dragged the full driver into the client bundle — next build of retail-store failed with 19 errors. ObjectId is a bson class that mongodb re-exports; import it from the standalone browser-safe bson package instead. The client-safety tests previously passed vacuously (off-by-one ROOT so the graph walk read nothing); rewrite the walk to traverse workspace packages and distinguish value from `import type`, catching this leak (red before, green after) for all three targets. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…drop the blindCast Reduce src/enums.ts to a single framework-typed derivation via mongoStatic, removing the interim buildNamespacedEnums + blindCast (TML-2955 step 5). The `use client` checkout-form consumes it, so this is the next-build client-safety acceptance path. Reconcile the spec with what actually shipped. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
… extensions survive The facades sourced db.context from the client-safe static builder (target + adapter only), so options.extensions never reached the context and createExecutionContext threw RUNTIME.MISSING_EXTENSION_PACK for any app using an extension pack (postgis/pgvector/paradedb demos all broke). Split out a shared surface helper (enums/sql/raw from an already-built context) so the enum cast stays centralized, and have each facade build its own context from its full stack (target + adapter + driver-as-capability-source + options.extensions). The /static entrypoints keep their target+adapter-only, driver-free stack. Adds extension-pack facade tests (red before, green after). Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…or 0.14→0.15 Additive client-safe static entrypoints + db.context/db.contract on the facades, and the internal mongo-adapter ObjectId→bson change. No user or extension-author action required; recorded as incidental per the per-pr-declaration check. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…ort shapes The walk stopped at object-form exports and dist/exports/ layouts (silently dropping e.g. mongo-query-ast) and missed require()/dynamic import(), so its driver-free guarantee was weaker than claimed. Resolve object-condition exports, map dist/exports/<name> back to source, and match require/await-import. Add a vacuous-walk guard (files.size > 100) so a zero-file walk can never pass silently again. mongo 115->127, postgres 257->317, sqlite 161->184 files walked; still no driver reachable. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
c31d3e7 to
e6a3e03
Compare
size-limit report 📦
|
@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/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/extension-supabase
@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/config-loader
@prisma-next/emitter
@prisma-next/language-server
@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: |
At a glance
You can now use a contract's enums, query builder, and generated types in a
'use client'component — with no database driver in the browser bundle:The same call shape exists on every target (
postgresStatic,sqliteStatic), and the same object is exposed on a connected client asdb.context/db.contract.The decision
Expose the
ExecutionContextas a first-class, client-safe surface — a new@prisma-next/<target>/staticentrypoint — symmetrically on all three target facades.The
ExecutionContextis the driver-free core every query is built against: the contract, its codecs, the query operations, and the derived types. Enums, the query builder, andraware all just views over it. It needs no connection and no driver to construct — so in principle it's usable anywhere, including the browser. This PR makes that real and uniform.Why it wasn't already usable
The context existed but you couldn't get at it cleanly from client code:
db.context— but only on a fully-wired, driver-carrying client.unknown.So when an app needed typed enums in a
'use client'form, it fell back to an interim: hand-calling the low-levelbuildNamespacedEnums(...)and casting the untyped result in application code. That worked but was a narrow, per-consumer workaround, not the abstraction.What this PR does
@prisma-next/<target>/staticwith<target>Static({ contractJson }), returning theExecutionContextplus the surface derived from it (enums, query builder,raw,contract). It's driver-free by construction, and a test walks the entrypoint's import graph to keep it that way.MongoExecutionContext<TContract>, and exposesdb.context/db.contract— matching Postgres, so the shape is the same across targets./statictwin through one shared builder, so the enum typing lives in framework code once instead of a cast in every app.examples/retail-storeoff the interim:src/enums.tsnow derives frommongoStatic(...), consumed by the'use client'checkout form — which doubles as thenext build"no driver in the client bundle" acceptance test.One cross-cutting change worth a look
Making the static context truly driver-free reached one layer deeper than the facades. Building the context aggregates the target's codecs, and the Mongo codec imported
ObjectIdfrommongodb(a value import), which drags the whole driver into a client bundle.ObjectIdis really absonclass thatmongodbre-exports, so the codec now imports it from the standalonebsonpackage. It's a one-line change but it lives inpackages/3-mongo-target/2-mongo-adapter, and it's what letsnext buildsucceed with zero driver code client-side.Extension packs (postgis, pgvector, …) are unaffected: the facade still builds its context from the full stack including
options.extensions; only the client-safe/staticpath is target+adapter-only.Testing
Full local gate green (build, typecheck, lint incl.
lint:deps/lint:casts,check:upgrade-coverage,fixtures:check,test:packages/integration/e2e) and CI green.retail-storenext buildproduces nomongodbin the client bundle. Upgrade instructions recorded as additive/incidental for 0.14→0.15.Alternatives considered
buildNamespacedEnums+ a cast). Rejected: untyped without a per-call cast, duplicated per consumer, and it leaks a framework detail into every app.mongoEnums/@prisma-next/mongo/enumspoint-solution prototyped in Exercise Mongo enums in retail-store; add raw/execute/mongoEnums to the Mongo client #880 and pulled back out. Rejected: it solved one symptom (enums) rather than exposing the abstraction they derive from. Exposing the wholeExecutionContextgives enums, query building,raw, and types from one surface, symmetrically./runtimeentrypoint tree-shakeable instead of adding/static. Rejected: the driver is imported at module scope, so bundlers can't reliably drop it. A separate driver-free module is a hard boundary — and the client-safety test enforces it.Spec:
projects/expose-static-execution-context/spec.md. Closes TML-2955.🤖 Generated with Claude Code