upgrading/extension/upgrades/8.0.0-rc.3-to-8.0.0-rc.4/instructions.md
upgrading/extension/upgrades/8.0.0-rc.3-to-8.0.0-rc.4/instructions.mdBrowse 76 files
7,036 bytes
Token encoding: o200k_base
Snapshot fac8604
from: "8.0.0-rc.3" to: "8.0.0-rc.4" changes:
-
id: prisma-config-hard-cut-and-top-level-commands summary: | The deprecated fallbacks are gone: the CLI no longer reads
prisma-next.config.ts, no longer accepts the flat (un-nested) config shape, and theprisma-nextcommand no longer exists. The unified CLI (@prisma/cli, installed from thenextdist-tag; its binary is currentlyprisma-cli) runs the ORM commands at the top level —contract emit,db init,migration plan,migrate— with onlyinitunder theormgroup (orm init), and the only config it reads isprisma.config.tsin the engine envelope shape.- Rename
prisma-next.config.tstoprisma.config.tsif you have not already. - Rewrite the export to the envelope shape. Old flat shape:
import { defineConfig } from '@prisma/orm-postgres/config';export default defineConfig({ contract: '…', db: { connection: … } });New shape:import { definePrismaConfig } from '@prisma/cli-engine';import { defineConfig as ormConfig } from '@prisma/orm-postgres/config';export default definePrismaConfig({ orm: ormConfig({ contract: '…', db: { connection: … } }) });The options object moves into the target helper unchanged. The same pattern applies to@prisma/orm-sqlite/configand@prisma/orm-mongo/config. - If the config reads
process.env, keep (or add)import 'dotenv/config';as the first import — the loader does not read.envfor you. - In
package.json, replace theprisma-nextdevDependency withprisma@latestplus@prisma/cli-engineat the exact version that@prisma/clinames in its own dependencies, and update your extension's contract-space build and emit scripts fromprisma-next contract emittoprisma-cli contract emit. - Run
prisma-cli contract emitto confirm the config loads and to regenerate the artifacts (their generated-file headers change with this release). detection: glob: "**/prisma-next.config.ts"
- Rename
-
id: facades-compose-the-raw-lane summary: | A facade no longer gets the whole-query raw tag from the builder.
Db<C>is a pure namespace map now, so therawkey it used to answer is gone, and the tag is composed at client build instead.Build it with
createRawLane({ context, rawCodecInferer })from@internal/sql-builder/runtime, typedRawLane<TContract>from@internal/sql-builder/types, and expose it as your client'sraw. Callers then writeclient.raw.sql`SELECT ...`. A client that binds per role or per scope builds one lane per bound context, the way it already builds onesqlper context. A static context — the no-runtime shape that returnscontext,contractandsql— builds one too and returns it asraw.If your
rawproperty was the contract-free expression tag (createRawSql(inferer)), it changes shape from a callable to{ sql }. That breaks your own surface, so note it in your release. detection: glob: "**/*.{ts,mts,cts}" regex: - 'createRawSql(' - 'RawSqlTag' #fns.rawis a fragment call site and is deliberately excluded: # fragments are unchanged by this release. - '(?<!(?<![\w$])fns).raw`' anyMatch: true -
id: reserved-raw-namespace-check-removed summary: |
sql()no longer refuses a contract whose storage declares a namespace namedraw, andORM.NAMESPACE_RESERVEDleaves the error catalogue. Nothing raises the code now, so drop any branch that matched it: a test asserting the refusal, a doc listing the code, an error mapping of your own. detection: glob: "**/*.{ts,mts,cts,md}" contains: - "ORM.NAMESPACE_RESERVED" anyMatch: true -
id: contract-fixture-restamp summary: | Committed contract artifacts (
contract.json/contract.d.ts, including test fixtures) embed the toolchain version, which moves to 8.0.0-rc.4. Regenerate them with your emit script (build:contract-spaceor equivalent) after upgrading, or fixture comparisons fail on the version stamp alone. detection: glob: "**/contract.json" contains: - '"version": "8.0.0-rc.3"'
8.0.0-rc.3 → 8.0.0-rc.4 — Extension-author upgrade instructions
facades-compose-the-raw-lane
Db<C> is a namespace map and nothing else, so a facade composes the whole-query raw tag itself
and exposes it as the raw lane:
import { createRawLane, sql } from '@internal/sql-builder/runtime';
import type { Db, RawLane } from '@internal/sql-builder/types';
const sqlDb: Db<TContract> = sql<TContract>({ context, rawCodecInferer });
const raw: RawLane<TContract> = createRawLane<TContract>({ context, rawCodecInferer });
Callers reach the tag at client.raw.sql. A client that binds per role or per scope builds one
lane per bound context, exactly as it already builds one sql per context.
A static context does the same. If your facade ships a no-runtime surface — the shape that
returns context, contract, sql and friends without opening a connection — build the lane
there too and return it as raw:
export interface YourStaticContext<TContract extends Contract<SqlStorage>> {
readonly sql: Db<TContract>;
readonly raw: RawLane<TContract>;
// …context, contract, enums
}
const raw: RawLane<TContract> = createRawLane<TContract>({ context, rawCodecInferer });
Its raw property changes type from the contract-free tag to RawLane<TContract>, the same
change the connected client makes, so a consumer reads both surfaces the same way.
Two shapes change for your consumers. Anyone who wrote client.sql.raw`...` writes
client.raw.sql`...` . Anyone who called client.raw as an expression tag calls
client.raw.sql....returns(codecId) instead, or fns.raw inside a builder callback. Both are
breaking changes to your own surface, so note them in your release.
The detector looks for createRawSql(, RawSqlTag, and raw used as a tag. It skips the
receiver fns exactly, including x.fns.raw, because that is a fragment call site and needs no
change. A receiver that merely ends in those letters, such as myfns.raw, still matches, as
does a functions object aliased to another name.
reserved-raw-namespace-check-removed
sql() used to refuse a contract whose storage declared a namespace named raw, raising
ORM.NAMESPACE_RESERVED at client construction. The check is gone with the constraint it
enforced: the lane is composed by the client, not answered by the namespace map, so no contract
can shadow it.
Drop any branch that matched the code — a test asserting the refusal, an error mapping, a doc that lists it. The code no longer exists in the catalogue, and nothing raises it.