Next-generation ORM for Node.js & TypeScript | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
TML-3199: Docs hygiene — dead links, stale API instructions, and the payload label (#30016) # Docs hygiene: dead links, stale API instructions, and the payload label Main-based cleanup (not part of the raw-SQL stack, though its items were surfaced by that campaign's reviews). ## What changed - **ADR-INDEX's dead ADR 035 link** — a pure capitalization mismatch (`Dual authoring conflict resolution` vs the file's `Dual Authoring Conflict Resolution`); corrected to the file's actual name. - **`error-reference.md`: "Meta:" → "Payload:" (260 entries) + one preamble sentence.** The old label was wrong for half the file: `structuredError()` writes `error.meta` but `runtimeError()` writes `error.details`, and a scripted classification showed a per-code label is ill-defined — of the codes classifiable at all, eight are raised through *both* constructors. The neutral label plus a preamble stating the rule (meta from structuredError, details from runtimeError, some codes both ways) is accurate today and stays accurate as raise sites move. No tooling reads the label (verified against `list-error-codes.mjs`). - **Stale `validateContract<Contract>(contractJson)` instruction removed from four surfaces** (`AGENTS.md` § Key Patterns, Testing Guide ×3, the Runtime subsystem doc, and the `typed-contract-in-tests` rulecard) — no such export exists, and the stale pattern had already generated a false review finding. Replacements verified against current code: the client factory hydrates (`postgres<Contract>({ contractJson, url })`), and tests use `validateSqlContractFully<Contract>(contractJson)` (the idiom with 174 current usages). The `validateContract` in `family-instance-domain-actions` is deliberately untouched — that one is the real ADR 204 control-plane primitive, a different thing sharing the name. - **ADR 012's refs clause** now states ADR 205's own conclusion: the unindexed-predicate lint and refs-based budget heuristic ran off the removed sidecar and no longer run for any plan. (The previous wording invited a hunt for a `meta.refs` field that no longer exists.) - **One ticketed item needed nothing**: the four "dead" source links in the Runtime & Middleware doc were already fixed upstream — verified resolving, left alone. ## Known merge note This PR and the raw-SQL stack (#29997) both edit the tail of the same ADR 012 update note, for different reasons. The conflict is one line but **semantic**: whichever lands second must carry both intents (the stack scopes the wire-level-rows claim as historical; this states the refs heuristics gone). Taking either side wholesale silently drops the other. Out of scope, ticketed: 68 further dead links across `docs/` + the missing link checker, two orphaned error-reference entries the one-directional checker cannot see, and ADR 205's own upstream ambiguity (all on TML-3211). Refs: TML-3199 https://claude.ai/code/session_01NnNjsNcPMtbJZhnZz5Zzbe <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated contract hydration and validation guidance to reflect the current workflow. * Refreshed testing and runtime examples for standalone contract usage. * Corrected architecture decision record titles, links, and descriptions of removed raw-plan metadata. * Clarified that contract data can be passed directly through runtime setup. * **Tests** * Updated typed contract fixture guidance to use full SQL contract validation for parsed contract data. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 8 天前 | |
Base agent worktrees on freshly fetched origin/main (#30080) The WorktreeCreate hook created every agent worktree from the main checkout's HEAD, with no fetch. That checkout is routinely stale (nothing pulls it), so agent sessions regularly started one or more commits behind origin/main and analyzed or built against outdated code. The hook now runs `git fetch origin main` and branches the worktree from `origin/main` instead of `HEAD`. If the fetch fails (for example offline), worktree creation fails loudly instead of silently starting from a stale base. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Worktrees are now created from the latest `origin/main`, ensuring new branches start with up-to-date code. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 19 天前 | |
docs(rules): record CI-classification and verification lessons from the raw-lane close-out (#30079) Close-out documentation from the whole-query raw SQL project (TML-3198 → TML-3214/TML-3217 and the CI work they surfaced: TML-3221, TML-3222). Records the durable lessons as rules and skill guidance. ## New rules - **`ci-failure-classification.mdc`** — classify CI failures from evidence before acting: run `pnpm install --frozen-lockfile` before classifying (stale dist/deps/fixtures fake both reds and greens), use control experiments that actually run the failing steps (the inert-diff detector makes docs-only controls vacuous), and recognize the flake fingerprints this project hit live: assertion drift across retries, connection death cascades (one error, then siblings at 0ms), and all-tests-green-but-exit-1 teardown rejections. Also: when a gate demands content about changes a PR does not contain, suspect the gate's comparison base. - **`non-vacuous-verification.mdc`** — every check must be able to fail. Regression tests run red pre-fix or test a purpose-built seam; verifiers fail on empty input; `not.toBeAny()` sentinels guard type fixtures against `skipLibCheck` any-poisoning; comments describing guards are not evidence the guard exists; generated-file claims are tested by regenerating. Both are scoped (`alwaysApply: false`); the always-apply and AGENTS.md budgets are unchanged. The total-rules-bytes footprint threshold rises 208000 → 216000 to cover them (the corpus was ~1 KiB under the ceiling before this PR). ## Extended rules - `typescript-patterns.mdc` — two reminders: key id-like string parameters on their map (`keyof CT & string` preserves literals and completions where `Record<string, string>` widens), and `ReturnType` of an overloaded function resolves to the last overload (order most-specific first; pin with a type test). - `adr-writing.mdc` — maintain the ADR in the PR that changes the decision, not in a follow-up. ## Skill guidance (`record-upgrade-instructions`) - Stacked PRs: the coverage gate diffs each PR against the branch it targets (#30076), so each PR declares entries for its own substrate diff; pooling a stack's entries in the bottom PR breaks partial mergeability. - Release-cut corollaries: a just-shipped transition directory is history (restore byte-for-byte; entries for unshipped changes may not remain), and the new in-flight directory is created by the first PR that needs it — `changes: []` when the diff needs no consumer action. - Detection predicates must be token-precise, with the shipped `fns.raw` exclusion as the worked example. ## Scope Documentation and one lint threshold only; no runtime code. https://claude.ai/code/session_01NnNjsNcPMtbJZhnZz5Zzbe <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added guidance for keeping architectural decisions, examples, and upgrade instructions aligned with shipped changes. * Expanded CI troubleshooting guidance to distinguish code-related failures, infrastructure issues, and pre-existing failures. * Added verification practices to ensure tests and checks genuinely detect failure conditions. * Refined TypeScript guidance for overloaded function return types and type-test coverage. * Updated skill installation paths, validation procedures, examples, and reference documentation. * **Chores** * Increased rule configuration capacity to support the expanded guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 19 天前 | |
ci: fix the prisma-cli publish notification (event type, repo name) (#30179) ## Linked issue n/a — small change; fallout from the repository rename (prisma/prisma → prisma/orm). ## Summary The publish workflow's "Notify prisma-cli" step never reached its consumer. It sent `event_type: family-published`, but prisma-cli's `update-product-versions.yml` triggers on `product-published`, so the auto-repin only ever ran from its daily scheduled backstop. The payload also still named this repo `prisma/prisma`. The step now sends `product-published` with `repo: prisma/orm`. ## Testing performed - Verified the receiving side: `prisma/prisma-cli` `.github/workflows/update-product-versions.yml` triggers on `repository_dispatch: types: [product-published]` and reads nothing from the payload, so the `repo` field is informational. - The diff changes only characters inside an existing quoted scalar; no YAML structure changed. ## Skill update n/a — internal only (CI workflow; no user-facing surface). ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). The DCO status check will block merge if any commit is missing a `Signed-off-by:` trailer. - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated (n/a — CI workflow change, no test surface). - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no Linear ticket exists for this rename fallout; the title follows the repo's convention for such chores (cf. #30145). - [x] The **Skill update** section above is filled in. ## Notes for the reviewer - The event-type mismatch predates the rename. prisma-cli's consumer workflow was created on 2026-08-17 listening for `product-published` (prisma/prisma-cli#192); this sender, added on 2026-08-13, was never updated. The daily cron masked the dead letter — a lost dispatch delays the repin by at most a day, which is why nothing visibly broke. - Companion PRs update the other side of the rename: `prisma/orm` `v7` branch (`github.repository` guards), `prisma/engines-wrapper` (workflow dispatch target), and `prisma/prisma-engines` (Makefile clone URL). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated the publication notification event type to `product-published`. * Repository and version information in the notification remain unchanged. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 8 天前 | |
chore: block commits missing DCO sign-off Add a husky commit-msg hook that rejects any commit whose message lacks a Signed-off-by trailer matching the commit author (name + email). This mirrors locally the DCO requirement documented in CONTRIBUTING.md so the remote status check never has to fail the PR. Merge / fixup! / squash! / amend! commits are skipped. Bypass remains available via git commit --no-verify. Signed-off-by: Serhii Tatarintsev <tatarintsev@prisma.io> | 3 个月前 | |
feat(codec-registration-completion): unify codec registration (TML-2357) (#417) <!-- CURSOR_AGENT_PR_BODY_BEGIN --> > **Status: ready for review.** All milestones complete; all 14 acceptance criteria PASS or LANDED at HEAD; validation gates green workspace-wide. Post-implementation surface cleanup (F9 + F10) and post-feedback hygiene round (F11–F39) landed on top. Completes the registration-side migration that the parent codec-registry-unification project (merged via [ADR 208](docs/architecture%20docs/adrs/ADR%20208%20-%20Higher-order%20codecs%20for%20parameterized%20types.md)) deliberately deferred. (TML-2357) ## Spec & plan - [`projects/codec-registration-completion/spec.md`](projects/codec-registration-completion/spec.md) — eight ACs (AC-0..AC-7), three pinning cases. - [`projects/codec-registration-completion/plan.md`](projects/codec-registration-completion/plan.md) — five milestones with validation gates and risks. - [`projects/codec-registration-completion/specs/class-based-codec-design.spec.md`](projects/codec-registration-completion/specs/class-based-codec-design.spec.md) — six implementation-level ACs (AC-CB-1..6) covering the abstract-class hierarchy. ## Milestones | # | Goal | Spec ACs | Status | |---|---|---|---| | **M0** | Class-based codec migration + per-codec helpers + Strength 3 deletion sweep | AC-0, AC-1, AC-CB-1..6 | **SATISFIED** at `a210fa1c5` | | **M1** | Narrow runtime `Codec` instance + descriptor-keyed metadata reads | AC-3 | **LANDED** at `1be7564c4`; reverified through M4 | | **M2** | Native descriptor migration + bridge / `aliasCodec` / `arktypeJsonEmitCodec` deletion | AC-2, AC-4 | **ABSORBED into M0** (Phase B + Phase C) | | **M3** | `ParamRef.refs` plumbing + encode-side `forColumn` + `forCodecId` retirement | AC-5 | **SATISFIED** at `3f0ec224a` | | **M4** | Delete `JsonSchemaValidatorRegistry`; retire `'json-validator'` trait | AC-6 | **SATISFIED** at `e055c9455` | | **F9 + F10** | Public-API surface cleanup: registry-only public surface; drop transition vocabulary | hygiene | **SATISFIED** at `c4d81ad1c` | | **F11–F39** | Post-feedback hygiene round: 27 findings closed; F38 rejected; SQL `CodecRegistry` consolidated into `CodecDescriptorRegistry` | hygiene + correctness | **SATISFIED** at `0e3aafc0b` | | **AC-7** | Validation gates green | AC-7 | **PASS** at every milestone close + every hygiene-round close | ## What landed - **Class-based codec hierarchy.** `interface CodecDescriptor<P>` + `abstract class CodecDescriptorImpl<P>`, paired with `interface Codec<Id, Traits, Wire, Input>` + `abstract class CodecImpl<...>`. Per-codec column helpers (e.g. `vectorColumn(N)`) directly invoke `descriptor.factory(params)` to preserve method-level generics; `satisfies ColumnHelperFor<D>` ties helpers to their descriptor without polymorphism. `AnyCodecDescriptor` (alias for `CodecDescriptor<any>`) is the canonical heterogeneous-storage type. - **Strength 3 forcing-function deletion.** Every legacy carrier deleted: `mkCodec`, `defineCodec`, `defineCodecGroup`, `defineCodecBundle`, `CodecDefBuilder*`, `synthesizeNonParameterizedDescriptor`, instance-keyed `ExtractCodecTypes`, `byScalar` maps, `dataTypes` exports, `sqlCodecDefinitions`, `codecDescriptorDefinitions`, `pgVectorRepresentativeCodec` placeholder, `parameterizedCodecs:` slot, `CodecParamsDescriptor`, `arktypeJsonEmitCodec`, `aliasCodec`, `aliasDescriptor` function form, the `'json-validator'` trait, `JsonSchemaValidatorRegistry` infrastructure, `arktypeParamsSchema` helper, the SQL-family `CodecRegistry` interface (consolidated into `CodecDescriptorRegistry`). Closing-grep zero call-sites. - **`ParamRef` + `ProjectionItem` carry `refs?: { table; column }`**; `validateParamRefRefs` builder-pipeline pass enforces refs for parameterized codec ids; encode/decode dispatch consults `metadata.refs` first via `contractCodecs.forColumn(table, column)`. - **JSON validation lives in the resolved codec's `decode` body** (arktype-json's inline pattern from TML-2229). Decode-error envelope equivalence verified via `codec-async.test.ts:408-456`. - **`ColumnTypeDescriptor` relocated** from `@prisma-next/contract-authoring` (layer 2) to `@prisma-next/framework-components` (layer 1) so codec base types live with the framework primitives. - **F8 portability fix** (`fae3bd688`): `CodecTypes` exposed at the public `exports/codec-types.ts` entry point with a `Resolve<T>` materializer to break tsdown's chunk-private path reference and restore consumer-side typecheck. - **F9 + F10 surface cleanup** (`3d57f9ecd..c4d81ad1c`): each codec-shipping package now exposes only column helpers + a `<package>CodecRegistry` instance + `type` re-exports of descriptor types. Internal `codecDescriptorMap` / `codecDescriptorClassList` no longer surface through public exports. Transition vocabulary (`Class` suffixes, `class-form` / `class-based` in comments, `codecs-class.ts` filenames) scrubbed. ## Post-feedback hygiene round (F11–F39) 19 commits between `c4d81ad1c..0e3aafc0b` close 27 findings surfaced from orchestrator-principal review and 30 GitHub PR review threads. Highlights: - **F11** (`f725db1f8`) — rename `ast/sql-codecs-class.ts` → `ast/sql-codecs.ts`, split helpers into `ast/sql-codec-helpers.ts`. - **F12** (`7d56a39b4`) — move parameterization predicate onto `CodecDescriptorImpl.isParameterized` getter; retire the standalone `IsParameterizedCodecId` callback type. - **F13 + F14 + F20** (`cfa078a23`) — align arktype params schemas with `TParams` optionality (`'length?': '...'`); delete `arktypeParamsSchema` helper; consumer sites direct-assign with `: StandardSchemaV1<TParams>`. The `arktype` runtime dep stays in `@prisma-next/contract` because `validate-contract.ts` consumes it directly for structural validation — that's by design, not a follow-up. - **F15** (`1051f24e8`) — replace `unique symbol` trait phantom with a string-key phantom property (`__codecTraits`) to avoid Node bundling failure modes. - **F16 + F17** (`083fff350`, `a278bd034`) — rewrite codec-authoring-guide alias section + fix self-referential JSDoc helper-source reference. - **F18** (`7ee52fae0`) — assert leaf scalar type in `no-emit-typed-flow.test-d.ts` to make AC-CB-6's literal claim explicit. - **F19 + F31 + F32 + F33** (`81c55248f`, `bc4e8d716`) — harden `extractCodecLookup`: lift inline imports, tighten `id` to non-optional `string`, refine the silent catch so non-parameterized codecs throw immediately while parameterized factories that tolerate empty params still materialise representatives. - **F21** (`f1be14d55`) — `createStubAdapter` returns a stable codec registry instance (no per-call rebuild). - **F22 + F26 + F29** (`20f99bffd`) — dispatch correctness: `refsFromLeft` walks via `collectColumnRefs` to preserve refs for wrapping expressions; encode-side `forColumn` fall-through is structurally safe (F19 + `ambiguousCodecIds` rejection + `byCodecId` column-correct materialisation); pgvector `length` threaded into `PgVectorCodec` constructor with `assertVector` validating the dimension at every ingress. - **F23 + F24 + F25** (`48ed1d135`) — type predicate `isArktypeSchemaLike` replaces blind cast in `rehydrateSchema`; `@ts-expect-error` replaces `as any` + biome-ignore in tests; `toExtend` replaces deprecated `toMatchTypeOf` matcher. - **F27** (`21b4cbca7`, `0e3aafc0b`) — retire SQL-family `CodecRegistry.register()` mutation surface in favour of `buildCodecRegistry(descriptors)` builder; phase-2 deletes the `CodecRegistry` interface entirely. Single registry surface in the SQL family is now `CodecDescriptorRegistry`. - **F28** (`9881a7efe`) — `buildCodecDescriptorRegistry` throws on duplicate `codecId`. - **F30** (`7a3faf20f`) — `codecDescriptorMap` relocated to `core/codec-type-map.ts`; `Resolve<T>` materialisation kept at the `exports/` boundary per F8. - **F34 + F35 + F36** (`4178072fa`) — postgres render hygiene: scale validation in `pgNumericRenderOutputType`; ISO 8601 regex for timestamps; string validation for enum values. - **F37** (`182d10c88`) — `SqliteDatetimeCodec` rejects `Invalid Date` in decode/decodeJson. - **F38** — **rejected.** Default identity codecs on `CodecImpl` would constrain its type signature and obscure where real conversion work happens. Convention stays: explicit identity overrides at codec-author site. - **F39** (`80ba4fd60`) — `enumParamsSchema` and `EnumParams` tightened to `readonly string[]`. Closure-mechanism note for F22: the implementer chose a structural argument over fail-fast on `forColumn` miss — F19's refinement makes `extractCodecLookup` skip parameterized descriptors that don't tolerate empty params; `buildContractCodecRegistry`'s `ambiguousCodecIds` set throws `RUNTIME.TYPE_PARAMS_INVALID` on multi-instance ids; for the non-ambiguous parameterized case `byCodecId` stores the column-correct per-instance codec. Reviewer cross-checked all three legs and accepted. ## Notable side effect: 16 pre-existing e2e failures resolved by M3 Before M3, the e2e suite ran 75/91 with 16 failures of the form `Codec '...' resolves to multiple parameterized instances; column-aware dispatch is required.` — top-level field shortcuts (`select('vectorCol')`) emitted `IdentifierRef` AST that didn't carry `(table, column)` context, so decode-side `resolveProjectionCodec` fell back to `forCodecId` and threw. M3's `ProjectionItem.refs` extension + decode-side parity in `decoding.ts` closed the path. **e2e is now 91/91.** ## Validation gates at HEAD `0e3aafc0b` | Gate | Result | |---|---| | `pnpm typecheck` | PASS — 123/123 | | `pnpm lint:deps` | PASS — 727 modules / 1444 deps / 0 violations | | `pnpm fixtures:check` | PASS — zero drift (demo emit byte-identical against `origin/main`) | | `pnpm build` | PASS — 62/62 | | `pnpm test:e2e` | **PASS — 91/91** (16 pre-existing failures resolved by M3) | | `pnpm test:packages` | PASS in scope (residual: pre-existing 7 sql-orm-client pgvector wire-format + TML-2402 parallel-flake) | ## Review artifacts `projects/codec-registration-completion/reviews/` carries three review artifacts produced by the reviewer subagent during orchestration. After user feedback that the initial structure didn't match the canonical skill output, all three were rewritten to conform to `/drive-pr-local-review` (flat F-numbered findings + AC verification table) and `/drive-pr-walkthrough` (intent-first semantic narrative). Final reviewer verdict at HEAD `0e3aafc0b`: **SATISFIED** with 12 PASS / 2 WEAK on the AC scoreboard. The two WEAKs are AC-7 (acknowledged baseline test failures in sql-orm-client pgvector wire format + TML-2402 parallel flake) and AC-CB-5 (a single internal `descriptor as unknown as AnyDescriptor` cast inside `buildCodecDescriptorRegistry` — purely a registry-internal heterogeneous-storage erasure, not a public surface concern). ## Linear follow-ups filed during close-out - **[TML-2402](https://linear.app/prisma-company/issue/TML-2402)** — `pnpm test:packages` parallel-execution flake (`adapter-postgres` / `cli` / `sql-orm-client`; passes cleanly in isolation). P3. - **[TML-2403](https://linear.app/prisma-company/issue/TML-2403)** — Turbo cache-keying gap on transitive AST/type-system changes (worked around with `pnpm build --force`). P4. - **[TML-2405](https://linear.app/prisma-company/issue/TML-2405)** — Codec dispatch follow-up: reference codec instances on the lowered Plan instead of carrying `(table, column)` lookup keys on the AST. The current shape's validator pass is a smell; instance-on-Plan would retire `forColumn`/`forCodecId` from the runtime dispatch surface entirely. Architectural successor to this work. P3. ## Out of scope - **Mongo codec registration migration** — folded into [TML-2324](https://linear.app/prisma-company/issue/TML-2324) (Mongo runtime `forColumn` plumbing). - **Renaming `Codec`** — type name stays; only the field set narrows. - **Reshaping the async codec runtime** ([ADR 204](docs/architecture%20docs/adrs/ADR%20204%20-%20Single-Path%20Async%20Codec%20Runtime.md)) or `CodecCallContext` ([ADR 207](docs/architecture%20docs/adrs/ADR%20207%20-%20Codec%20call%20context%20per-query%20AbortSignal%20and%20column%20metadata.md)). - **`pgEnumCodec` placeholder factory audit** (already clean at HEAD; documented in ADR 208 § Future work). - **Retiring `CodecLookup.get(id)` and `ProjectionItem.refs` / `ParamRef.refs` lookup-key carriers from the AST** — TML-2405. ## Note on project artifacts Per the user's mid-flight directive at close-out, `projects/codec-registration-completion/` is **preserved in-tree** (the standard transient-directory deletion was reverted at `5b0113a5a`). The directory's review artifacts under `reviews/` are gitignored and don't appear in the diff; they live in the working tree only as historical context. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-a00fe249-d674-4cb5-8939-5b9d17b36650"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-a00fe249-d674-4cb5-8939-5b9d17b36650"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Unified descriptor-driven codec system and class-based codec authoring; per-codec column helpers. * Codecs now receive per-call context (AbortSignal + column provenance). * **Documentation** * Added codec authoring reference and multiple ADR updates clarifying descriptor and async model. * **Improvements** * Stronger parameter validation and improved output-type rendering for parameterized codecs. * Query builder/runtime now propagate column refs into expressions and parameter encoding. * **Tests** * Expanded type and runtime tests covering descriptor-driven flows and helpers. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> | 3 个月前 | |
chore: add workspace settings for Zed editor (#22) Translate the settings in `.vscode/settings.json` to `.zed/settings.json`: - Set up Biome as the formatter for the supported file types. - Configure vtsls to use the workspace version of `tsserver` automatically (it does already seem to be the behaviour for me by default anyway, maybe due to other global settings, so I'm not sure it's strictly necessary, but this option isn't set by default according to the vtsls docs, so it doesn't hurt to enable it explicitly). | 9 个月前 | |
The Prisma 8 language server ignores documents without the use prisma-next directive (#30140) ## Linked issue n/a — no Linear ticket. Part of the extension routing model where both the legacy (Prisma ≤7) and Prisma 8 language servers receive document sync for all `.prisma` files and each decides ownership locally; the legacy server's half is already implemented in `prisma/language-tools`. ## At a glance ```ts // packages/1-framework/3-tooling/language-server/src/schema-directive.ts const PRISMA_NEXT_DIRECTIVE = /^\s*\/\/ *use +prisma-next *(?!\S)/; export function isPrismaNextSchema(text: string): boolean { return PRISMA_NEXT_DIRECTIVE.test(text); } ``` A document whose first non-whitespace content is a `// use prisma-next` line comment is this server's responsibility; everything else belongs to the legacy server and is now ignored — feature requests return the protocol's empty result, and the push path publishes an **empty** diagnostics array (not nothing), so an edit that removes the directive clears this server's stale squiggles as ownership flips back mid-edit. Before this PR, the server diagnosed every configured input regardless of the directive. ## Decision `prisma lsp` decides per request, from current document content, whether a document is a Prisma Next schema: 1. **One ownership gate at the artifacts seam.** `computeDocumentDiagnostics` — the existing "do we own this document" decision that already returns `null` for non-configured inputs — now also returns `null` when the text lacks the directive. Every feature path (push/pull diagnostics, completion, semantic tokens, folding) and multi-file schema composition reads through this seam, so one check covers them all. 2. **No caching of ownership.** The regex is re-tested lazily from the current text at each publish/request, so adding or removing the directive flips ownership immediately in both directions. Document sync itself is untouched — unmarked documents stay tracked. 3. **A local copy of the shared convention.** The regex is the only coupling with the legacy server; it must stay byte-for-byte in sync with the copy in `prisma/language-tools`. This server does not import, spawn, or proxy to the legacy server. ## Reviewer notes - **The bulk of the diff is test-source churn, not behavior.** Every pre-existing test schema gained the directive line, which shifted line-sensitive expectations: semantic-token arrays gained the leading comment token (`0, 0, 18, 9, 0`) plus a line delta, formatting ranges grew a line, and the fabricated interpreter-diagnostic spans moved by the 19-character directive line (interpreter mapping is offset-based). The new behavior is concentrated in the `prisma-next directive gating` describe at the end of [test/server.test.ts](packages/1-framework/3-tooling/language-server/test/server.test.ts). - **Unconfigured documents still publish nothing at all** (pre-existing, still asserted). The explicit empty publish applies to *configured inputs* without the directive — the only case where this server could have stale markers to clear. - **`getProjectSymbolTable` now guards instead of throwing.** With gating, a project can have open configured inputs that are all unmarked; the public accessor returns `undefined` for a document without artifacts rather than reaching the "no readable configured input" invariant throw in [src/project-artifacts.ts](packages/1-framework/3-tooling/language-server/src/project-artifacts.ts). Internal callers (completion, semantic tokens) already only read the symbol table after confirming the requested document's artifacts. - **By the regex's own grammar, `// use prisma-next extra words` matches** (the lookahead only rejects a token *attached* to `prisma-next`, e.g. `prisma-nextgen`). That behavior is pinned in [test/schema-directive.test.ts](packages/1-framework/3-tooling/language-server/test/schema-directive.test.ts) so a well-meaning "fix" can't silently desync us from the legacy server. - The `lsp-playground` sample fixture gained the directive so the playground keeps demonstrating live diagnostics. ## How it fits together 1. **The directive helper** ([src/schema-directive.ts](packages/1-framework/3-tooling/language-server/src/schema-directive.ts)) holds the regex and `isPrismaNextSchema`. 2. **The gate** lands in [src/document-diagnostics.ts](packages/1-framework/3-tooling/language-server/src/document-diagnostics.ts): an unmarked configured input computes to `null`, exactly like a non-input. The project artifacts store therefore never caches artifacts for unmarked documents, which is what makes the check lazy — `documentChanged` drops the cache and the next read re-tests the current text. 3. **Everything downstream falls out of the seam.** The push path already publishes `[]` when a tracked document has no artifacts; pull reports, completion, semantic tokens, and folding already return their empty results; and `symbolTable()` composition skips inputs that yield no artifacts, so an unmarked sibling never becomes part of a Prisma Next schema. 4. **Formatting is the one path that bypasses the store** (it formats raw buffer text), so [src/server.ts](packages/1-framework/3-tooling/language-server/src/server.ts) re-tests the directive there before formatting — a document the legacy server owns must not be reformatted by this server. ## Behavior changes & evidence - A configured input without the directive gets an explicit empty diagnostics publish on open and on every change, and empty results for completion, semantic tokens, folding, formatting, and pull diagnostics ([src/document-diagnostics.ts](packages/1-framework/3-tooling/language-server/src/document-diagnostics.ts); evidence: `prisma-next directive gating` in [test/server.test.ts](packages/1-framework/3-tooling/language-server/test/server.test.ts)). - An edit that removes the directive from a handled document publishes empty diagnostics and stops answering feature requests; an edit that adds it starts diagnosing from the edited content ([test/server.test.ts](packages/1-framework/3-tooling/language-server/test/server.test.ts)). - With a marked and an unmarked file open in the same project, the unmarked file is excluded from schema composition — the project symbol table contains only the marked file's models ([src/project-artifacts.ts](packages/1-framework/3-tooling/language-server/src/project-artifacts.ts); evidence: [test/project-artifacts.test.ts](packages/1-framework/3-tooling/language-server/test/project-artifacts.test.ts)). - The directive grammar itself — leading blank lines and flexible spacing accepted, attached tokens and block comments rejected — is pinned in [test/schema-directive.test.ts](packages/1-framework/3-tooling/language-server/test/schema-directive.test.ts). - The package README ([README.md](packages/1-framework/3-tooling/language-server/README.md)) is trimmed to a short description and now states the directive-ownership rule up front. ## Testing performed - `pnpm test` in `@internal/language-server` — 292 tests, 15 files, all green (includes the new gating suites). - `pnpm typecheck` and `pnpm lint` in the package (lint output identical to baseline). - `pnpm lint:deps` at the root. - `pnpm test:packages` at the root — 1171 files passed; the 5 failing tarball-packaging smoke tests (`pnpm pack`/`pnpm install` in temp dirs) reproduce identically on a clean checkout and are unrelated. ## Skill update n/a — no skill under `packages/0-shared/skills/` documents language-server behavior; the ownership model is documented in the package README instead. ## Alternatives considered - **Gating in each request handler** instead of at the artifacts seam — would need five-plus checks that drift independently; the seam already models "document we own" via its `null` return, so ownership stays a single decision. - **Caching an "owned" flag on open/change** — a cached flag can go stale across edits and config reloads; the regex test is one cheap call per event, so lazy re-evaluation from current text is both simpler and correct by construction. - **Publishing nothing for unmarked configured inputs** — publishing an explicit empty array is what clears stale squiggles when an edit removes the directive mid-session; silence would leave this server's markers stranded while the legacy server takes over. - **Sharing the regex via a common package with the legacy server** — rejected up front: this server must not depend on the legacy server in any way. The shared directive convention is the only coupling, hence a local copy of the regex. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). The DCO status check will block merge if any commit is missing a `Signed-off-by:` trailer. - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated (or `n/a` if the change is doc-only / refactor with no behavioural delta). - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no Linear ticket exists for this change; the title is a plain sentence-case description. - [x] The **Skill update** section above is filled in (or stated `n/a — internal only`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added opt-in schema processing through the `// use prisma-next` directive. * Unmarked documents are excluded from diagnostics, formatting, tokens, folding, AST results, and symbol tables. * Adding or removing the directive updates language-server processing automatically. * **Bug Fixes** * Prevented unmarked sibling documents from affecting schema composition. * **Tests** * Added comprehensive coverage for directive detection and language-server behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 13 天前 | |
refactor(lint): find framework vocabulary with a Biome plugin, not a text scan (#29988) The framework-vocabulary check was a bespoke line scanner. It is now a Biome GritQL plugin plus a counting ratchet, matching the pattern `no-bare-cast` and `no-bare-throw` already use. ## Why **Over half of what it counted was documentation.** 433 of the 801 lines it flagged were comments and JSDoc, and sampling them shows what they are: `* family-parameterized (SQL, Mongo, etc. specialize via TStorage)`, `* Family storage types (SqlStorage, MongoStorage, etc.) extend this`. That is the right way to document a generic mechanism, and the checker taxed it while burying its own signal. Matching syntax nodes ignores comment trivia, so the count now reflects real surface: types, fields, identifiers, string literals, import paths. **Suppression is now aimed and self-policing.** `// biome-ignore lint/plugin/no-family-vocabulary: <reason>` silences one line, requires a reason, and a suppression naming the wrong plugin is reported as `suppressions/unused` rather than rotting silently. The previous escape hatches were renaming to a synonym or raising the committed threshold — the first changes what users read to satisfy a linter, the second makes the number drift for reasons that are not leakage. ## Count 364, down from 801. The drop is the comments, by design. ## Scoping Biome 2.5.6 does support `plugins` inside `overrides`, and they add to the top-level list rather than replacing it — but scoping that way silently under-covers. An override's `includes` glob resolves against the config in effect for the file, and most framework packages ship their own `biome.jsonc` extending the root, so a root-level `packages/1-framework/**` glob reached only 63 of 473 sites. The plugin is registered top-level and scoped by a `$filename` guard instead, which sees the whole path. Verified: across all of `packages/`, every diagnostic lands under `packages/1-framework`. ## Known difference Five sites inside multi-line template literals now report at the chunk's first line rather than once per line, because a template chunk is one syntax node. Every affected chunk is still flagged — the resolution inside a chunk is coarser, nothing escapes. Documented in the plugin header. ## Verified - Flags `readonly table`, `parentColumns`, `nativeType`, `'@prisma/orm-postgres/config'`, `SQLite`, `PostgreSQL` - Ignores `abortable`, `urls`, `tableau`, `SQLQueryPlan`, and every comment and JSDoc line - Silent on an identical file outside `packages/1-framework` - `lint:casts` 841/841 and `lint:throws` 47/47 unchanged — the third plugin disturbs neither <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added automated detection of family- or target-specific vocabulary in framework code. * Added guidance for suppressing approved exceptions and managing vocabulary thresholds. * **Bug Fixes** * Improved detection across identifiers, strings, module paths, regular expressions, and templates. * Excluded comments and test files from findings while honoring approved framework-neutral terms. * **Tests** * Expanded integration coverage for diagnostics, duplicate findings, thresholds, suppressions, exclusions, and listing output. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 27 天前 | |
TML-3199: Docs hygiene — dead links, stale API instructions, and the payload label (#30016) # Docs hygiene: dead links, stale API instructions, and the payload label Main-based cleanup (not part of the raw-SQL stack, though its items were surfaced by that campaign's reviews). ## What changed - **ADR-INDEX's dead ADR 035 link** — a pure capitalization mismatch (`Dual authoring conflict resolution` vs the file's `Dual Authoring Conflict Resolution`); corrected to the file's actual name. - **`error-reference.md`: "Meta:" → "Payload:" (260 entries) + one preamble sentence.** The old label was wrong for half the file: `structuredError()` writes `error.meta` but `runtimeError()` writes `error.details`, and a scripted classification showed a per-code label is ill-defined — of the codes classifiable at all, eight are raised through *both* constructors. The neutral label plus a preamble stating the rule (meta from structuredError, details from runtimeError, some codes both ways) is accurate today and stays accurate as raise sites move. No tooling reads the label (verified against `list-error-codes.mjs`). - **Stale `validateContract<Contract>(contractJson)` instruction removed from four surfaces** (`AGENTS.md` § Key Patterns, Testing Guide ×3, the Runtime subsystem doc, and the `typed-contract-in-tests` rulecard) — no such export exists, and the stale pattern had already generated a false review finding. Replacements verified against current code: the client factory hydrates (`postgres<Contract>({ contractJson, url })`), and tests use `validateSqlContractFully<Contract>(contractJson)` (the idiom with 174 current usages). The `validateContract` in `family-instance-domain-actions` is deliberately untouched — that one is the real ADR 204 control-plane primitive, a different thing sharing the name. - **ADR 012's refs clause** now states ADR 205's own conclusion: the unindexed-predicate lint and refs-based budget heuristic ran off the removed sidecar and no longer run for any plan. (The previous wording invited a hunt for a `meta.refs` field that no longer exists.) - **One ticketed item needed nothing**: the four "dead" source links in the Runtime & Middleware doc were already fixed upstream — verified resolving, left alone. ## Known merge note This PR and the raw-SQL stack (#29997) both edit the tail of the same ADR 012 update note, for different reasons. The conflict is one line but **semantic**: whichever lands second must carry both intents (the stack scopes the wire-level-rows claim as historical; this states the refs heuristics gone). Taking either side wholesale silently drops the other. Out of scope, ticketed: 68 further dead links across `docs/` + the missing link checker, two orphaned error-reference entries the one-directional checker cannot see, and ADR 205's own upstream ambiguity (all on TML-3211). Refs: TML-3199 https://claude.ai/code/session_01NnNjsNcPMtbJZhnZz5Zzbe <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated contract hydration and validation guidance to reflect the current workflow. * Refreshed testing and runtime examples for standalone contract usage. * Corrected architecture decision record titles, links, and descriptions of removed raw-plan metadata. * Clarified that contract data can be passed directly through runtime setup. * **Tests** * Updated typed contract fixture guidance to use full SQL contract validation for parsed contract data. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 8 天前 | |
TML-3166: Close the affected-row-counts project (#30007) ## Linked issue Refs [TML-3166](https://linear.app/prisma-company/issue/TML-3166) Delivered by [#29907](https://github.com/prisma/prisma/pull/29907), [#29920](https://github.com/prisma/prisma/pull/29920), and [#29921](https://github.com/prisma/prisma/pull/29921). ## At a glance ```ts interface SqlQueryable { query<Row>(request: SqlExecuteRequest): AsyncIterable<Row> execute(request: SqlExecuteRequest): Promise<{ affectedRows: number }> } ``` The project is complete: count-returning writes use one statement and return the database-reported statistic rather than counting rows from a preceding read. ## Decision Close the affected-row-counts project by preserving its durable architecture and semantics in the canonical ADRs, subsystem documentation, and scorecards, then deleting the transient project workspace. ## Project DoD verification - The SQL driver SPI has separate row-query and statement-statistics operations, with prepared-ness carried by the request handle. - Postgres and SQLite return real `affectedRows` values, and Mongo maps `modifiedCount` or `deletedCount` according to the command kind. - `updateAndCount` and `deleteAndCount` issue one write statement; integration coverage proves the returned count comes from that write. - The pre-`SELECT` fallback and retired operation names are absent. - ADR 210 documents the two-method prepared-statement SPI and `DRIVER.PREPARE_FAILED` under ADR 239. - ADR 215 and the runtime subsystem documentation describe the operation-specific query and execute middleware lifecycles. - SQL and Mongo scorecards record the shipped count-terminal behavior and target-specific semantics. - Manual documentation QA passed for both application users and extension/driver/middleware authors. - The mandatory final retro landed a dispatch-DoR guard requiring explicit design-owner approval for public or cross-family API shapes. - All tracked project artifacts are deleted and no tracked references to the removed workspace remain. ## How it fits together 1. ADR 210 records the two-method SQL driver contract and the runtime-owned prepared-handle lifecycle. 2. ADR 215 and the runtime subsystem page describe `beforeQuery` / `interceptQuery` / `afterQuery` separately from `beforeExecute` / `interceptExecute` / `afterExecute`. 3. The Mongo subsystem and both scorecards state each target's native affected-row semantics and point to qualifying evidence. 4. The reusable process lesson lands in Drive's dispatch Definition of Ready. 5. The transient specs, plans, dispatch briefs, decision log, QA artifacts, and retro log are removed. ## Notes for the reviewer The large runtime-documentation diff replaces stale generic middleware terminology with the operation-specific lifecycle on `main`. ADR 215 preserves the original May 2026 decision and its rationale under a historical section while adding the August 2026 amendment. The manual-QA script, report, and retro were created and committed as close-out evidence before being removed with the rest of the transient workspace; their evidence remains in this branch's signed commit history. ## Testing performed - Manual QA: durable-documentation read-through for application and extension-author audiences — pass, no findings - Local Markdown link validation — no missing links - `pnpm lint:docs` — pass, with pre-existing package README warnings - `git diff --check origin/main...HEAD` — pass - Source and integration behavior — green on merged PR #29921 CI, including Test, Integration Tests, E2E, Coverage, Type Check, Lint, and Supabase Acceptance ## Skill update The existing Prisma Next upgrade instructions shipped with #29921. This close-out adds no new user-facing API change. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are n/a for this documentation and project-cleanup PR; merged implementation CI and close-out manual QA provide the behavior evidence. - [x] The PR title is in `TML-NNNN: <sentence-case title>` form. - [x] The Skill update section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Query and execute operations now have distinct lifecycles and results: queries stream rows, while executions report affected-row statistics. * SQL and MongoDB provide clearer update and delete counts, including no-op updates and deleted-document totals. * Prepared statement and transaction behavior is documented with clearer lazy execution and resource handling details. * **Documentation** * Updated architecture, middleware, MongoDB, SQL ORM, and scorecard documentation to reflect current behavior and supported operations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 26 天前 | |
#30153: Export reusable where filter types (#30158) ## Linked issue Closes #30153 ## At a glance SQL builder: ```ts import type { WhereFilter } from '@prisma/orm-postgres/builder/types'; import type { Contract } from '../src/prisma/contract'; import { db } from '../src/prisma/db'; const users = db.sql.public.user.select('id', 'email', 'createdAt'); function userById(id: string): WhereFilter<Contract, 'public', 'user'> { return (fields, operators) => operators.eq(fields.id, id); } users.where(userById('00000000-0000-0000-0000-000000000001')); ``` SQL ORM, with shorthand and predicate forms side by side: ```ts import type { RelationPredicate, ShorthandWhereFilter } from '@prisma/orm-postgres/orm-client'; import { createOrmClient } from '../src/orm-client/client'; import type { Contract } from '../src/prisma/contract'; function userById(id: string): ShorthandWhereFilter<Contract, 'public', 'User'> { return { id }; } function userByIdPredicate(id: string): RelationPredicate<Contract, 'public', 'User'> { return (user) => user.id.eq(id); } const db = createOrmClient(null as never); const userId = '00000000-0000-0000-0000-000000000001'; db.User.where(userById(userId)); db.User.where(userByIdPredicate(userId)); ``` These real integration-test examples show the new SQL builder annotation and the namespace-qualified ORM annotations in use. In both lanes, field mistakes are reported inside the helper body while the returned filter passes directly to `.where()`. ## Decision This PR ships three connected pieces: 1. A public SQL builder `WhereFilter<Contract, Namespace, Table>` type exported from `@prisma/orm-postgres/builder/types`. 2. Namespace-precise SQL ORM standalone filters using the existing `ShorthandWhereFilter<Contract, Namespace, Model>` and `RelationPredicate<Contract, Namespace, Model>` names. 3. Compile-only integration coverage and RC upgrade instructions that prove and explain the public API through the PostgreSQL facade. ## Summary Extracting a SQL builder `where()` callback currently loses contextual typing unless users reconstruct internal signatures or cast the result. This change adds a supported public builder type for that pattern and makes the existing SQL ORM reusable filter types namespace-precise, keeping errors and autocomplete at the helper definition where they are actionable. ## Reviewer notes - The SQL ORM generic change is intentionally breaking: namespace is now required and appears before model. Existing annotations need the migration recorded in this PR. - Relation predicates carry the target namespace from `relation.to.namespace`; emitted branded namespace IDs are normalized back to concrete contract namespace keys. - Runtime query behavior and generated SQL are unchanged. The small `find-user-by-id` cleanup removes an unnecessary ID cast discovered while adding the public-facade integration type tests. ## How it fits together 1. [`WhereFilter`](packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts) binds the existing expression callback to the selected table's `DefaultScope` and contract query context, then [`exports/types.ts`](packages/2-sql/4-lanes/sql-builder/src/exports/types.ts) exposes only that consumer-facing type. 2. [`types.ts`](packages/3-extensions/sql-orm-client/src/types.ts) makes the domain namespace a required coordinate for ORM shorthand filters, predicates, and relation filter accessors, so fields and operations resolve against one exact model facet. 3. [`collection.ts`](packages/3-extensions/sql-orm-client/src/collection.ts) and [`model-accessor.ts`](packages/3-extensions/sql-orm-client/src/model-accessor.ts) carry that namespace through `.where()`, `.first()`, ordering, grouped collections, and nested relation accessors. 4. Public-facade type tests in the PostgreSQL demo exercise both authoring forms and pin negative diagnostics to nonexistent fields inside the helper bodies. 5. The app and extension upgrade transitions explain how to migrate existing ORM filter annotations. ## Behavior changes & evidence - **SQL builder filters can be named, parameterized, and reused with table-specific fields and operators.** The public surface is defined in [`table-proxy.ts`](packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts) and [`exports/types.ts`](packages/2-sql/4-lanes/sql-builder/src/exports/types.ts), with package and facade evidence in [`where-filter.types.test-d.ts`](packages/2-sql/4-lanes/sql-builder/test/types/where-filter.types.test-d.ts) and [`sql-builder-filter.types.test-d.ts`](examples/prisma-8-demo/test/sql-builder-filter.types.test-d.ts). - **SQL ORM shorthand and predicate helpers retain model-specific autocomplete and local diagnostics.** Namespace-aware definitions live in [`types.ts`](packages/3-extensions/sql-orm-client/src/types.ts) and flow through [`collection.ts`](packages/3-extensions/sql-orm-client/src/collection.ts) and [`model-accessor.ts`](packages/3-extensions/sql-orm-client/src/model-accessor.ts); [`user-filter.types.test-d.ts`](examples/prisma-8-demo/test/user-filter.types.test-d.ts) proves both forms through `@prisma/orm-postgres/orm-client`. - **Namespace collisions resolve to the correct model facet.** [`orm-namespace-unique-fields.types.test-d.ts`](packages/3-extensions/sql-orm-client/test/orm-namespace-unique-fields.types.test-d.ts) proves that `public.User` and `auth.User` expose different fields and that missing or unknown namespace coordinates fail at compile time. - **Existing ORM filter annotations receive an explicit migration path.** The app and extension transitions in [`8.0.0-rc.8-to-8.0.0-rc.9`](skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.8-to-8.0.0-rc.9/instructions.md) and its [`extension counterpart`](skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.8-to-8.0.0-rc.9/instructions.md) describe adding and reordering the namespace coordinate. ## Testing performed - `pnpm --filter @internal/sql-builder test` — 13 test files, 171 tests passed. - `pnpm --filter @internal/sql-orm-client test` — 70 test files, 772 tests passed, no type errors. - `pnpm --filter prisma-8-demo test` — 14 test files, 73 tests passed, including all 26 repository integration cases. - `pnpm --filter @internal/sql-builder typecheck` - `pnpm --filter @internal/sql-orm-client typecheck` - `pnpm --filter prisma-8-demo typecheck` - `pnpm lint:deps` - `pnpm lint:skills` - `pnpm check:upgrade-coverage` - `git diff --check` ## Skill update The public ORM type signature change is recorded for both application and extension consumers in the `8.0.0-rc.8` → `8.0.0-rc.9` upgrade instructions. `pnpm lint:skills` and `pnpm check:upgrade-coverage` pass. ## Alternatives considered - **Export the builder machinery directly.** Exposing `Scope`, `QueryContext`, `ExpressionBuilder`, and `FieldProxy` would let consumers reconstruct the callback type, but would make internal query representation part of the supported API. `WhereFilter` supplies the useful contract coordinate without that leakage. - **Add `PredicateFor` and a union-shaped `WhereInput`.** `WhereFilter` matches the method it targets, while the existing `ShorthandWhereFilter` and `RelationPredicate` names keep the ORM's object and callback authoring forms explicit instead of hiding them behind one broad union. - **Keep namespace optional or after model.** Optional namespace lookup becomes imprecise when model names collide. Requiring `<Contract, Namespace, Model>` matches the contract coordinate order and guarantees useful autocomplete. - **Document `Parameters<...>` or casts as the workaround.** Those approaches duplicate complexity at every helper and can move diagnostics to the eventual `.where()` call. A first-class exported type keeps the error at its source. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated. - [x] The PR title uses the linked GitHub issue prefix because this issue has no Linear ticket. - [x] The **Skill update** section above is filled in. ## Notes for the reviewer The main compatibility consideration is the intentionally required ORM namespace coordinate; matching app and extension upgrade instructions ship in this PR. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - SQL ORM filter and relation types now support namespace-qualified model references. - Added reusable, publicly available filter type support for SQL builder workflows. - Namespace-aware typing improves autocomplete and validation across filtering, sorting, and relation queries. - **Bug Fixes** - Invalid fields and unknown namespaces are now rejected more reliably during TypeScript checks. - **Documentation** - Added upgrade guidance for updating reusable ORM filter type parameters. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 11 天前 | |
chore: better readme (#219) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated README navigation and project framing * Added TypeScript code examples demonstrating fluent query API patterns and extension pack configuration * Enhanced "Getting Started" section with prerequisites, workflow steps, and demo instructions * Clarified API stability messaging and contribution guidelines <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com> | 6 个月前 | |
fix(framework-components): call descriptor.factory as a method (#30222) ## Summary `materializeCodec` evaluated `descriptor.factory` to a bare value before calling it, so `this` was `undefined` inside the factory. Every codec built as `new XCodec(this)` — the standard pattern for class-based codecs — received `descriptor === undefined`. `CodecImpl.get id()` is `this.descriptor.codecId`, so `codec.id` threw on every such codec. ## Why it went unnoticed `id` is read almost nowhere: the decode and encode failure wrappers read it to build their message, and little else does. So the fault only surfaced on an already-failing path — and when it did, it replaced a diagnostic that names the column with one that names nothing: ``` TypeError: Cannot read properties of undefined (reading 'codecId') ``` The wrapper's real message — `Failed to decode column <table>.<column> with codec '<id>'` — already existed and never got the chance to render. Both `decoding.ts` and `encoding.ts` were affected. ## The change ```diff - return blindCast< - (params: unknown) => (ctx: CodecInstanceContext) => Codec, - 'registry erases P to any; paramsSchema validates input before forwarding' - >(descriptor.factory)(validated)(ctx); + return descriptor.factory(validated)(ctx); ``` The `blindCast` is not needed once the call is a method call: `AnyCodecDescriptor` is `CodecDescriptor<any>`, so the validated params pass without narrowing. Net one fewer cast against the ratchet. ## Blast radius `this.descriptor` is dereferenced at four production sites (`codec.ts:73`, the postgres and sqlite codec descriptors). None branches or memoises on it, so nothing depended on the `undefined`. Closure-style factories were already correct — `PostgresCodecDescriptorAdapter` assigns `this.factory = (params) => descriptor.factory(params)`, an arrow that forwards regardless of receiver. So adapted extension descriptors (pgvector, postgis, arktype-json) were unaffected; only directly-declared `CodecDescriptorImpl` subclasses were broken. ## Testing `materialize-codec.test.ts` covers a non-parameterized and a parameterized descriptor whose factories use `new XCodec(this)`, and asserts `codec.id`. Verified load-bearing: against `main`'s version 2 of the 3 cases fail with the exact `Cannot read properties of undefined (reading 'codecId')` above. - `@internal/framework-components`: 54 files, 628 tests - Codec consumers: `@internal/sql-runtime` 343, `@internal/target-postgres` 1596, `@internal/adapter-postgres` 867 + 3 expected-fail - Repo `pnpm typecheck`: 166/166; package lint clean ## Provenance Salvaged from #30195, which was closed. That PR paired this fix with an interim `::text[]` projection cast for enum-array decoding; the cast is superseded by target-owned list framing, but this defect is unrelated to framing and is worth landing on its own. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01UcqoY3CKfnubdZt5YQk2Rq <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed codec creation so descriptor-bound factories retain the correct context. * Ensured both standard and parameterized codec references resolve correctly, including encoding and decoding behavior. * **Tests** * Added coverage for codec materialization with non-parameterized and parameterized codecs. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> | 1 天前 | |
TML-3227: central attribute-spec registration machinery (registry-core) (#30154) First slice of the attribute-registry project: every consumer of PSL attribute knowledge — family interpreters and the language server — gets one shared registration surface, delivering the central-registration follow-up that ADR 231 deferred. This slice builds the machinery end-to-end and proves it LSP-consumable; registering the actual SQL/Mongo built-in sets and block-level attributes follow as parallel slices (TML-3228/3229/3230). ## Changes - **Contribution surface (`@internal/framework-components`)**: `AuthoringContributions` gains an optional `attributeSpecs` key (`{ model, field }` records) whose entries transit core erased as `unknown` — core cannot name `AttributeSpec` (it lives in the PSL authoring layer), the same erasure pattern the descriptor `spec` field already uses. `AssembledAuthoringContributions.attributeSpecs` is required; assembly merges per level with duplicate-name, non-function-entry, and prototype-polluting-name rejection (`mergeAuthoringAttributeSpecs` in `framework-authoring.ts`). - **Uniform factory ctx + assembled view (`@internal/psl-parser`)**: `AttributeSpecContext` (`{ symbols, model, controlMutationDefaults }`) and `FieldAttributeSpecContext` (adds required `field`) are the framework-owned context every spec factory takes. `assembleAttributeSpecs` merges family built-ins with target-contributed descriptor specs into `AssembledAttributeSpecs` — **plain frozen data, no interface or accessor methods**. Interpreters never consume this view: each family keeps total, `InferAttr`-typed access through its own registered `const` namespace; the assembled records serve consumers that genuinely face unknown names (LSP enumeration, upcoming unknown-attribute diagnostics). The one `blindCast` in `assemble.ts` is the project's single documented narrow restoring the erased factory types. - **ADR 236 descriptor migration**: `AuthoringModelAttributeDescriptor.spec` is re-contracted from "spec value" to "spec factory over the uniform ctx". Postgres `@@rls` supplies a typed factory const; the SQL interpreter's contributed-attribute loop invokes the factory with a ctx built from facts already at the site (symbol table, declaring `ModelSymbol`, default-function registry) — the existing narrow was reshaped in place, and a new test pins the ctx threading by identity (it fails if the registry slot is wired to anything but the composed stack's registry). ADR 236's text now describes the factory shape. - **LSP-consumability proof**: two test-only proofs, split by a real layering constraint (Domain 1 may not name Domain 3). `packages/1-framework/3-tooling/language-server/test/attribute-spec-consumability.test.ts` proves the plumbing with a synthetic target pack registered at a nested path claiming `rls` — simultaneously proving enumeration must go through `assembleAttributeSpecs`, since namespace path segments are not attribute names. `test/integration/test/authoring/attribute-specs.lsp-consumability.test.ts` proves the real postgres `@@rls` descriptor reaches a resolved LSP project through `resolveConfigInputs` — it goes red if the postgres pack stops registering `@@rls`. Zero production changes in the language server. ## Why - **Factories, not spec values**: the attribute surface isn't fully static (SQL builds `@default` specs per field, Mongo builds index specs per model), so the uniform entry shape is `(ctx) => AttributeSpec` with static specs as nullary factories — one shape, no consumer branching (project design decision, ADR 231's dynamic-composition principle). - **Plain data over a registry service**: accessor methods overloaded on a string `level` add nothing — the level is statically known at every call site — and a generic `get(): F | undefined` would force `undefined` checks on interpreters whose key sets are total. Data view for unknown-name consumers, `const` namespaces for interpreters. - **`AttributeSpec<never>` as the erased factory return type**: `Out` is contravariant (via `refine`), so `AttributeSpec<unknown>` rejects every real spec; `never` follows the codebase's own precedent (`AuthoringModelAttributeDescriptor<Out = never>`). Caught by compiler probe before implementation. - **Emitted contracts are untouched**: `pnpm fixtures:check` is byte-clean — this is authoring-time machinery only. Slice workspace (spec, plan, design decisions): `projects/attribute-registry/slices/registry-core/`. Refs: TML-3227 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for registering and consuming contributed model- and field-level attribute specifications. * Attribute specifications can now be created with relevant schema context, including the declaring model or field. * Added support for resolving contributed attributes by their declared names across tooling and integrations. * **Bug Fixes** * Improved validation for malformed, duplicate, or unsafe attribute registrations. * Ensured assembled attribute specifications remain stable and protected from unintended modification. * **Documentation** * Updated architecture guidance with the new attribute specification contribution workflow. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 11 天前 | |
feat(orm): rename take/skip to limit/offset (#30112) ## Linked issue n/a — no Linear ticket. ## At a glance ```ts const page2 = await db.orm.User .orderBy((u) => u.id.asc()) .offset(10) .limit(10) .all(); ``` The same ORM query previously used `.skip(10).take(10)`. ## Decision This PR ships a breaking rename of ORM collection pagination from `.take(n)` / `.skip(n)` to `.limit(n)` / `.offset(n)` across root SQL collections, relation refinements, grouped SQL collections, and Mongo ORM collections. The old ORM names are removed, while Mongo's lower-level query builder continues to expose `.skip(n)` for the native `$skip` pipeline stage. ## Reviewer notes - The implementation is concentrated in the SQL, grouped SQL, and Mongo collection classes; most of the broad diff migrates repository call sites and documentation. - Pagination semantics are unchanged. The renamed methods write the same `limit` and `offset` collection state, which still lowers to SQL `LIMIT` / `OFFSET` and Mongo `$limit` / `$skip`. - Grouped SQL pagination still requires a prior non-empty `orderBy`; only the method names changed. - This is intentionally breaking and includes rc.6-to-rc.7 app and extension upgrade instructions. ## How it fits together 1. [SQL collections](packages/3-extensions/sql-orm-client/src/collection.ts) expose `limit` and `offset`, with `first()` using the renamed limiter internally. 2. [Grouped SQL collections](packages/3-extensions/sql-orm-client/src/grouped-collection.ts) carry the same vocabulary through post-group pagination while preserving their ordering gate and separate pre-group/post-group windows. 3. [Mongo ORM collections](packages/2-mongo-family/5-query-builders/orm/src/collection.ts) expose the shared ORM names while retaining native `$skip` / `$limit` lowering and updated mutation-windowing diagnostics. 4. Examples, reference material, scorecards, and [upgrade instructions](skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.6-to-8.0.0-rc.7/instructions.md) move with the API so consumers get one consistent migration path. ## Behavior changes & evidence - **SQL ORM callers now paginate with `.limit(n)` and `.offset(n)` across root collections, includes, combinators, and aggregate input windows.** The implementation lives in [collection.ts](packages/3-extensions/sql-orm-client/src/collection.ts) and [query-plan-select.ts](packages/3-extensions/sql-orm-client/src/query-plan-select.ts); [pagination.test.ts](test/integration/test/sql-orm-client/pagination.test.ts) verifies database results and [aggregate-pagination.test.ts](packages/3-extensions/sql-orm-client/test/aggregate-pagination.test.ts) verifies aggregate scoping. - **Grouped SQL ORM callers use the renamed methods without weakening deterministic ordering.** [grouped-collection.ts](packages/3-extensions/sql-orm-client/src/grouped-collection.ts) preserves the gate, while [grouped-collection.test.ts](packages/3-extensions/sql-orm-client/test/grouped-collection.test.ts) and [grouped-pagination-gate.test-d.ts](packages/3-extensions/sql-orm-client/test/grouped-pagination-gate.test-d.ts) cover runtime planning and type-level availability. - **Mongo ORM callers use `.limit(n)` and `.offset(n)`, while plans still contain `$limit` and `$skip`.** [collection.ts](packages/2-mongo-family/5-query-builders/orm/src/collection.ts) implements the rename; [collection.test.ts](packages/2-mongo-family/5-query-builders/orm/test/collection.test.ts) verifies immutable stage construction and diagnostics, and [orm.test.ts](test/integration/test/mongo/orm.test.ts) verifies the resulting subset against MongoDB. ## Compatibility / migration / risk This is a source-breaking API rename with no deprecated aliases. Consumers must translate ORM `.take(n)` to `.limit(n)` and ORM `.skip(n)` to `.offset(n)`, including calls inside relation refinements, combinator branches, and grouped SQL chains. Mongo query-builder `.skip(n)` calls must remain unchanged. Runtime pagination behavior, cursor semantics, ordering requirements, and generated query-plan shapes do not otherwise change. ## Testing performed - `pnpm --filter @internal/sql-orm-client typecheck` - `pnpm --filter @internal/sql-orm-client test` — 771 tests - `pnpm --filter @internal/mongo-orm typecheck` - `pnpm --filter @internal/mongo-orm test` — 231 tests - Integration package typecheck plus targeted SQL, SQLite, and Mongo integration coverage — 33 tests - E2E package typecheck plus targeted SQLite ORM coverage — 18 tests - Typechecks for affected examples - `pnpm lint:deps` - `pnpm lint:skills` - `pnpm check:upgrade-coverage` - `pnpm lint:rules:symlinks` - `git diff --check` ## Skill update Updated the Prisma 8 query guidance for SQL and Mongo, and added app and extension upgrade instructions for `8.0.0-rc.6` → `8.0.0-rc.7`. The upgrade guidance explicitly preserves Mongo query-builder `.skip(n)`. ## Alternatives considered - **Keep deprecated `.take()` / `.skip()` aliases:** not chosen because Prisma Next is pre-1.0 and repository policy favors updating consumers over carrying compatibility shims. - **Rename Mongo query-builder `.skip()` too:** not chosen because the lower-level builder deliberately names native Mongo pipeline stages; `$skip` remains the correct vocabulary there. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated. - [x] No Linear ticket exists; the title uses a concrete issue-free format. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Renamed ORM pagination methods from `take()` and `skip()` to `limit()` and `offset()` across SQL and Mongo collections. * Preserved existing pagination behavior, including relation refinement, grouped queries, aggregation, and cursor scenarios. * **Documentation** * Updated guides, examples, reference material, scorecards, and upgrade instructions with the new terminology. * Added migration guidance for upgrading to the latest release. * **Tests** * Updated coverage to validate `limit()` and `offset()` pagination across supported query scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 14 天前 | |
ci: shard package tests without weakening coverage gates (#30156) ## Linked issue n/a — infrastructure change without a Linear ticket. ## At a glance ```yaml # Package Tests (1/4 ... 4/4) - run: pnpm coverage:packages --reporter=blob --shard=${{ matrix.index }}/4 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # Coverage - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with: pattern: package-coverage-* merge-multiple: true - run: pnpm coverage:packages:merge - run: pnpm coverage:report ``` Package tests now execute on four runners, while a separate `Coverage` job evaluates thresholds once against the combined native Vitest report. `Test Examples` runs concurrently, and a lightweight final `Test` job preserves the required status name. ## Summary The package-test portion of `Test` was the remaining serial CI bottleneck. This change shards that work horizontally while keeping one authoritative coverage gate and the existing required `Test` status context. ## Decision This PR ships three connected CI changes: 1. Run package tests and V8 coverage across four native Vitest shards, each uploading one uniquely named blob artifact. 2. Download and require all four blob reports in a separate `Coverage` fan-in job, merge their coverage counters with Vitest, and only then apply the existing package-level thresholds and warning policy. 3. Run examples concurrently and preserve assertion failures, inert-diff behavior, and the required `Test` check name through a lightweight final gate. ## Reviewer notes - Shards use SHA-pinned `actions/upload-artifact`; `Coverage` uses SHA-pinned `actions/download-artifact` with `pattern: package-coverage-*` and `merge-multiple: true`. Both are GitHub-created actions in the `actions` organization, so the existing GitHub-actions category permits them without individual allow-list entries. - Uploads set `include-hidden-files: true` because Vitest writes blobs below `.vitest/blob`, and `if-no-files-found: error` prevents a shard from silently publishing nothing. - GitHub does not expose artifacts from an earlier workflow attempt to rerun jobs. Use **Re-run all jobs**, not **Re-run failed jobs**; a partial rerun fails safely when `Coverage` verifies the four expected files. - Coverage thresholds and file reporters are deliberately disabled only in partial shard processes. The merge process runs without the shard marker and therefore restores the complete policy. - The stable required status remains `Test`; the four `Package Tests (N/4)` jobs, `Coverage`, and `Test Examples` are implementation details behind its final result. - The hosted four-runner transport can only execute in GitHub Actions. A local two-shard smoke test proved Vitest's blob names, merged counters, and final-only 100% threshold behavior. ## How it fits together 1. [`vitest.config.ts`](vitest.config.ts) recognizes shard collection through `VITEST_COVERAGE_SHARD`, keeps the full include/exclude policy, and suppresses only partial-run thresholds and coverage output. 2. [`.github/workflows/ci.yml`](.github/workflows/ci.yml) runs `vitest --coverage --reporter=blob --shard=N/4` on four PostgreSQL-backed runners. Each shard still reports test failures, uploads exactly one hidden blob file, and explicitly propagates a failing outcome after the upload. 3. `Coverage` downloads all `package-coverage-*` artifacts into `.vitest/blob` and checks for `blob-1-4.json` through `blob-4-4.json` before doing any merge. 4. [`pnpm coverage:packages:merge`](package.json) invokes Vitest's native `--merge-reports` path, which combines Istanbul counters rather than averaging percentages and replays failed tests. 5. The existing [`pnpm coverage:report`](scripts/coverage-report.mjs) attributes merged source entries to packages and enforces their thresholds. `Test Examples` runs concurrently, while the final `Test` job fails if any package shard, coverage, example, or prerequisite job failed. ## Behavior changes & evidence - **Package tests execute across four CI runners instead of one.** The matrix and fan-in are in [`.github/workflows/ci.yml`](.github/workflows/ci.yml), with the expected orchestration locked by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **Coverage gates see the complete combined run.** Shard-aware configuration lives in [`vitest.config.ts`](vitest.config.ts), while the native merge command is declared in [`package.json`](package.json) and existing package aggregation remains in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs). - **Missing shards, assertion failures, and partial reruns cannot silently pass.** Unique artifact names, hidden-file uploads, all four required filenames, and the final failure fan-in are asserted by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **The CI contract is documented for future changes.** The rationale and operational flow are recorded in [`docs/oss/ci-pipeline.md`](docs/oss/ci-pipeline.md) and the package coverage guides. ## Testing performed - `pnpm build` — 85 tasks passed - `pnpm test:scripts` — 498 tests passed - `node --test scripts/coverage-config.test.mjs scripts/coverage-report.test.mjs` — 34 tests passed - `pnpm lint:workflows` - `pnpm exec biome check vitest.config.ts scripts/coverage-config.test.mjs package.json turbo.json` - `pnpm exec turbo run build --dry=json` - Parsed `.github/workflows/ci.yml` with the installed `yaml` package - `git diff --check` - Synthetic two-shard Vitest 5 smoke test — generated both expected blob files, merged both source maps, replayed both tests, and passed combined 100% thresholds ## Skill update n/a — internal CI orchestration only; no user-facing CLI, API, configuration, error, or terminology changes. ## Alternatives considered - **Use cache transport:** cache prefix matching restores only one matching entry rather than all shard outputs, which would require four explicit restores. Cache fallback also suggests cross-attempt reuse that GitHub's artifact model intentionally avoids. - **Merge raw JSON manually:** Vitest's blob merger already preserves test failures, project metadata, and Istanbul hit counters, avoiding a custom coverage-merging implementation. - **Apply thresholds in every shard:** each shard sees only partial execution, so this would create false failures and would not represent repository coverage. - **Keep the single runner and increase workers:** package coverage is already worker-capped to protect PGlite/PostgreSQL stability; horizontal runners improve wall time without oversubscribing one machine. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — n/a, this infrastructure change has no Linear ticket and follows the repository's conventional-title precedent. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Package tests now run across four parallel CI shards. * Added coverage report merging for sharded test runs. * Coverage thresholds are applied after all shard results are combined. * Example tests now run as a dedicated CI check. * **Documentation** * Updated testing and CI guides with the new sharded coverage workflow and command. * **Chores** * Excluded Vitest cache files from version control. * Improved CI checks and diagnostics for incomplete or failed test shards. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 11 天前 | |
docs(skills): fix claims-vs-reality drift from the skills audit (TML-3223) (#30088) ## Linked issue Refs TML-3223 part 2 — the skills audit's docs findings. ## Summary Three auditors swept the 18 skills beside `record-upgrade-instructions` and found 40 claims that no longer match the tree. This PR fixes the documentation half: paths that resolve nowhere, examples that outlived the code they cite, and instructions with no runnable form. The corrections are mechanical and wide but shallow — each replaces a claim with what the tree, the scripts, or the PR template actually do: - **Dead references.** The visitor example pointed at a file that dispatches through polymorphic hooks now; it names the live Mongo DDL command set instead, across the three files that set really occupies. `create-pr` sent readers to `.agents/skills/drive-pr-walkthrough/SKILL.md`, which is installed from prisma/ignite and absent here — it now names the skill and says what to do when it is not installed. - **Phantom path segments.** Release-notes recipe URLs carried `skills/upgrade/…` and `skills/extension-author/…`; neither exists, so every migration link 404'd. Fixed in the skill and in `docs/releases/README.md`, along with the `prisma/prisma-next` → `prisma/prisma` slug. - **A template that grew a section.** `contrib-pr` and `create-pr` both enumerate the PR template's headers, and neither mentioned `## Skill update` — whose checkbox their own instructions then tell you to tick. - **Instructions with no runnable form.** Reacting 👍/👎 on a thread and detecting pending reviews each got the exact `gh api graphql` call. - **Smaller corrections.** Two agent files named models the harness cannot resolve; a documented table promised a Linear column its renderer does not emit; the release skill's PR title contradicted its own frontmatter; the biome rename step is now conditional on files that no longer exist. Two findings are held for an operator ruling and are **not** in this PR: `contrib-pr`'s conventional-commit-versus-`TML-NNNN` title-policy collision (the repo's own surfaces disagree), and renaming `skills-contrib/record-gotcha/` to match its installed plural name. `record-gotcha`'s broken bootstrap link and MCP plugin naming are fixed here. ## Testing performed `pnpm lint:skills` (green), `pnpm rules:sync` (no-op). ## Skill update This PR is entirely skill maintenance — it corrects 13 skill documents plus `docs/releases/README.md`. ## Notes for the reviewer Wide but shallow by design: 15 files, ~66 lines changed, no behavior. The script-side findings ship separately in the companion PR so this one stays reviewable as prose. https://claude.ai/code/session_01NnNjsNcPMtbJZhnZz5Zzbe <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated release-note guidance for migration links, transition labels, prerelease versions, and fallback examples. * Clarified AST, architecture, package export, Biome, and release-process instructions. * Refined contribution and pull request guidance, including templates and branch handling. * Improved review workflow guidance for pending reviews, reactions, action scaffolding, and output conventions. * Corrected integration references, repository links, skill paths, and checkout requirements. * Added guidance for documenting breaking changes when migration recipes are unavailable. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 8 天前 | |
#30153: Export reusable where filter types (#30158) ## Linked issue Closes #30153 ## At a glance SQL builder: ```ts import type { WhereFilter } from '@prisma/orm-postgres/builder/types'; import type { Contract } from '../src/prisma/contract'; import { db } from '../src/prisma/db'; const users = db.sql.public.user.select('id', 'email', 'createdAt'); function userById(id: string): WhereFilter<Contract, 'public', 'user'> { return (fields, operators) => operators.eq(fields.id, id); } users.where(userById('00000000-0000-0000-0000-000000000001')); ``` SQL ORM, with shorthand and predicate forms side by side: ```ts import type { RelationPredicate, ShorthandWhereFilter } from '@prisma/orm-postgres/orm-client'; import { createOrmClient } from '../src/orm-client/client'; import type { Contract } from '../src/prisma/contract'; function userById(id: string): ShorthandWhereFilter<Contract, 'public', 'User'> { return { id }; } function userByIdPredicate(id: string): RelationPredicate<Contract, 'public', 'User'> { return (user) => user.id.eq(id); } const db = createOrmClient(null as never); const userId = '00000000-0000-0000-0000-000000000001'; db.User.where(userById(userId)); db.User.where(userByIdPredicate(userId)); ``` These real integration-test examples show the new SQL builder annotation and the namespace-qualified ORM annotations in use. In both lanes, field mistakes are reported inside the helper body while the returned filter passes directly to `.where()`. ## Decision This PR ships three connected pieces: 1. A public SQL builder `WhereFilter<Contract, Namespace, Table>` type exported from `@prisma/orm-postgres/builder/types`. 2. Namespace-precise SQL ORM standalone filters using the existing `ShorthandWhereFilter<Contract, Namespace, Model>` and `RelationPredicate<Contract, Namespace, Model>` names. 3. Compile-only integration coverage and RC upgrade instructions that prove and explain the public API through the PostgreSQL facade. ## Summary Extracting a SQL builder `where()` callback currently loses contextual typing unless users reconstruct internal signatures or cast the result. This change adds a supported public builder type for that pattern and makes the existing SQL ORM reusable filter types namespace-precise, keeping errors and autocomplete at the helper definition where they are actionable. ## Reviewer notes - The SQL ORM generic change is intentionally breaking: namespace is now required and appears before model. Existing annotations need the migration recorded in this PR. - Relation predicates carry the target namespace from `relation.to.namespace`; emitted branded namespace IDs are normalized back to concrete contract namespace keys. - Runtime query behavior and generated SQL are unchanged. The small `find-user-by-id` cleanup removes an unnecessary ID cast discovered while adding the public-facade integration type tests. ## How it fits together 1. [`WhereFilter`](packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts) binds the existing expression callback to the selected table's `DefaultScope` and contract query context, then [`exports/types.ts`](packages/2-sql/4-lanes/sql-builder/src/exports/types.ts) exposes only that consumer-facing type. 2. [`types.ts`](packages/3-extensions/sql-orm-client/src/types.ts) makes the domain namespace a required coordinate for ORM shorthand filters, predicates, and relation filter accessors, so fields and operations resolve against one exact model facet. 3. [`collection.ts`](packages/3-extensions/sql-orm-client/src/collection.ts) and [`model-accessor.ts`](packages/3-extensions/sql-orm-client/src/model-accessor.ts) carry that namespace through `.where()`, `.first()`, ordering, grouped collections, and nested relation accessors. 4. Public-facade type tests in the PostgreSQL demo exercise both authoring forms and pin negative diagnostics to nonexistent fields inside the helper bodies. 5. The app and extension upgrade transitions explain how to migrate existing ORM filter annotations. ## Behavior changes & evidence - **SQL builder filters can be named, parameterized, and reused with table-specific fields and operators.** The public surface is defined in [`table-proxy.ts`](packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts) and [`exports/types.ts`](packages/2-sql/4-lanes/sql-builder/src/exports/types.ts), with package and facade evidence in [`where-filter.types.test-d.ts`](packages/2-sql/4-lanes/sql-builder/test/types/where-filter.types.test-d.ts) and [`sql-builder-filter.types.test-d.ts`](examples/prisma-8-demo/test/sql-builder-filter.types.test-d.ts). - **SQL ORM shorthand and predicate helpers retain model-specific autocomplete and local diagnostics.** Namespace-aware definitions live in [`types.ts`](packages/3-extensions/sql-orm-client/src/types.ts) and flow through [`collection.ts`](packages/3-extensions/sql-orm-client/src/collection.ts) and [`model-accessor.ts`](packages/3-extensions/sql-orm-client/src/model-accessor.ts); [`user-filter.types.test-d.ts`](examples/prisma-8-demo/test/user-filter.types.test-d.ts) proves both forms through `@prisma/orm-postgres/orm-client`. - **Namespace collisions resolve to the correct model facet.** [`orm-namespace-unique-fields.types.test-d.ts`](packages/3-extensions/sql-orm-client/test/orm-namespace-unique-fields.types.test-d.ts) proves that `public.User` and `auth.User` expose different fields and that missing or unknown namespace coordinates fail at compile time. - **Existing ORM filter annotations receive an explicit migration path.** The app and extension transitions in [`8.0.0-rc.8-to-8.0.0-rc.9`](skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.8-to-8.0.0-rc.9/instructions.md) and its [`extension counterpart`](skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.8-to-8.0.0-rc.9/instructions.md) describe adding and reordering the namespace coordinate. ## Testing performed - `pnpm --filter @internal/sql-builder test` — 13 test files, 171 tests passed. - `pnpm --filter @internal/sql-orm-client test` — 70 test files, 772 tests passed, no type errors. - `pnpm --filter prisma-8-demo test` — 14 test files, 73 tests passed, including all 26 repository integration cases. - `pnpm --filter @internal/sql-builder typecheck` - `pnpm --filter @internal/sql-orm-client typecheck` - `pnpm --filter prisma-8-demo typecheck` - `pnpm lint:deps` - `pnpm lint:skills` - `pnpm check:upgrade-coverage` - `git diff --check` ## Skill update The public ORM type signature change is recorded for both application and extension consumers in the `8.0.0-rc.8` → `8.0.0-rc.9` upgrade instructions. `pnpm lint:skills` and `pnpm check:upgrade-coverage` pass. ## Alternatives considered - **Export the builder machinery directly.** Exposing `Scope`, `QueryContext`, `ExpressionBuilder`, and `FieldProxy` would let consumers reconstruct the callback type, but would make internal query representation part of the supported API. `WhereFilter` supplies the useful contract coordinate without that leakage. - **Add `PredicateFor` and a union-shaped `WhereInput`.** `WhereFilter` matches the method it targets, while the existing `ShorthandWhereFilter` and `RelationPredicate` names keep the ORM's object and callback authoring forms explicit instead of hiding them behind one broad union. - **Keep namespace optional or after model.** Optional namespace lookup becomes imprecise when model names collide. Requiring `<Contract, Namespace, Model>` matches the contract coordinate order and guarantees useful autocomplete. - **Document `Parameters<...>` or casts as the workaround.** Those approaches duplicate complexity at every helper and can move diagnostics to the eventual `.where()` call. A first-class exported type keeps the error at its source. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated. - [x] The PR title uses the linked GitHub issue prefix because this issue has no Linear ticket. - [x] The **Skill update** section above is filled in. ## Notes for the reviewer The main compatibility consideration is the intentionally required ORM namespace coordinate; matching app and extension upgrade instructions ship in this PR. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - SQL ORM filter and relation types now support namespace-qualified model references. - Added reusable, publicly available filter type support for SQL builder workflows. - Namespace-aware typing improves autocomplete and validation across filtering, sorting, and relation queries. - **Bug Fixes** - Invalid fields and unknown namespaces are now rejected more reliably during TypeScript checks. - **Documentation** - Added upgrade guidance for updating reusable ORM filter type parameters. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 11 天前 | |
fix(target-postgres): avoid uncast array_position for pg.enum ORDER BY (#30191) ## Summary `ORDER BY` on a column typed `pg.enum(...)` rendered as `array_position(ARRAY[...]::text[], "col")` with no cast on the column argument. Against a native Postgres enum column that is rejected outright: ``` 42883: function array_position(text[], "TicketStatus") does not exist ``` So ordering by any enum-restricted column failed at runtime on rc.8. `db.sql` failed identically — it is the SQL renderer, not the ORM surface, so dropping to the SQL builder was not a workaround. Fixes #30163 ## The fix Gate the `array_position` declaration-order rewrite off for native enums, rather than casting the column argument to `text`. A native Postgres enum already sorts by declaration order under a plain `ORDER BY` — Postgres orders enum values by `pg_enum.enumsortorder` — so the rewrite is redundant there. It exists for value-sets backed by `text`/`varchar` columns with a CHECK constraint, which would otherwise sort alphabetically. Those are unaffected: they carry `pg/text@1`, the gate is inert for them, and the existing declaration-order suite passes 7/7 unchanged. The alternative was casting the column inside `array_position`. That also works — it preserves declaration order, it does not sort alphabetically — but it keeps a per-row function call that defeats a plain index on the column, and it leaves the renderer unable to distinguish "needs sort-order emulation" from "the database already sorts this correctly". Gating also agrees with `renderWhere`, which renders comparisons on the raw column, so a keyset/cursor predicate already compares by enum ordering where `array_position` did not. ## Why it is safe Contract declaration order and `pg_enum.enumsortorder` are kept identical by the migration planner: it can only append a value (`ALTER TYPE … ADD VALUE`, no `BEFORE`/`AFTER`) and refuses any other member change — rename, removal, or reorder — via `nativeEnumMemberChangeRefusal`. If that refusal is ever relaxed to permit reordering, this gate has to be revisited. The gate keys on `codecId`, not `nativeType`. A hand-authored contract carrying a `pg/text@1` codec over a column whose adopted physical type happens to be a native enum would not be caught — reachable only by hand-adopting an existing enum type as text, not by anything `pg.enum(...)` authoring produces. ## Interaction with #30099 #30099 ("enum ORDER BY / DISTINCT ON loses declaration order behind a derived table") touches the same function. **This PR should land first** — it is ~10 lines against a hard runtime error on a published release, while #30099 is larger and still in review. #30099 deletes `TableSourceCoordinate` / `collectTableSources` and both resolver functions here, replacing them with `resolveColumnValueSetFromSource(source, column, contract)` returning `{ found, values }`. On rebase, drop both call sites of `sortsByDeclarationOrderNatively` and call it once instead, in that PR's `table-source` branch, immediately after `storageColumn` is resolved: ```ts if (sortsByDeclarationOrderNatively(storageColumn)) return { found: true, values: undefined }; ``` `found: true`, not `false` — the column exists, it is simply not rewritten, and the identifier resolver's ambiguity counter depends on that distinction. That single site also covers #30099's new derived-table recursion, which this PR's two call sites do not reach. Re-inserting the gate at the two old call sites instead would pass the tests here but leave a native-enum column behind a `distinct()`/`groupBy()` wrap as a new, untested 42883. ## Testing `test/integration/test/ports/prisma/functional/issues-30163-enum-order-by` — an ORM-level port test. The harness pushes the contract through the plan → apply path (no hand-written DDL), then seeds rows and queries through the public facade: ```ts await db.public.Ticket.orderBy([(t) => t.status.asc(), (t) => t.id.asc()]) .select('id', 'status') .all(); ``` Declaration order is `open, closed`, so alphabetical ordering is distinguishable from a correct sort. Ascending and descending are both asserted on the whole result shape. Against the renderer on `main` both cases fail with `42883`; with the fix both pass. The existing text-backed value-set suite (`order-by-enum.integration.test.ts`) passes 7/7 unchanged, and the postgres adapter suite is green at 866 passed / 3 expected-fail. ## Release note `docs/releases/v8.0.0-rc.9.md` does not exist yet; the entry follows once it does, matching the precedent set by #30099 for rc.5. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01UcqoY3CKfnubdZt5YQk2Rq <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Fixed PostgreSQL native enum sorting so ascending and descending order follow the enum’s declared value order. - Prevented runtime errors when ordering columns backed by native PostgreSQL enums. - Improved deterministic results when multiple records share the same enum value. - Corrected `distinctOn` behavior to return one record for each enum value. - Ensured native enum queries behave consistently across supported ordering scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> | 6 天前 | |
feat(scripts): add :agent variants for running tests (and other slow commands) (#832) ## At a glance ```bash $ pnpm test:packages:agent log: wip/test-packages.20260615-190441.32317.log $ grep -nE " FAIL |Test Files" wip/test-packages.20260615-190441.32317.log … ``` The `:agent` variant runs the canonical command, redirects its full output to a timestamped file under `wip/`, prints that path as its first line of output, and exits with the same status as the underlying command. The agent uses the exact path the script just announced. ## The decision Every slow verification command — `test:packages`, `test:integration`, `test:e2e`, `build`, `typecheck`, `lint`, `lint:deps`, `fixtures:check` — gets an `:agent` variant. Agents use the `:agent` form; canonical commands are unchanged for humans and CI. Each variant writes `wip/<name>.<YYYYMMDD-HHMMSS>.<pid>.log` and a sibling `.exit`, then prints the log path. Every run gets a unique filename so history is preserved automatically. `wip/.gitkeep` is committed; everything else under `wip/` is gitignored. A new always-apply rulecard, `.agents/rules/running-tests.mdc`, documents the workflow: 1. Run a test suite (use the `:agent` variant). 2. Run one package's tests (`pnpm --filter <pkg> test`). 3. Rerun a specific failing test (by file, or by test name with vitest `-t`). 4. Find specific failures in the captured output (grep the log path the `:agent` printed). ## Why this matters Sampled from one Drive session, ~90 min in a single subagent: - 4× `pnpm test:packages` (~150s each) chasing the same failure list - 4× `pnpm test:integration` for the same reason - 11× `pnpm fixtures:check` re-runs grepping different slices of the same output - 3× `pnpm turbo typecheck --force` in the same minute ~25 min of pure re-run waste in one subagent. The cause: piping `pnpm test:packages` to `tail`/`grep`/`head` discards the rest of the output and hides the exit code (those tools return 0). The next question about the failure forces a full re-run. A rulecard alone would tell agents "redirect to a file, then grep it" — standing guidance they have to remember and apply. The `:agent` scripts bake the pattern into the command. Affordance, not memory. ## What's in this PR - **8 new package.json scripts**, one per slow command. Each follows the same shell template: ``` ts=$(date +%Y%m%d-%H%M%S).$$; log=wip/<name>.$ts.log; echo "log: $log"; \ pnpm <name> > "$log" 2>&1; status=$?; \ echo $status > wip/<name>.$ts.exit; exit $status ``` - **`.agents/rules/running-tests.mdc`** (always-apply), symlinked into `.cursor/rules/` and `.claude/rules/` by the existing `pnpm rules:sync`. - **`wip/.gitkeep`** committed; `.gitignore` now reads `/wip/*` + `!/wip/.gitkeep`. - Rules-footprint thresholds bumped to fit the new always-apply rule. ## Alternatives considered - **A helper script (`scripts/agent-run.sh`).** Each `:agent` is one self-contained shell statement; no shared library to maintain. - **A skill** (`skills-contrib/running-tests/`). Skills are procedural workflows you *invoke*; "always run tests this way" is standing guidance, which is what `.agents/rules/*.mdc` is for. - **Stable symlinks** `wip/<name>.log` → latest run. Tried, removed. The script prints the exact log path, so the read path is unambiguous — no need for a "latest" abstraction. - **`mkdir -p wip` prefix in every script.** Replaced by committing `wip/.gitkeep` — the directory always exists, the scripts stay short. - **Overwriting a single log per command.** First iteration. Broke the "run full → fix → run full again, compare" workflow. Replaced by timestamped + PID-suffixed filenames; history is preserved automatically. - **A structured (`--reporter=json`) reporter on the first run.** Plausible but unnecessary — everything an agent does is programmatic; the agent reads the same human-readable log a human would, and `grep`/`tail` work fine against it. ## Verification - `pnpm lint:deps:agent` end-to-end: prints `log: wip/lint-deps.<ts>.<pid>.log`, writes the log + `.exit`, exits with the right status. - `pnpm lint:rules:footprint` — passes after threshold bumps. - `pnpm lint:rules:symlinks` — symlink trees consistent. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> | 2 个月前 | |
chore: enable CodeRabbit auto-review on PRs targeting non-default branches (#30024) ## Linked issue n/a — small change (repo tooling config). ## At a glance ```yaml reviews: path_filters: - "!projects/**" auto_review: base_branches: - ".*" ``` Before this change, `.coderabbit.yml` left `base_branches` at its default (empty), so CodeRabbit only reviewed PRs based on `main`. ## Decision Enable CodeRabbit auto-review for PRs targeting any base branch, not just the default one. Stacked PRs base each PR on the branch below it, so under the default config every PR in a stack except the bottom one gets no CodeRabbit review. Setting `reviews.auto_review.base_branches` to `".*"` (a regex matching all branches, per the [CodeRabbit schema](https://coderabbit.ai/integrations/schema.v2.json)) makes each stacked PR get an incremental review against its own base. ## Notes for the reviewer - CodeRabbit reads `.coderabbit.yml` from the head branch of each PR, so the setting takes effect for a given PR only once this change is present in that PR's branch (i.e. after this merges and stacks rebase onto `main`, or if a stack includes it). - Minor cost: when a lower PR in a stack merges and the PR above retargets `main`, CodeRabbit may post a fresh incremental review on the retargeted PR. ## Testing performed - Validated the key path and value against CodeRabbit's published config schema (`reviews.auto_review.base_branches`, array of regex strings, default `[]`). - No code paths touched; CI is unaffected. ## Skill update n/a — internal only (review-bot configuration, no user-facing surface). ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read CONTRIBUTING.md and the change is scoped to one logical concern. - [x] Tests are updated (n/a — config-only change with no testable behavioural delta in this repo). - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no Linear ticket exists for this repo-tooling tweak. - [x] The **Skill update** section above is filled in. https://claude.ai/code/session_01WxsDtFe21Td8TQWznuywoW <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Enabled automatic code reviews for changes targeting any base branch. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 25 天前 | |
refactor: rename migration contract artifacts to end-contract / start-contract Within a migration directory, rename the on-disk contract files and the planner-emitted scaffold import so authoring-surface vocabulary matches the semantics: `end-contract.{json,d.ts}` is the schema that must be true at the end of the migration, and `start-contract.{json,d.ts}` is the schema true at the start. Framework-level `from`/`to` tracking vocabulary (manifest fields, `Migration.describe()`, internal hashes) is unchanged — it names edges in the DAG, a distinct concern. Per ADR 199, `computeMigrationId` strips contract payloads before hashing, so this rename does not invalidate attestation on existing demo migrations. - DataTransformCall now emits `dataTransform(endContract, ...)` and declares a default import from `./end-contract.json`. - `migration plan` / `migration new` copy artifacts as `end-contract.{json,d.ts}` (and, when a prior migration exists, `start-contract.{json,d.ts}`). - Rename existing example migration artifacts and update the two hand-authored `migration.ts` files that import the contract. - Mark the new patterns `linguist-generated` in `.gitattributes`. - Update unit + e2e tests and the spec / pr-plan / review artifacts. Live source-package `src/prisma/contract.{json,d.ts}` is unchanged — it is the unqualified live contract, not a point-in-time snapshot. | 4 个月前 | |
ci: shard package tests without weakening coverage gates (#30156) ## Linked issue n/a — infrastructure change without a Linear ticket. ## At a glance ```yaml # Package Tests (1/4 ... 4/4) - run: pnpm coverage:packages --reporter=blob --shard=${{ matrix.index }}/4 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # Coverage - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with: pattern: package-coverage-* merge-multiple: true - run: pnpm coverage:packages:merge - run: pnpm coverage:report ``` Package tests now execute on four runners, while a separate `Coverage` job evaluates thresholds once against the combined native Vitest report. `Test Examples` runs concurrently, and a lightweight final `Test` job preserves the required status name. ## Summary The package-test portion of `Test` was the remaining serial CI bottleneck. This change shards that work horizontally while keeping one authoritative coverage gate and the existing required `Test` status context. ## Decision This PR ships three connected CI changes: 1. Run package tests and V8 coverage across four native Vitest shards, each uploading one uniquely named blob artifact. 2. Download and require all four blob reports in a separate `Coverage` fan-in job, merge their coverage counters with Vitest, and only then apply the existing package-level thresholds and warning policy. 3. Run examples concurrently and preserve assertion failures, inert-diff behavior, and the required `Test` check name through a lightweight final gate. ## Reviewer notes - Shards use SHA-pinned `actions/upload-artifact`; `Coverage` uses SHA-pinned `actions/download-artifact` with `pattern: package-coverage-*` and `merge-multiple: true`. Both are GitHub-created actions in the `actions` organization, so the existing GitHub-actions category permits them without individual allow-list entries. - Uploads set `include-hidden-files: true` because Vitest writes blobs below `.vitest/blob`, and `if-no-files-found: error` prevents a shard from silently publishing nothing. - GitHub does not expose artifacts from an earlier workflow attempt to rerun jobs. Use **Re-run all jobs**, not **Re-run failed jobs**; a partial rerun fails safely when `Coverage` verifies the four expected files. - Coverage thresholds and file reporters are deliberately disabled only in partial shard processes. The merge process runs without the shard marker and therefore restores the complete policy. - The stable required status remains `Test`; the four `Package Tests (N/4)` jobs, `Coverage`, and `Test Examples` are implementation details behind its final result. - The hosted four-runner transport can only execute in GitHub Actions. A local two-shard smoke test proved Vitest's blob names, merged counters, and final-only 100% threshold behavior. ## How it fits together 1. [`vitest.config.ts`](vitest.config.ts) recognizes shard collection through `VITEST_COVERAGE_SHARD`, keeps the full include/exclude policy, and suppresses only partial-run thresholds and coverage output. 2. [`.github/workflows/ci.yml`](.github/workflows/ci.yml) runs `vitest --coverage --reporter=blob --shard=N/4` on four PostgreSQL-backed runners. Each shard still reports test failures, uploads exactly one hidden blob file, and explicitly propagates a failing outcome after the upload. 3. `Coverage` downloads all `package-coverage-*` artifacts into `.vitest/blob` and checks for `blob-1-4.json` through `blob-4-4.json` before doing any merge. 4. [`pnpm coverage:packages:merge`](package.json) invokes Vitest's native `--merge-reports` path, which combines Istanbul counters rather than averaging percentages and replays failed tests. 5. The existing [`pnpm coverage:report`](scripts/coverage-report.mjs) attributes merged source entries to packages and enforces their thresholds. `Test Examples` runs concurrently, while the final `Test` job fails if any package shard, coverage, example, or prerequisite job failed. ## Behavior changes & evidence - **Package tests execute across four CI runners instead of one.** The matrix and fan-in are in [`.github/workflows/ci.yml`](.github/workflows/ci.yml), with the expected orchestration locked by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **Coverage gates see the complete combined run.** Shard-aware configuration lives in [`vitest.config.ts`](vitest.config.ts), while the native merge command is declared in [`package.json`](package.json) and existing package aggregation remains in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs). - **Missing shards, assertion failures, and partial reruns cannot silently pass.** Unique artifact names, hidden-file uploads, all four required filenames, and the final failure fan-in are asserted by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **The CI contract is documented for future changes.** The rationale and operational flow are recorded in [`docs/oss/ci-pipeline.md`](docs/oss/ci-pipeline.md) and the package coverage guides. ## Testing performed - `pnpm build` — 85 tasks passed - `pnpm test:scripts` — 498 tests passed - `node --test scripts/coverage-config.test.mjs scripts/coverage-report.test.mjs` — 34 tests passed - `pnpm lint:workflows` - `pnpm exec biome check vitest.config.ts scripts/coverage-config.test.mjs package.json turbo.json` - `pnpm exec turbo run build --dry=json` - Parsed `.github/workflows/ci.yml` with the installed `yaml` package - `git diff --check` - Synthetic two-shard Vitest 5 smoke test — generated both expected blob files, merged both source maps, replayed both tests, and passed combined 100% thresholds ## Skill update n/a — internal CI orchestration only; no user-facing CLI, API, configuration, error, or terminology changes. ## Alternatives considered - **Use cache transport:** cache prefix matching restores only one matching entry rather than all shard outputs, which would require four explicit restores. Cache fallback also suggests cross-attempt reuse that GitHub's artifact model intentionally avoids. - **Merge raw JSON manually:** Vitest's blob merger already preserves test failures, project metadata, and Istanbul hit counters, avoiding a custom coverage-merging implementation. - **Apply thresholds in every shard:** each shard sees only partial execution, so this would create false failures and would not represent repository coverage. - **Keep the single runner and increase workers:** package coverage is already worker-capped to protect PGlite/PostgreSQL stability; horizontal runners improve wall time without oversubscribing one machine. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — n/a, this infrastructure change has no Linear ticket and follows the repository's conventional-title precedent. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Package tests now run across four parallel CI shards. * Added coverage report merging for sharded test runs. * Coverage thresholds are applied after all shard results are combined. * Example tests now run as a dedicated CI check. * **Documentation** * Updated testing and CI guides with the new sharded coverage workflow and command. * **Chores** * Excluded Vitest cache files from version control. * Improved CI checks and diagnostics for incomplete or failed test shards. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 11 天前 | |
TML-2502: Add SupabaseRuntime and the supabase() façade (#792) Linear: [TML-2502](https://linear.app/prisma-company/issue/TML-2502) (ships TML-2878/2879/2880/2881). Design record: `projects/runtime-target-layer/specs/adr-runtime-target-layer.md`. ## What this is for The Supabase integration needs a database client where the person making the request decides which rows they can see. Supabase does this with Postgres Row-Level Security (RLS): you connect, tell Postgres which role you are (`anon`, `authenticated`, `service_role`) and who the user is (their JWT claims), and Postgres filters every query against the policies defined on each table. This PR builds that client — `SupabaseRuntime` and the `supabase()` factory — plus the runtime restructuring needed to support it. ```ts import { createDb } from "./prisma/db"; // the app surface, built on supabase() const db = await createDb(process.env.DATABASE_URL); const session = db.asUser(jwt); // this request is "user X" await session.orm.public.Profile.find({ ... }); // returns only the rows X may see await db.asServiceRole().orm.public.Profile.create({ ... }); // full access (bypasses RLS) db.asAnon(); // the public, unauthenticated role ``` ## How a role-bound session works `asUser(jwt)` verifies the JWT — rejecting expired or forged tokens before touching the database — and returns a `Db` bound to that role. When you run a query on it, the runtime: 1. checks out a connection from the pool; 2. sets the Postgres role and JWT claims on that connection (`SELECT set_config(role, authenticated, false)` and the same for `request.jwt.claims` — parameterized, so nothing from the JWT is ever interpolated into SQL); 3. runs your work — a single statement, an ORM operation with its nested reads/writes, or a transaction — on that same connection, so the role is in effect for all of it; 4. resets the connection (`RESET ALL`) before returning it to the pool, and destroys it if the reset fails, so one requests role can never leak to the next. The role is set on the connection itself, underneath the query layer, so application middleware cannot run a query that skips it. That is the guarantee RLS depends on. ## Runtime changes needed to support it `SupabaseRuntime` is a Postgres runtime with this session behaviour added, so it has to extend the Postgres runtime, which extends the SQL runtime. The SQL runtime wasnt built to be extended — it was a single internal class built by a `createRuntime` factory. This PR restructures it: - `SqlRuntime` becomes **`SqlRuntimeBase`**, an abstract base that targets extend. - Each target ships a concrete runtime — **`PostgresRuntimeImpl`**, **`SqliteRuntimeImpl`** — and **`SupabaseRuntimeImpl`** extends the Postgres one. App code depends on the interfaces (`PostgresRuntime`, `SqliteRuntime`, `SupabaseRuntime`), never the classes. - **`createRuntime` is removed**; you build a runtime through its target factory (`postgres()`, `sqlite()`, `supabase()`). These are breaking changes. The 0.13→0.14 upgrade instructions (in both the user and extension-author upgrade trees) tell consumers how to migrate. ## Tests `examples/supabase` exercises the whole thing end to end against a real RLS policy: through the example apps own `createDb()`, `asUser(jwt)` sees and updates only that users rows, `asAnon()` sees none, and `asServiceRole()` sees and creates everything — while a logging middleware confirms it never observes the role-setting SQL. Tests run real runtime objects over a fake driver (and real in-memory SQLite) rather than mocking our own classes. ## Alternatives considered Full record in the ADR. The short version: an earlier cut of this PR set the role as a step inside each `execute()` call rather than on the session. That left the ORM free to run its own statements on a different, unbound connection — an RLS hole. Binding the role to the connection the whole operation runs on is what closes it. ## Verification All gates green: `@prisma-next/sql-runtime` 278 tests · `extension-supabase` 46+ · `postgres` 88 · `sqlite` 46 · `test:packages` 10256 · integration 1070 · e2e 109 · `examples` (skeleton + RLS acceptance; `prisma-next-cloudflare-worker` needs a local Hyperdrive env that CI provides) · `lint:deps`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Refactor** * Restructured SQL runtime architecture: `SqlRuntime` is now an abstract base class with concrete implementations (`PostgresRuntimeImpl`, `SqliteRuntimeImpl`). Removed `createRuntime` factory in favor of direct class instantiation. * **New Features** * Added Supabase runtime extension with role-based access control and JWT verification, enabling Row-Level Security (RLS) enforcement via `asUser()`, `asAnon()`, and `asServiceRole()`. * **Documentation** * Updated architecture documentation and upgrade guides to reflect runtime naming and construction changes. * **Tests** * Expanded test coverage for role binding, raw connection access patterns, and runtime lifecycle management. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> | 2 个月前 | |
chore: bump Node.js to 24.16.0 Update the .tool-versions pin (the single source mise reads in CI) from 24.13.0 to the latest v24 release, and refresh the environment line in the testing onboarding doc to match. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net> | 2 个月前 | |
TML-3199: Docs hygiene — dead links, stale API instructions, and the payload label (#30016) # Docs hygiene: dead links, stale API instructions, and the payload label Main-based cleanup (not part of the raw-SQL stack, though its items were surfaced by that campaign's reviews). ## What changed - **ADR-INDEX's dead ADR 035 link** — a pure capitalization mismatch (`Dual authoring conflict resolution` vs the file's `Dual Authoring Conflict Resolution`); corrected to the file's actual name. - **`error-reference.md`: "Meta:" → "Payload:" (260 entries) + one preamble sentence.** The old label was wrong for half the file: `structuredError()` writes `error.meta` but `runtimeError()` writes `error.details`, and a scripted classification showed a per-code label is ill-defined — of the codes classifiable at all, eight are raised through *both* constructors. The neutral label plus a preamble stating the rule (meta from structuredError, details from runtimeError, some codes both ways) is accurate today and stays accurate as raise sites move. No tooling reads the label (verified against `list-error-codes.mjs`). - **Stale `validateContract<Contract>(contractJson)` instruction removed from four surfaces** (`AGENTS.md` § Key Patterns, Testing Guide ×3, the Runtime subsystem doc, and the `typed-contract-in-tests` rulecard) — no such export exists, and the stale pattern had already generated a false review finding. Replacements verified against current code: the client factory hydrates (`postgres<Contract>({ contractJson, url })`), and tests use `validateSqlContractFully<Contract>(contractJson)` (the idiom with 174 current usages). The `validateContract` in `family-instance-domain-actions` is deliberately untouched — that one is the real ADR 204 control-plane primitive, a different thing sharing the name. - **ADR 012's refs clause** now states ADR 205's own conclusion: the unindexed-predicate lint and refs-based budget heuristic ran off the removed sidecar and no longer run for any plan. (The previous wording invited a hunt for a `meta.refs` field that no longer exists.) - **One ticketed item needed nothing**: the four "dead" source links in the Runtime & Middleware doc were already fixed upstream — verified resolving, left alone. ## Known merge note This PR and the raw-SQL stack (#29997) both edit the tail of the same ADR 012 update note, for different reasons. The conflict is one line but **semantic**: whichever lands second must carry both intents (the stack scopes the wire-level-rows claim as historical; this states the refs heuristics gone). Taking either side wholesale silently drops the other. Out of scope, ticketed: 68 further dead links across `docs/` + the missing link checker, two orphaned error-reference entries the one-directional checker cannot see, and ADR 205's own upstream ambiguity (all on TML-3211). Refs: TML-3199 https://claude.ai/code/session_01NnNjsNcPMtbJZhnZz5Zzbe <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated contract hydration and validation guidance to reflect the current workflow. * Refreshed testing and runtime examples for standalone contract usage. * Corrected architecture decision record titles, links, and descriptions of removed raw-plan metadata. * Clarified that contract data can be passed directly through runtime setup. * **Tests** * Updated typed contract fixture guidance to use full SQL contract validation for parsed contract data. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 8 天前 | |
ci: combine package tests and coverage (#30082) ## Linked issue n/a — this infrastructure migration has no Linear ticket. ## At a glance ```json "coverage:packages": "turbo run build --filter='!./examples/**' --filter='!./test/**' && vitest run --coverage", "coverage:report": "node scripts/coverage-report.mjs" ``` One root Vitest invocation now runs package tests and collects coverage, replacing the duplicated package-test and coverage CI jobs. ## Decision This PR ships three related changes: 1. Package tests and package coverage run together in one root Vitest multi-project invocation on Vitest `5.0.0-rc.2`. 2. Each package owns its complete coverage policy in an adjacent `coverage.config.json`, while root composition and post-processing preserve package thresholds and time-limited warning-only exceptions. 3. The obsolete, type-test-only SQL lane query-builder package and its public facade export are removed instead of retaining a permanently unmeasurable 95% runtime-coverage policy. ## Reviewer notes - The broad config diff is mostly moving existing coverage include/exclude/threshold blocks from `vitest.config.ts` into adjacent JSON policies and removing now-redundant package coverage scripts. - Vitest 5 removes `describe.sequential`; affected suites now use `{ concurrent: false }`. Compile-only `.test-d.ts` suites also declare compile-time test cases so Vitest 5 recognizes them. - `examples/prisma-8-cloudflare-worker` intentionally remains on Vitest 4 because `@cloudflare/vitest-pool-workers@0.20.3` requires Vitest 4 peers. - Eight existing package coverage deficits remain visible as active, non-blocking warning-only entries. Expired warnings and ordinary threshold failures still block CI. ## How it fits together 1. `scripts/coverage-config.js` discovers and validates package policies deterministically, rebases package globs to the repository root, and composes process-wide V8 collection settings. 2. The root `vitest.config.ts` references every package project and applies the composed coverage settings to a single test process. 3. `scripts/coverage-report.mjs` reads the root `coverage/coverage-final.json`, attributes files to their owning package, calculates all four metrics, and enforces each package's policy and warning expiry. 4. `.github/workflows/ci.yml` runs `pnpm coverage:packages` in the test job, reports package coverage even when collection finds a test failure, and removes the standalone coverage job. Test failures remain blocking. 5. Vitest 5 compatibility updates keep type tests, sequential suites, and CLI module mocks deterministic under the new runner behavior. ## Behavior changes & evidence - **Package tests execute once in CI while still producing coverage.** The combined command and workflow live in [`package.json`](package.json) and [`.github/workflows/ci.yml`](.github/workflows/ci.yml); [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs) guards the single-run workflow shape. - **Coverage ownership remains package-local and threshold enforcement remains package-aware.** Composition is implemented in [`scripts/coverage-config.js`](scripts/coverage-config.js), reporting in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs), and exercised by [`scripts/coverage-report.test.mjs`](scripts/coverage-report.test.mjs). - **Vitest 5 runs the workspace without the previous V8 merge bottleneck.** The workspace pins are in [`package.json`](package.json) and [`pnpm-lock.yaml`](pnpm-lock.yaml); representative compatibility fixes are covered by [`packages/1-framework/3-tooling/cli/test/migration-cli.test.ts`](packages/1-framework/3-tooling/cli/test/migration-cli.test.ts) and the migrated type-test suites. - **The obsolete SQL lane query-builder is no longer published.** Its package is removed, along with the facade dependency/export in [`packages/9-public/@prisma/orm-family-sql/package.json`](packages/9-public/@prisma/orm-family-sql/package.json) and publish-surface mapping in [`packages/0-shared/publish-surface/src/shells.ts`](packages/0-shared/publish-surface/src/shells.ts). ## Compatibility / migration / risk This is a pre-1.0 breaking cleanup: `@internal/sql-lane-query-builder` and `@prisma/orm-family-sql/lane-query-builder` are removed. Repository references and generated facade wiring were removed together, and the public SQL family shell rebuilds without them. Coverage semantics remain package-specific; only orchestration and report aggregation change. ## Testing performed - `CI=true TEST_TIMEOUT_MULTIPLIER=2 pnpm coverage:packages` — 1,155 files passed; 15,311 tests passed, 3 expected failures, no type errors - `pnpm coverage:report` — 69 package policies, 0 blocking failures, 8 active warnings, 0 expired warnings - `pnpm test:scripts` — 476 tests passed - `pnpm lint:deps` - `pnpm lint:manifests` - `pnpm build --filter=@prisma/orm-family-sql...` - Publish-surface tests and typecheck — 56 tests passed - Focused package tests/typechecks for CLI, Mongo runtime, SQL ORM client, SQLite codec testkit, integration tests, examples, and shell tarballs - `pnpm install --frozen-lockfile --ignore-scripts` - Targeted Biome checks and `git diff --check` ## Skill update n/a — the removed prototype query-builder export was not referenced by any user-facing skill; its package, public README, architecture docs, and publish surface were updated directly. ## Alternatives considered - **Keep Vitest 4 and optimize around it:** the single V8 run remained CPU-bound for more than 37 minutes because the relevant V8 merge optimization is only available in Vitest 5; the Vitest 4 backport was not merged. - **Switch to Istanbul coverage:** benchmarking was slower and introduced CLI language-server instrumentation timeouts, so V8 remains the provider. - **Run packages sequentially:** this preserves policy isolation but repeats runner startup and cannot eliminate duplicate test execution in CI; root collection plus package-aware post-processing keeps policy ownership without that cost. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no Linear ticket exists, so this uses the conventional commit title required by `CONTRIBUTING.md`. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Breaking Changes** - Removed the SQL lane query-builder package and its public package export. - Updated SQL documentation and package entrypoint references. - **Testing & Quality** - Centralized package coverage reporting with package-specific thresholds, exclusions, and warning policies. - Improved coverage validation, threshold reporting, and CI integration. - Updated serialized integration-test execution for compatibility with the current test runner. - **Documentation** - Expanded testing guidance for package coverage workflows and CI behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 18 天前 | |
Bump to version 8.0.0-rc.8: the engine peer moves to @prisma/cli-engine@0.3.0 (#30137) ## Release: 8.0.0-rc.7 → 8.0.0-rc.8 This is the routine release PR per [docs/oss/versioning.md](https://github.com/prisma/prisma/blob/main/docs/oss/versioning.md). It bumps every workspace package to 8.0.0-rc.8 and moves every `@prisma/cli-engine` pin from 0.2.3 to 0.3.0. The engine change: `@prisma/cli-engine@0.3.0` declares `@prisma/management-api-sdk` as a peer dependency (`^1.55.0`) instead of a regular dependency ([prisma/prisma-cli#236](https://github.com/prisma/prisma-cli/pull/236)). The `prisma` CLI shell supplies the SDK at runtime. In this repo pnpm resolves the peer to 1.61.0 in the lockfile. Review surface: [docs/releases/v8.0.0-rc.8.md](https://github.com/prisma/prisma/blob/release/8.0.0-rc.8/docs/releases/v8.0.0-rc.8.md) is the release notes file that becomes the GitHub Release body. The matching `CHANGELOG.md` entry and the `8.0.0-rc.7-to-8.0.0-rc.8` upgrade recipes are included. **Merging this PR ships the release**: the push to `main` carries the bumped root `version`, the `Publish to npm` workflow detects the change and publishes 8.0.0-rc.8 under `latest`, creates a pre-release GitHub Release from the notes file, then publishes `8.0.0-rc.8-dev.1` under `dev`. Local verification: `check:release-notes` (PR mode), `check:upgrade-coverage`, and `test:scripts` pass; the CLI tooling package's typecheck and its 1436 tests pass against the new engine. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added migration-model guidance and an upgrade recipe for Prisma 8.0.0-rc.8. * Added safeguards for planning migrations against existing migrations on empty databases. * **Bug Fixes** * Improved migration planning and corrected structured error links, Windows file URIs, and development release tags. * **Documentation** * Updated Prisma 8 release and upgrade guidance, including CLI tooling requirements. * **Chores** * Published the 8.0.0-rc.8 release across packages and examples. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 13 天前 | |
chore: Link AGENT.md to CLAUDE.md | 6 个月前 | |
feat(oss-setup): add SECURITY.md, CODEOWNERS, and CoC reporting channel Establishes the safety/disclosure surface area required to accept external contributions: - SECURITY.md documents GitHub Private Vulnerability Reporting as the primary channel (security@prisma.io as fallback), commits to a 5-business-day acknowledgement SLA, declares scope (every published @prisma-next/* package), and is explicit that pre-1.0 only the latest minor receives security fixes. - .github/CODEOWNERS routes every PR to @prisma/ORM-TS-Maintain. A flat single-rule layout is intentional: until the maintainer group is large enough to warrant subsystem routing, per-directory rules drift faster than they help. Branch protection (admin-side, not in this commit) is the gate that turns this from advisory to required. - CODE_OF_CONDUCT.md previously routed reports only to Discord. The Reporting an Issue section now names conduct@prisma.io as the primary channel with Discord as a fallback for cases where email is uncomfortable (e.g. report concerns a maintainer). The rest of the Contributor Covenant text is unchanged. The corresponding GitHub admin actions (enable PVR, require CODEOWNER review on main, provision conduct@prisma.io if not already in place) are tracked separately in plan.md M2 and need to land before this PR merges. Refs TML-2439. | 3 个月前 | |
feat: an application depends on one Prisma package (ADR 242) (#29864) ## What changes for someone using Prisma Today, an application that talks to Postgres installs a long list of our packages: ```jsonc { "dependencies": { "@prisma-next/postgres": "...", "@prisma-next/sql-runtime": "...", "@prisma-next/sql-orm-client": "...", "@prisma-next/target-postgres": "...", "@prisma-next/adapter-postgres": "...", "@prisma-next/sql-contract": "..." // ...a dozen more } } ``` After this PR, it installs one: ```jsonc { "dependencies": { "@prisma/orm-postgres": "0.16.0" } } ``` Everything else arrives as that package's own dependencies. Three of our example apps are converted in this PR to prove it — one per database — and each has exactly one Prisma package in its `dependencies`. This implements [ADR 242](https://github.com/prisma/prisma/pull/29852), which is already merged. ## What gets published 17 packages, all under the `@prisma` scope: - **3 database packages** — `@prisma/orm-postgres`, `orm-sqlite`, `orm-mongo`. An application installs exactly one. We call these *facades*: each is a small package that wires its database together and re-exports everything an application needs. - **6 extension packs** — PostGIS, pgvector, ParadeDB, Supabase, arktype-json, middleware-cache. Optional, installed alongside a database package. - **7 platform packages** — the framework, the toolchain, one per database family, one per database target. Applications never install these directly; they arrive as dependencies. Extension authors do install them. - **the `prisma` command**, as a bin-only package. Every other workspace package — around 50 of them — stops being published. They still exist in the repo as the unit we organise code in; they just stop having a life on the registry. **This PR does not make that switch yet.** It builds and proves the new surface while leaving today's publish list exactly as it is. Flipping it is a separate change. ## The problem this design has to avoid A published package can't depend on packages that won't exist on the registry. So each published package *contains a compiled copy* of the internal packages it covers. That creates a trap. If one application ends up with the same code twice — once inside a published package, once as its own package — then classes, registries, and anything compared by reference exist twice too. An `instanceof` check quietly returns false. Nothing crashes, nothing fails to compile, and both copies behave identically in isolation. You find out much later, somewhere unrelated. So the rule the whole design follows is: **every piece of internal code is published from exactly one package.** Concretely, that means: - Each published package is built in one pass, so code shared between its own entry points exists once. Verified from the build's source maps: no module appears in more than one chunk, in any published package. - When one published package needs code from another, it imports it as a real dependency rather than compiling in a second copy. - A facade re-exports from the platform packages; it never carries its own copy. `@prisma/orm-postgres/orm-client` and `@prisma/orm-family-sql/orm-client` are two names for the same object, and there's a test that asserts exactly that from installed tarballs. - One table in `packages/0-shared/publish-surface` maps every internal package to where it's published. The build, the code generator, and the lint checks all read it, so there's one answer to "where does this live" rather than three that can drift. ## Generated code follows the application Prisma writes imports into your project — contract types and migration files. Those imports have to name packages your project actually depends on, or they won't resolve. So the generator now reads the `package.json` next to the config it's generating for. A project that depends on `@prisma/orm-postgres` gets imports from that package. A project on today's names keeps today's names. Nothing to configure, because the manifest already says which it is. Contract hashes are unaffected, and that isn't an assumption — hashes are computed from a structure that import text never enters, and there's a test asserting the hash is identical across naming schemes *while* the emitted imports demonstrably differ. ## What stops the trap coming back Two checks, because the failure is silent and won't show up in a test suite: - Every example app and test project must use one naming scheme, not a mix. `lint-single-import-root` scans them and fails the build if any project imports from both, since that's the situation that loads code twice. - `lint-consumer-internal-imports` counts how many internal-package imports remain in those projects and compares against a committed number. It fails if the number goes up (someone added one) and also if it goes down without the number being updated (so improvements get locked in). Target is zero. The build itself also refuses to proceed if the published-package map would put one module in two places, or if a published package's `package.json` no longer matches what its code actually needs. ## Reading this PR It's large — 257 files — because it's a migration. The commits are grouped and meant to be read in order: 1. **Platform packages** — the build mechanism, and the seven platform packages it produces. 2. **Database packages, extension packs, the `prisma` command** — completes the set of 17. 3. **Generated imports become configurable** — one place decides which names get written, with today's names still the default. 4. **Database-family symmetry, publishing the map, the identity checks.** 5. **One package per application** — the three converted examples, the re-exports they proved necessary, and the counting check. 6. **Migration files follow the project too.** One thing worth knowing while reading: re-exporting a package republishes all of its sub-paths, not just the one that was needed. This PR adds 115 published sub-paths across the three database packages. Two candidates were dropped for exactly that reason — see below. ## Alternatives considered **Let an application install platform packages alongside its facade.** Nothing would need re-exporting and the facades would stay thinner. Rejected: an application would again juggle several Prisma dependencies whose correct combination it maintains by hand, and getting it wrong — upgrading one and not the other — produces the silent two-copies failure above. Re-exporting costs a generated line and nothing at runtime. **Re-export everything an application might plausibly want.** Rejected in review: because re-exporting brings a package's entire sub-path surface, generosity is expensive and hard to undo. Migration tooling (54 sub-paths) was dropped because its only users are extension packs, which install platform packages anyway; the SQL driver re-export was dropped because nothing imported it at all. What remains is what a converted example actually needed. **Flip the publish list in this same PR.** Rejected: it would mix "does the new surface work" with "is it safe to stop publishing 50 packages" in one review. The switch is mechanical once this lands, and gets its own change. ## Verification `build`, `typecheck` (156 tasks), `test:packages` (1077 files / 14087 tests), `test:e2e`, `lint`, `lint:deps`, `lint:docs`, `lint:manifests`, `check:publish-deps`, `check:clean-tree`, `lint:casts` and `lint:throws` (no new instances), `test:scripts`, coverage, the tarball-install suites, and regenerating every committed artifact leaves the tree unchanged. Known-unstable and unrelated to this change: the `relation-mode-gh-*` port suites (TML-3140), and several test timeouts that are too tight under load. ## Follow-ups TML-3124 switch the publish list · TML-3127 build cache can validate a stale published package on CI · TML-3140 unstable port suites · TML-3141 a test-helper sub-path reaches a package that is never published. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added consolidated public ORM packages for PostgreSQL, MongoDB, SQLite, framework tooling, database targets, and extensions. - Generated contracts, migrations, and scaffolds now adapt imports to the consuming project’s package surface. - Added facade-provided `prisma-next` CLI access and consolidated migration entrypoints. - **Documentation** - Updated installation, package naming, public entrypoint, and migration scaffolding guidance. - **Tests** - Added coverage for package installation, exports, CLI behavior, module identity, and import compatibility. - **Chores** - Added checks preventing incompatible internal and public package imports. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 1 个月前 | |
chore: add LICENSE | 6 个月前 | |
One config and one command language for the ORM: prisma.config.ts, driven by the unified CLI (#30058) Every surface in this repo now agrees on one config file and one command language. A freshly scaffolded project looks like this: ```ts // prisma.config.ts — the only config file the ORM reads, shared with the unified Prisma CLI import 'dotenv/config'; import { defineConfig } from '@prisma/cli-engine'; import { defineConfig as ormConfig } from '@prisma/orm-postgres/config'; export default defineConfig({ orm: ormConfig({ contract: './src/prisma/contract.prisma', db: { connection: process.env['DATABASE_URL']! }, }), }); ``` and is driven like this: ``` prisma-cli orm init # scaffold (init sits under `orm`; compute owns top-level init) prisma-cli contract emit # every other ORM command is top-level prisma-cli db init prisma-cli migration plan --name first prisma-cli migrate prisma-cli db verify ``` **The decision: the transition period is over.** Until now the loaders still accepted the retired `prisma-next.config.ts` filename and the old un-nested config shape (with deprecation warnings), and this repo still built its own `prisma-next` binary whose command tree didn't match the CLI users actually install. This PR deletes all of it. A config in the old spelling now fails loudly, and the workspace binary is a faithful stand-in for the real host — same command paths, same loader semantics. ## Why now, and what it flushed out The soft fallbacks weren't just clutter — they were hiding bugs. Because the workspace bin loaded config its own way and mounted commands at its own paths, the 22 ORM commands had never once run the way `@prisma/cli` actually runs them. Making the workspace bin mount the family exactly like the shipped host immediately surfaced three real defects, all fixed here: 1. **Mounted commands couldn't construct.** The family's retired-invocation redirects pointed at command paths that only existed in the old standalone tree, so the engine rejected the whole CLI at build time. 2. **Relative config paths crashed every path-consuming command.** The engine's loader hands commands the config exactly as authored, so under the real host `contract.output` arrived as `./src/prisma/contract.json` and `contract emit` died inside `createRequire`. This is the failure Shane hit with `bunx prisma@next orm init` — init succeeds, then the very next command falls over. The ORM command boundary (`defineOrmCommand`) now finalizes contract and migration paths idempotently, so both hosts hand handlers the same absolute paths. 3. **`init` installed a broken toolchain.** It added `@prisma/cli-engine` untagged, which resolves npm's lagging `latest` (0.0.9) instead of the version `@prisma/cli` actually runs against. It now reads the exact engine version from the installed CLI's own manifest. An end-to-end QA run (empty directory → init → emit → `db init` → typed queries → schema change → plan → migrate → verify, against the *published* `@prisma/cli@8.0.0-rc.5` with this branch's toolchain) is green top to bottom. That run also caught a fourth defect: the TypeScript starter contract triggered `PN_CONTRACT_TYPED_FALLBACK_AVAILABLE` warnings on its own first emit; it now uses the typed model-token form the warning recommends. ## What changed, piece by piece - **Loaders**: `@internal/config-loader` and the bin's loader read only `prisma.config.ts` with the `$prismaConfig` envelope. The deprecated-filename discovery, the flat-shape acceptance, the `CONFIG.DEPRECATED_*` codes, and the old Symbol-based format marker are deleted. The telemetry enricher's matching fallbacks too. - **Binary**: the workspace bin is named `prisma` and mounts the family the way the host does — commands top-level, `init` under `orm`. Examples, e2e journeys, and harnesses drive it through those paths, which is what finally puts the mounted tree under test. - **Strings**: every user-facing command string (errors, docs, READMEs, scaffolded scripts, next-step hints) reads `prisma <command>` / `prisma orm init`. - **Ratchet**: `scripts/lint-legacy-name.mjs` now *forbids* `prisma-next.config.ts` repo-wide, so the retired spelling can't creep back. Deliberate residuals stay allowed: `prisma-next.md`, `// use prisma-next` schema headers, `prisma-next-*` skill names, the per-user telemetry dir. - **Upgrade path**: `upgrades/8.0.0-rc.3-to-8.0.0-rc.4/` entries in both skill clusters walk consumers through the rename, the envelope rewrite, the dependency change, and the command grammar. Verified: 15,296 package tests, 2,075 integration tests, fixtures regenerated and stable, all repo lints green. One honest gap: the upgrade-instruction entries were authored from the applied diff, not validated by the full revert-and-replay flow. ## Alternatives considered - **Keep the deprecation fallbacks another release.** Rejected: every surface that still worked under the old spelling postponed exactly the couplings this change needed to surface, and the fallback paths themselves had no coverage in the real host. - **Mount the workspace commands under `prisma orm <command>`.** This PR briefly did that — the config *section* is named `orm`, so it looked right. The published rc.5 host proved otherwise: its tree is top-level with only `init` nested. The workspace bin now copies the host instead of guessing. - **Fix path finalization in the engine instead.** The cleaner home would be the engine handing validators the config file's path, but that's a prisma-cli-repo API change. The command-boundary fix works with today's engine, is idempotent, and stays correct if the engine later finalizes upstream. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 21 天前 | |
TML-3165: count/sum/avg return JS numbers, with lossless variants beside them (#29930) ## Linked issue Refs [TML-3165](https://linear.app/prisma-company/issue/TML-3165/native-number-aggregate-defaults-countcountbigint-sumsumbigint) — slice 08, the last of the [Codec JSON projections](https://linear.app/prisma-company/project/codec-json-projections-a10fba2e9cd5) project. **Stacked on [#29922](https://github.com/prisma/prisma/pull/29922)** (TML-3164) and targets that branch until it merges, then advances to `main`. Prerequisites: slice 06 ([#29902](https://github.com/prisma/prisma/pull/29902), merged) supplied the codecs this names; slice 07 (#29922) made the operation set a contribution, so this PR adds three operations without touching a line of client or lane code. Follow-ups filed: [TML-3187](https://linear.app/prisma-company/issue/TML-3187/schema-written-literals-are-not-application-values-give-them-their-own). ## At a glance ```ts const stats = await db.orm.Order.aggregate((agg) => ({ orders: agg.count(), // number — was bigint cents: agg.sum('amountCents'), // number — was bigint; throws past 2^53 mean: agg.avg('amountCents'), // number — was a decimal string exactOrders: agg.countBigInt(), // bigint exactCents: agg.sumBigInt('amountCents'), // bigint, exact past 2^63 exactMean: agg.avgDecimal('amountCents'), // decimal string })); ``` Since the aggregate hard cut, `count()` returned a `bigint` — which `JSON.stringify` refuses — and integer `avg()` returned a decimal string. Correct, but not what a JS developer expects. This restores the expected types without restoring the silent corruption they used to hide: where a value cannot fit, the codec throws. ## Decision The aggregate vocabulary splits in two, by policy: 1. **Bare operations answer in JS-native types.** `count()` and `sum()` over integers return `number` through a guarded codec that raises `RUNTIME.DECODE_FAILED` past the safe-integer range rather than handing back a rounded value. `avg()` returns `number` through `float8` — a mean is a fraction already, so there is nothing to guard. 2. **Suffixed operations are lossless.** `countBigInt()`, `sumBigInt()`, `avgDecimal()`. Offered over every integer input, including those whose bare form is already lossless, so the escape hatch is uniform rather than something you learn column by column. 3. **Bare operations over Float and Decimal columns stay in the column's own family** — those users already chose their representation. `min`/`max` return the column's own type and are untouched. 4. **A non-nullable aggregate descriptor now declares `emptyResultJson`** — the empty-input answer in its result codec's canonical JSON. It belongs to the operation, not the codec: `count`'s identity is zero, but a `every()` would answer `true`. Classic Prisma is the prior art — `BigInt` columns are `bigint` there while `count` is a `number` — but where it casts down in the engine, this throws at the boundary. ## Reviewer notes - **Read the two matrices first** (`packages/3-targets/3-targets/{postgres,sqlite}/src/core/aggregates.ts`). They are the entire judgment; everything else derives. Every row was probed against a live database before it was authored. - **Three facts are load-bearing, and each has a test that fails if it is quietly substituted.** `sumBigInt` over `int8` reads PostgreSQL's `numeric` through `pg/unboundedint@1` rather than casting to `int8` — the cast is exercised *as a negative in the same test*, raising `bigint out of range` over the data the shipped row reads exactly. `avg` casts the **result**, not the input, pinned on a dataset where the two genuinely differ (`4503599627370497` vs `...496`). `emptyResultJson` cannot be omitted: the type is a discriminated union, so a `nullable: false` descriptor without it does not compile. - **Three substrate repairs the matrices exposed rather than caused**, each a stale assumption that held only while every non-nullable aggregate decoded through a bigint codec. SQLite's number-flavoured codec needed a JSON projection (its transport cast renders a JSON *string* inside an envelope, so every SQLite include aggregate was failing to decode — and no test covered that path, which is why CI stayed green over it). The integer codecs now distinguish a wrong JS type from a wrong magnitude — which uncovered that the bigint codecs had been *silently accepting* JS numbers, so `1.5` could reach an integer column as `'1.5'`. And the DDL renderers compose `encode(decodeJson(stored))` instead of feeding canonical JSON to `encode`, which also fixed a `timestamptz` default handed an ISO string where the codec declares a `Date`. - **One acknowledged stopgap.** Tightening those guards broke `BigInt @default(0)`: a schema language writes no `bigint`, so PSL literals arrive as JSON numbers, and emission of the Supabase extension's contract stopped. `encodeJson` now accepts a safe-integer `number` (guarded — integral, in-range) while the wire `encode` stays strict. The proper seam is TML-3187. Reviewed as safe: `encodeJson` is unreachable from the runtime parameter path. - **~100 regenerated `contract.d.ts` files.** All movement is inside `export type AggregateTypes` — verified mechanically: `git diff -U0` yields 247 hunks under that one header and no other. No `contract.json` and no migration fixture moved. - A local fresh-eyes review ran before this PR; its three MUST-FIX findings were all in the documentation, not the code, and are fixed here. ## How it fits together 1. **The PostgreSQL matrix** — the policy, probed and authored, with database-backed conformance evidence. 2. **The SQLite matrix** — the same policy in SQLite's terms; `avgDecimal` is not contributed (no decimal), and its absence is asserted as unavailability rather than a runtime error. 3. **The substrate repairs** — the three above, at their source. 4. **The sweep** — contracts regenerated, every moved expectation classified as *mechanical form change* or *corrected defect*; five tests re-expressed against `sumBigInt` because they asserted that a wide bare `sum` survives, which the policy now forbids. 5. **The record** — upgrade instructions in both clusters, a 13-pattern docs sweep, ADR 020 and the descriptor guide. ## Behavior changes & evidence - **`count()`/`sum()` return `number` and throw past 2^53** rather than rounding — on the wire path *and* the include/JSON path, where the value is emitted as a JSON number, rounded by `JSON.parse`, and refused by the post-parse guard. Evidence: [integer-representation.test.ts](test/integration/test/sql-orm-client/integer-representation.test.ts), both cases with whole error shapes. - **`sumBigInt()` is exact past 2^63** on PostgreSQL. Evidence: [aggregate-defaults.integration.test.ts](packages/3-targets/6-adapters/postgres-codec-testkit/test/aggregate-defaults.integration.test.ts) — `18446744073709551614n`, beside the `int8` cast raising. - **`avg()` returns a `number`, `avgDecimal()` a decimal string**, pinned on a non-terminating mean so the two visibly differ. - **SQLite include aggregates decode again**, as JSON numbers. Evidence: [sqlite-include-canonical-json.test.ts](test/integration/test/sql-orm-client/sqlite-include-canonical-json.test.ts) — the first committed coverage of that path. ## Testing performed - `pnpm build`, `pnpm typecheck:all` (92 tasks), `pnpm lint:deps` (no violations), `pnpm lint` — green - `pnpm test:packages` — 1113 files, 14,776 tests green; `pnpm test:e2e` — 113 green - Full unsharded `pnpm test:integration` — green apart from two host-environment files reproduced independently of this branch (`init-journey.e2e`, host pnpm; `issues-28192-pg-historical-dates`, host timezone) - `pnpm fixtures:check` green with movement fully attributable; `check:upgrade-coverage`, `check:error-reference` (274 codes), `lint:docs`, `lint:skills` green; cast ratchet `delta=-5` ## Skill update Both upgrade clusters carry entries for `8.0.0-rc.1-to-8.0.0-rc.2`: the app cluster covers the result-type flips and the integer columns now refusing a wrong JS type; the extension cluster adds the `emptyResultJson` obligation and the `encode`/`encodeJson` split. Entries slice 07 wrote in the same transition were corrected where this slice falsified them. The shipped query guide's aggregate result-type table is rewritten. ## Follow-ups - [TML-3187](https://linear.app/prisma-company/issue/TML-3187/schema-written-literals-are-not-application-values-give-them-their-own) — schema-written literals need their own codec seam, distinct from `encodeJson`'s application-value contract; includes the related gap that the TS authoring surface cannot express a `bigint` default at all. ## Alternatives considered - **Casting `sumBigInt` to `int8`** — simpler, and wrong: it reintroduces a 64-bit overflow this design does not have, and would resurrect the need for a `sumDecimal` the design discarded. - **Casting `avg`'s input rather than its result** — changes accumulation semantics; the result cast computes the exact mean once and rounds once. - **A codec-side "canonical zero" for the empty-input answer** — it can only serve operations whose identity is zero, and asks every codec in the stack a question most cannot answer. - **Skipping the transport lowering inside a JSON envelope** (the obvious fix for the SQLite defect) — wrong: the lossless variants' lowerings are semantic, not transport, so skipping them computes nothing. - **Withholding the lossless variant where the bare form is already lossless** — logically tidy, but it makes the escape hatch conditional on knowledge a caller shouldn't need. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). The DCO status check will block merge if any commit is missing a `Signed-off-by:` trailer. - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated (or `n/a` if the change is doc-only / refactor with no behavioural delta). - [x] The PR title is in `TML-NNNN: <sentence-case title>` form (Linear ticket prefix + concise title naming the concrete deliverable). See `.claude/skills/create-pr/SKILL.md` for the full convention. - [x] The **Skill update** section above is filled in (or stated `n/a — internal only`). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Aggregate `count`, integer `sum`, and integer `avg` results now use JavaScript numbers by default. * Added lossless `countBigInt`, `sumBigInt`, and PostgreSQL `avgDecimal` options for exact results. * Aggregate results now follow the selected database target and field representation. * **Bug Fixes** * Unsafe numeric results beyond JavaScript’s safe-integer range now raise a runtime error. * Non-nullable aggregates correctly return their defined empty-result values. * **Documentation** * Updated aggregate behavior, codec guidance, error references, and upgrade instructions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net> | 29 天前 | |
migration plan refuses to silently plan from an empty database when migrations exist (#30122) Here is the failure this PR removes. A project has one migration on disk and asks for the next one: ```console $ prisma migration plan --name add-user-role ✔ Planned migration 20260824_add-user-role from: (baseline) to: f3a9c1… ``` That plan looks fine and exits 0 — but `from: (baseline)` means "starting from an empty database", so the package contains `CREATE TABLE` for the entire schema. Applying it to any real database fails on the first statement. Nothing warned. A field tester shipped exactly this; our own gotchas file documents the trap. **The decision: `migration plan` now refuses to plan from an empty database when migrations already exist, unless you explicitly ask for that.** Silence becomes a structured error: ```console $ prisma migration plan --name add-user-role ✖ MIGRATION.PLAN_ORIGIN_UNKNOWN: no starting point for this plan. → Record where your database is: prisma migration ref set db 8c2fe0… → Or name the starting contract: prisma migration plan --from 8c2fe0… → Or plan from an empty database on purpose: --from @empty ``` To see why the silence existed, follow how `plan` picks its starting point. It is deliberately offline — it never connects to a database — so it reads the starting contract from `--from` if given, otherwise from the `db` ref: a small committed file recording which contract your dev database has been brought to. `db init` and `db update` maintain that file as you iterate. But a project that never runs those commands (the Composer-style workflow, where deploys apply migrations) never has a `db` ref — and plan's last resort was "assume empty database", silently, even with history sitting on disk. First plans are the legitimate case for that assumption, so the refusal only fires when migrations already exist on disk; a first plan in a fresh project still proceeds silently, including the auto-baseline (the from-empty starter migration `plan` writes alongside your first real change). The refusal immediately proved its worth inside this repo: three e2e journeys were walking the exact trap — planning follow-up migrations with no ref and no `--from`, producing from-empty migrations while their comments claimed incremental ones. The divergence journey was not testing divergence at all. They now chain with `--from` and prove what they claim. Also here: the gotchas entry is marked resolved; the roadmap's stale-ref data-loss item is narrowed, not closed (a ref that exists but points at the wrong contract is a different case this refusal does not cover); and a docs sweep against ADR 218 fixed six statements teaching the old behavior — four claiming `db update` advances no ref, two describing `migration plan` as advancing refs (that is TML-2560, still unimplemented; they now say so). Verification: 1436 CLI tests, 124 journey tests, typecheck, lint, and the error-reference check all green; every behavior above exercised against the built binary. **Alternatives considered.** *Warn instead of refuse*: a warning above a plausible-looking plan gets scrolled past — and the roadmap already classifies the sibling case as data-loss risk; an error with exits gets acted on, by agents especially. *Advance the ref at plan time so the situation can't arise*: rejected — the `db` ref means "where the dev database has been brought", and moving it for an unapplied plan corrupts that meaning; plan-time advancement as an explicit flag is tracked separately (TML-2560). *Teach the workflow and change nothing*: the prisma-8 skill rewrite does teach it (sibling PR), but the error channel reaches whoever the skill doesn't. Coordination: the sibling skill PR truthfully states today's lack of this refusal (one doc line, one journey-test assertion). Whichever PR merges second updates those two spots. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added `@empty` as the supported origin for planning migrations from an empty database. * `db update` on the default development database now advances the `db` reference automatically. * **Bug Fixes** * Migration planning now reports `MIGRATION.PLAN_ORIGIN_UNKNOWN` when migrations exist without a known origin. * Prevented `@empty` from being used as a migration destination. * **Documentation** * Updated CLI help, error guidance, roadmap, and migration documentation to reflect the new behavior and terminology. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 14 天前 | |
feat: an application depends on one Prisma package (ADR 242) (#29864) ## What changes for someone using Prisma Today, an application that talks to Postgres installs a long list of our packages: ```jsonc { "dependencies": { "@prisma-next/postgres": "...", "@prisma-next/sql-runtime": "...", "@prisma-next/sql-orm-client": "...", "@prisma-next/target-postgres": "...", "@prisma-next/adapter-postgres": "...", "@prisma-next/sql-contract": "..." // ...a dozen more } } ``` After this PR, it installs one: ```jsonc { "dependencies": { "@prisma/orm-postgres": "0.16.0" } } ``` Everything else arrives as that package's own dependencies. Three of our example apps are converted in this PR to prove it — one per database — and each has exactly one Prisma package in its `dependencies`. This implements [ADR 242](https://github.com/prisma/prisma/pull/29852), which is already merged. ## What gets published 17 packages, all under the `@prisma` scope: - **3 database packages** — `@prisma/orm-postgres`, `orm-sqlite`, `orm-mongo`. An application installs exactly one. We call these *facades*: each is a small package that wires its database together and re-exports everything an application needs. - **6 extension packs** — PostGIS, pgvector, ParadeDB, Supabase, arktype-json, middleware-cache. Optional, installed alongside a database package. - **7 platform packages** — the framework, the toolchain, one per database family, one per database target. Applications never install these directly; they arrive as dependencies. Extension authors do install them. - **the `prisma` command**, as a bin-only package. Every other workspace package — around 50 of them — stops being published. They still exist in the repo as the unit we organise code in; they just stop having a life on the registry. **This PR does not make that switch yet.** It builds and proves the new surface while leaving today's publish list exactly as it is. Flipping it is a separate change. ## The problem this design has to avoid A published package can't depend on packages that won't exist on the registry. So each published package *contains a compiled copy* of the internal packages it covers. That creates a trap. If one application ends up with the same code twice — once inside a published package, once as its own package — then classes, registries, and anything compared by reference exist twice too. An `instanceof` check quietly returns false. Nothing crashes, nothing fails to compile, and both copies behave identically in isolation. You find out much later, somewhere unrelated. So the rule the whole design follows is: **every piece of internal code is published from exactly one package.** Concretely, that means: - Each published package is built in one pass, so code shared between its own entry points exists once. Verified from the build's source maps: no module appears in more than one chunk, in any published package. - When one published package needs code from another, it imports it as a real dependency rather than compiling in a second copy. - A facade re-exports from the platform packages; it never carries its own copy. `@prisma/orm-postgres/orm-client` and `@prisma/orm-family-sql/orm-client` are two names for the same object, and there's a test that asserts exactly that from installed tarballs. - One table in `packages/0-shared/publish-surface` maps every internal package to where it's published. The build, the code generator, and the lint checks all read it, so there's one answer to "where does this live" rather than three that can drift. ## Generated code follows the application Prisma writes imports into your project — contract types and migration files. Those imports have to name packages your project actually depends on, or they won't resolve. So the generator now reads the `package.json` next to the config it's generating for. A project that depends on `@prisma/orm-postgres` gets imports from that package. A project on today's names keeps today's names. Nothing to configure, because the manifest already says which it is. Contract hashes are unaffected, and that isn't an assumption — hashes are computed from a structure that import text never enters, and there's a test asserting the hash is identical across naming schemes *while* the emitted imports demonstrably differ. ## What stops the trap coming back Two checks, because the failure is silent and won't show up in a test suite: - Every example app and test project must use one naming scheme, not a mix. `lint-single-import-root` scans them and fails the build if any project imports from both, since that's the situation that loads code twice. - `lint-consumer-internal-imports` counts how many internal-package imports remain in those projects and compares against a committed number. It fails if the number goes up (someone added one) and also if it goes down without the number being updated (so improvements get locked in). Target is zero. The build itself also refuses to proceed if the published-package map would put one module in two places, or if a published package's `package.json` no longer matches what its code actually needs. ## Reading this PR It's large — 257 files — because it's a migration. The commits are grouped and meant to be read in order: 1. **Platform packages** — the build mechanism, and the seven platform packages it produces. 2. **Database packages, extension packs, the `prisma` command** — completes the set of 17. 3. **Generated imports become configurable** — one place decides which names get written, with today's names still the default. 4. **Database-family symmetry, publishing the map, the identity checks.** 5. **One package per application** — the three converted examples, the re-exports they proved necessary, and the counting check. 6. **Migration files follow the project too.** One thing worth knowing while reading: re-exporting a package republishes all of its sub-paths, not just the one that was needed. This PR adds 115 published sub-paths across the three database packages. Two candidates were dropped for exactly that reason — see below. ## Alternatives considered **Let an application install platform packages alongside its facade.** Nothing would need re-exporting and the facades would stay thinner. Rejected: an application would again juggle several Prisma dependencies whose correct combination it maintains by hand, and getting it wrong — upgrading one and not the other — produces the silent two-copies failure above. Re-exporting costs a generated line and nothing at runtime. **Re-export everything an application might plausibly want.** Rejected in review: because re-exporting brings a package's entire sub-path surface, generosity is expensive and hard to undo. Migration tooling (54 sub-paths) was dropped because its only users are extension packs, which install platform packages anyway; the SQL driver re-export was dropped because nothing imported it at all. What remains is what a converted example actually needed. **Flip the publish list in this same PR.** Rejected: it would mix "does the new surface work" with "is it safe to stop publishing 50 packages" in one review. The switch is mechanical once this lands, and gets its own change. ## Verification `build`, `typecheck` (156 tasks), `test:packages` (1077 files / 14087 tests), `test:e2e`, `lint`, `lint:deps`, `lint:docs`, `lint:manifests`, `check:publish-deps`, `check:clean-tree`, `lint:casts` and `lint:throws` (no new instances), `test:scripts`, coverage, the tarball-install suites, and regenerating every committed artifact leaves the tree unchanged. Known-unstable and unrelated to this change: the `relation-mode-gh-*` port suites (TML-3140), and several test timeouts that are too tight under load. ## Follow-ups TML-3124 switch the publish list · TML-3127 build cache can validate a stale published package on CI · TML-3140 unstable port suites · TML-3141 a test-helper sub-path reaches a package that is never published. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added consolidated public ORM packages for PostgreSQL, MongoDB, SQLite, framework tooling, database targets, and extensions. - Generated contracts, migrations, and scaffolds now adapt imports to the consuming project’s package surface. - Added facade-provided `prisma-next` CLI access and consolidated migration entrypoints. - **Documentation** - Updated installation, package naming, public entrypoint, and migration scaffolding guidance. - **Tests** - Added coverage for package installation, exports, CLI behavior, module identity, and import compatibility. - **Chores** - Added checks preventing incompatible internal and public package imports. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 1 个月前 | |
feat: target-declared aggregate codecs; count() returns bigint (TML-3064) (#29867) # Linked issue Refs [TML-3064](https://linear.app/prisma-company/issue/TML-3064/aggregate-codec-typing-and-extension-testkits) — the fifth and final slice of the [Codec JSON projections](https://linear.app/prisma-company/project/codec-json-projections-a10fba2e9cd5) project. Predecessors: #1023 (AST foundations), #1051 (codec descriptor protocols), #29844 (the lossless JSON hard cut). ## At a glance ```ts // test/integration/test/sql-builder/group-by.test.ts — the roadmap's witness, flipped: expect(alice!.cnt).toBe(2n); // was: expect(alice!.cnt).toBe('2') // test/integration/test/sql-orm-client/include-codec-canonical-json.test.ts: expect(total).toBe('9007199254740995'); // sum(int8) — the exact decimal, past 2^53 expect(peak).toBe(9007199254740993n); // max(int8) through an include's JSON envelope ``` Before this PR, aggregate values carried no codec: `count()` was typed `bigint` but returned whatever text the driver sent, and results were `Number()`-coerced — silently lossy past 2^53. ## Summary Aggregates were the last codec-blind read path after the lossless JSON hard cut. This PR gives them the same treatment columns received: targets declare what each aggregate returns, and everything downstream — emitted types, ORM planning, decoding, and the sql-builder lane — resolves through that one declaration. ## Decision 1. **`SqlAggregateDescriptor`**: a declarative mapping from `(operation, optional input codec)` to output codec + nullability + optional lowering, contributed beside `codecDescriptors`, validated at composition (never at query time), with exact-over-trait-over-input-agnostic precedence implemented once (`settleAggregateOverloads` in framework-components) and consumed by both the runtime registry and the emitter. 2. **Database-probed matrices** for PostgreSQL and SQLite, pinned two-sidedly by live conformance suites (a declared-but-wrong row fails one way; an unclaimed-but-supported pair fails the other). The targets genuinely diverge — PostgreSQL's integer `avg` is a `numeric` decimal string, SQLite's is a `real` number — so nothing is derived from a shared rule. 3. **`TypeMaps.aggregateTypes`**, emitted from the contributed descriptor set (deliberately not the target registry: the SQLite adapter contributes 9 of the target's 11 codecs, and emitting from the registry would advertise availability the runtime won't honour). 4. **The consumer cuts**: ORM planning stamps resolved output codecs (include aggregates become codec-projected JSON — no `native` aggregate entries remain), the `Number()`-coercion shims are deleted, decoding flows through the generic codec path, and the sql-builder lane's hardcoded `'pg/int8@1'` is retired with its static types now resolved from the emitted map. SQLite's bigint-output aggregates lower to `CAST(… AS TEXT)` so the driver can read them at all past 2^53. 5. **Public conformance testkits**: `@prisma-next/postgres-codec-testkit` and `@prisma-next/sqlite-codec-testkit` — dev-only, test-framework-independent packages extracted from the adapters' test-internal harnesses; pgvector and arktype-json consume them as packages instead of reaching across package boundaries with relative imports. 6. **The breaking-change record**: upgrade instructions for both audiences, a docs sweep for stale `number`-aggregate claims, and the codec authoring guide's new aggregate-descriptor section. ## Reviewer notes - **The three commits to spot-check**: `29d602143c` (the ORM cut — the largest), `8246165f97` / `51bbb2abb2` (the probed matrices — the doc blocks carry the probe findings and the unsupported lists). - **Two local gate reds at close, both ruled extrinsic** (full evidence in the review artifact's round notes): `test/cli-journeys` fails on `ERR_PNPM_IGNORED_BUILDS: esbuild@0.28.1` in the harness's temp-project installs — the esbuild version is identical on both sides of this diff (it came from #29812 on main) and this branch touches no build-approval config; and the adapter-postgres coverage run aborts on instrumentation-induced timeouts before computing numbers (the same suite passes 794/798 uninstrumented) — CI's Coverage job is the arbiter, and if its thresholds miss, the precedented remedy is a `warningOnly` entry in `coverage.config.json` for the tests-moved-to-break-a-cycle situation (the built-in conformance suites moved into the testkits because Turborepo's workspace graph cannot represent the adapter↔testkit dev-cycle). - **`sum`/`avg` outputs deliberately drop input type parameters** — a `numeric(10,3)` column sums to an unconstrained `numeric`; carrying the parameters into the result would overstate precision. - **HAVING operands stay `number`** on the result-typed surfaces — they are compared inside SQL against the aggregate the database computes and never cross a codec. The docs carve this out explicitly; a deliberate API-consistency decision is filed as a follow-up rather than flipped hastily. - **Project artifacts** under `projects/codec-json-projections/` (spec, plan, dispatch briefs, trace) ride this PR per the project convention; close-out removes the directory after the final retro. - **One test helper carries a typed workaround** for a real type-level inference gap (`IsToManyRelation` not recognising an in-file `.relations()` hasMany) — commented at both sites, follow-up drafted. ## How it fits together 1. **The protocol** (`6268028e13`, `24f1c819d1`): descriptor vocabulary split on the framework/SQL seam — the declarative half family-neutral (the emitter, which layering bars from the lanes, must read it), the lowering half in relational-core; contribution key beside `codecDescriptors`; composition-time validation with three documented error codes. 2. **The matrices** (`8246165f97`, `51bbb2abb2`): every built-in aggregate/input pair probed against a live database, declared or explicitly recorded unsupported. The probe earned its keep — `avg(float4)` widens to `float8` while `sum(float4)` does not; SQLite computes *something* for twelve pairs whose result class depends on the data, so they stay deliberately untyped. 3. **The input-agnostic match kind** (`6afc62e32f`): execution surfaced that `count(x)` matched nothing under the original three kinds; the spec was amended visibly and the fourth kind added — `count` declares one descriptor covering both forms. 4. **The emission** (`c137f6227e`, `4a26af3ea3`): `aggregateTypes` joins `TypeMaps`, pre-settled per contributed codec so type-level resolvers reproduce runtime precedence without re-deriving traits; 33 `contract.d.ts` fixtures regenerated, zero `contract.json` movement. 5. **The cuts** (`29d602143c`…`df63ce88f4`, `01f8c2d635`): ORM and lane resolve through the registry; coercion deleted; the lossless claim proven past 2^53 on both targets at both read paths, including the SQLite `CAST` lowering that makes the top-level read possible at all. 6. **The record** (`7811990a9c`…`8633f366fc`): upgrade instructions enumerated from the matrices, the docs sweep, the authoring guide's aggregate section, and the HAVING carve-out. ## Behavior changes & evidence - **`count()` returns `bigint`** on both targets, top-level and include; empty sets return `0n`. Implementation: `packages/3-extensions/sql-orm-client/src/aggregate-codecs.ts`, `query-plan-aggregate.ts`. Evidence: `test/integration/test/sql-orm-client/aggregate.test.ts`, `test/integration/test/sql-builder/group-by.test.ts`. - **Integer sums widen losslessly** (`pg/int8@1` → `bigint`; `sum(int8)`/integer `avg` → `pg/numeric@1` decimal strings; SQLite integer sums → `bigint`). Implementation: `packages/3-targets/3-targets/postgres/src/core/aggregates.ts`, `.../sqlite/src/core/aggregates.ts`. Evidence: the two testkit aggregate-conformance suites; `include-codec-canonical-json.test.ts` (values past 2^53). - **Include aggregates are codec-projected JSON** — no `native` aggregate entries remain. Implementation: `query-plan-select.ts`. Evidence: `packages/3-extensions/sql-orm-client/test/json-projection-emission.test.ts` (`expect(natives).toEqual([])`). - **SQLite bigint aggregates render `CAST(… AS TEXT)`** — the driver previously threw `RangeError` on any wide top-level aggregate. Implementation: `.../sqlite/src/core/aggregates.ts` (the protocol's first lowering hooks). Evidence: `sqlite-include-canonical-json.test.ts`, the sqlite testkit conformance suite. - **The conformance harnesses are published dev-only packages** consumed by adapters and extensions alike. Implementation: `packages/3-targets/6-adapters/{postgres,sqlite}-codec-testkit/`. Evidence: `pnpm lint:deps` (no production dependency), the extensions' migrated suites. ## Testing performed Per-dispatch gates across nine reviewed dispatches (two implementers, one persistent reviewer; 9 findings filed, 9 resolved), plus a full deferred-gate reckoning at close: adapter-postgres 794/798 (3 expected-fail, 1 skipped), pgvector 160/160, postgres testkit 134/134 (both live aggregate matrices), integration suites by directory — slice surfaces 463/464 (one 100ms timeout, green serially), ports 476 + 52 expected-fail, authoring/cross-package 108/108, mongo 148/148 — and the workspace confirmation: build 70/70, typecheck 146/146, `lint:deps` clean, `fixtures:check` no-op, `check:upgrade-coverage` green. The two extrinsic reds are described under Reviewer notes. ## Skill update `skills/prisma-next-queries` (per-target aggregate type table, HAVING carve-out, checklist) and `skills/upgrade/0.16-to-0.17` (two new entries: the aggregate break for users; the testkit migration + descriptor authoring for extension authors). `pnpm lint:skills` green. ## Follow-ups Three drafted tickets await Linear re-authorization (drafts in `plan.md § Open items`): the SQLite plain-column wide-bigint `RangeError` (independent of aggregates), the `IsToManyRelation` inference gap, and the HAVING typing asymmetry. The cli-journeys esbuild approval breakage is main's, from #29812. ## Alternatives considered - **Per-trait `count` descriptors or lane special-casing** instead of the input-agnostic kind — rejected: the first models count's result as input-dependent (false), the second puts operation knowledge in a generic planner. - **Emitting `aggregateTypes` from the target registry** — rejected: SQLite's adapter contributes a filtered codec set, and registry-derived emission would advertise availability the runtime won't honour. - **Driver-level `setReadBigInts`** instead of descriptor lowering — rejected: it changes the JS type of every integer column read; the lowering is scoped to the aggregates that need it. - **Trait fallbacks for `sum`/`avg`** — rejected: the probed populations disagree row by row; only `min`/`max` have probed-uniform trait populations. - **Keeping the conformance suites in the adapters** with a testkit devDependency — rejected by Turborepo itself: the workspace graph cannot represent the dev-cycle; the suites moved into the testkits, which also dogfoods the public API extension authors consume. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read CONTRIBUTING.md and the change is scoped to one logical concern. - [x] Tests are updated (extensively; nine dispatches of tests-first work). - [x] The PR title is in `TML-NNNN: <sentence-case title>` form. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Aggregate results now use database-accurate types across PostgreSQL and SQLite. * Counts and widened integer sums return `bigint`; averages may return decimal strings. * Aggregate nullability and supported operations are reflected in generated types. * Added target-aware handling for `count`, `sum`, `avg`, `min`, and `max`, including large values beyond JavaScript’s safe integer range. * Added aggregate codec conformance tooling and target-specific SQL result handling. * **Bug Fixes** * Empty counts return `0n`, while other empty aggregates remain `null`. * Unsupported or ambiguous combinations now produce structured errors. * SQLite preserves oversized integer aggregate values without numeric narrowing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net> | 1 个月前 | |
chore(deps-dev)(deps-dev): bump the dev-deps group across 1 directory with 10 updates (#30037) Bumps the dev-deps group with 10 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.5.7` | `2.5.8` | | [dependency-cruiser](https://github.com/sverweij/dependency-cruiser) | `18.1.0` | `18.1.1` | | [pkg-pr-new](https://github.com/stackblitz-labs/pkg.pr.new/tree/HEAD/packages/cli) | `0.0.86` | `0.0.87` | | [skills](https://github.com/vercel-labs/skills) | `1.5.21` | `1.5.22` | | [turbo](https://github.com/vercel/turborepo) | `2.10.8` | `2.10.9` | | [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) | `4.118.0` | `4.119.0` | | [@cloudflare/vitest-pool-workers](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/vitest-pool-workers) | `0.20.1` | `0.20.3` | | [@cloudflare/workers-types](https://github.com/cloudflare/workerd) | `5.20260714.1` | `5.20260804.1` | | [@prisma/compute-sdk](https://github.com/prisma/project-compute) | `0.38.0` | `0.39.0` | | [@prisma/management-api-sdk](https://github.com/prisma/pdp-control-plane/tree/HEAD/packages/management-api-sdk) | `1.53.0` | `1.56.0` | Updates `@biomejs/biome` from 2.5.7 to 2.5.8 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/biomejs/biome/releases">@biomejs/biome's releases</a>.</em></p> <blockquote> <h2>Biome CLI v2.5.8</h2> <h2>2.5.8</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/10710">#10710</a> <a href="https://github.com/biomejs/biome/commit/0a0fbc15d67c410c80dfae398903f845544fcd65"><code>0a0fbc1</code></a> Thanks <a href="https://github.com/dyc3"><code>@dyc3</code></a>! - Added a new nursery rule <a href="https://biomejs.dev/linter/rules/use-react-compiler/"><code>useReactCompiler</code></a>, which reports diagnostics from React Compiler lint mode.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11251">#11251</a> <a href="https://github.com/biomejs/biome/commit/ea9dd8a93e65f849840415e8e26cd668aa1af913"><code>ea9dd8a</code></a> Thanks <a href="https://github.com/dyc3"><code>@dyc3</code></a>! - Improved performance of <a href="https://biomejs.dev/linter/rules/no-import-cycles/"><code>noImportCycles</code></a>.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11247">#11247</a> <a href="https://github.com/biomejs/biome/commit/52b44d6795741d051bf703bd69c6cb447af8fd1d"><code>52b44d6</code></a> Thanks <a href="https://github.com/dyc3"><code>@dyc3</code></a>! - Added the nursery rule <a href="https://biomejs.dev/linter/rules/no-svelte-legacy-const/"><code>noSvelteLegacyConst</code></a>, which disallows legacy Svelte <code>{@const}</code> tags and recommends declaration tags with <code>$derived()</code>.</p> <p>Invalid:</p> <pre lang="svelte"><code>{#each boxes as box} {@const area = box.width * box.height} <p>{area}</p> {/each} </code></pre> <p>Valid:</p> <pre lang="svelte"><code>{#each boxes as box} {const area = $derived(box.width * box.height)} <p>{area}</p> {/each} </code></pre> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11252">#11252</a> <a href="https://github.com/biomejs/biome/commit/d5f570414fdcdddf62372e35c05f6dababad9287"><code>d5f5704</code></a> Thanks <a href="https://github.com/Turtle-Hwan"><code>@Turtle-Hwan</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11250">#11250</a>: <a href="https://biomejs.dev/linter/rules/use-await/"><code>useAwait</code></a> no longer reports async functions that contain an <code>await using</code> declaration.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11143">#11143</a> <a href="https://github.com/biomejs/biome/commit/6be7be1b147d7b4352ff5625a78bd54a48958950"><code>6be7be1</code></a> Thanks <a href="https://github.com/vznh"><code>@vznh</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11017">#11017</a>: <a href="https://biomejs.dev/linter/rules/no-useless-undefined/"><code>noUselessUndefined</code></a> no longer reports <code>return undefined</code> when the enclosing function has a return type annotation other than <code>undefined</code> or <code>void</code>.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11234">#11234</a> <a href="https://github.com/biomejs/biome/commit/caefe393c66340914c481f7ccfc82979cf76b61b"><code>caefe39</code></a> Thanks <a href="https://github.com/subotac"><code>@subotac</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11228">#11228</a>: CSS block comments between a declaration colon and value now preserve their source indentation.</p> <pre lang="diff"><code> :root { --font-stack: -/* comment */ + /* comment */ system-ui; } </code></pre> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11285">#11285</a> <a href="https://github.com/biomejs/biome/commit/bca1f73d939423056337bfd0a42cbdcb66bb1e3f"><code>bca1f73</code></a> Thanks <a href="https://github.com/denbezrukov"><code>@denbezrukov</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11280">#11280</a>: CSS formatting keeps comments inside functional pseudo-classes and pseudo-elements instead of moving them before the function name.</p> <pre lang="diff"><code>-:/* comment */ where(div) {} +:where(/* comment */ div) {} </code></pre> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md">@biomejs/biome's changelog</a>.</em></p> <blockquote> <h2>2.5.8</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/10710">#10710</a> <a href="https://github.com/biomejs/biome/commit/0a0fbc15d67c410c80dfae398903f845544fcd65"><code>0a0fbc1</code></a> Thanks <a href="https://github.com/dyc3"><code>@dyc3</code></a>! - Added a new nursery rule <a href="https://biomejs.dev/linter/rules/use-react-compiler/"><code>useReactCompiler</code></a>, which reports diagnostics from React Compiler lint mode.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11251">#11251</a> <a href="https://github.com/biomejs/biome/commit/ea9dd8a93e65f849840415e8e26cd668aa1af913"><code>ea9dd8a</code></a> Thanks <a href="https://github.com/dyc3"><code>@dyc3</code></a>! - Improved performance of <a href="https://biomejs.dev/linter/rules/no-import-cycles/"><code>noImportCycles</code></a>.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11247">#11247</a> <a href="https://github.com/biomejs/biome/commit/52b44d6795741d051bf703bd69c6cb447af8fd1d"><code>52b44d6</code></a> Thanks <a href="https://github.com/dyc3"><code>@dyc3</code></a>! - Added the nursery rule <a href="https://biomejs.dev/linter/rules/no-svelte-legacy-const/"><code>noSvelteLegacyConst</code></a>, which disallows legacy Svelte <code>{@const}</code> tags and recommends declaration tags with <code>$derived()</code>.</p> <p>Invalid:</p> <pre lang="svelte"><code>{#each boxes as box} {@const area = box.width * box.height} <p>{area}</p> {/each} </code></pre> <p>Valid:</p> <pre lang="svelte"><code>{#each boxes as box} {const area = $derived(box.width * box.height)} <p>{area}</p> {/each} </code></pre> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11252">#11252</a> <a href="https://github.com/biomejs/biome/commit/d5f570414fdcdddf62372e35c05f6dababad9287"><code>d5f5704</code></a> Thanks <a href="https://github.com/Turtle-Hwan"><code>@Turtle-Hwan</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11250">#11250</a>: <a href="https://biomejs.dev/linter/rules/use-await/"><code>useAwait</code></a> no longer reports async functions that contain an <code>await using</code> declaration.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11143">#11143</a> <a href="https://github.com/biomejs/biome/commit/6be7be1b147d7b4352ff5625a78bd54a48958950"><code>6be7be1</code></a> Thanks <a href="https://github.com/vznh"><code>@vznh</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11017">#11017</a>: <a href="https://biomejs.dev/linter/rules/no-useless-undefined/"><code>noUselessUndefined</code></a> no longer reports <code>return undefined</code> when the enclosing function has a return type annotation other than <code>undefined</code> or <code>void</code>.</p> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11234">#11234</a> <a href="https://github.com/biomejs/biome/commit/caefe393c66340914c481f7ccfc82979cf76b61b"><code>caefe39</code></a> Thanks <a href="https://github.com/subotac"><code>@subotac</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11228">#11228</a>: CSS block comments between a declaration colon and value now preserve their source indentation.</p> <pre lang="diff"><code> :root { --font-stack: -/* comment */ + /* comment */ system-ui; } </code></pre> </li> <li> <p><a href="https://redirect.github.com/biomejs/biome/pull/11285">#11285</a> <a href="https://github.com/biomejs/biome/commit/bca1f73d939423056337bfd0a42cbdcb66bb1e3f"><code>bca1f73</code></a> Thanks <a href="https://github.com/denbezrukov"><code>@denbezrukov</code></a>! - Fixed <a href="https://redirect.github.com/biomejs/biome/issues/11280">#11280</a>: CSS formatting keeps comments inside functional pseudo-classes and pseudo-elements instead of moving them before the function name.</p> <pre lang="diff"><code>-:/* comment */ where(div) {} +:where(/* comment */ div) {} </code></pre> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/biomejs/biome/commit/6b8f09c04394f2a9f72b89f9381724681169641a"><code>6b8f09c</code></a> ci: release (<a href="https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome/issues/11236">#11236</a>)</li> <li><a href="https://github.com/biomejs/biome/commit/23c0369c43b59284ca68c65883d6ede4228b6fb8"><code>23c0369</code></a> feat(lint): nursery noInvalidPropertyInitValue (<a href="https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome/issues/11187">#11187</a>)</li> <li><a href="https://github.com/biomejs/biome/commit/52b44d6795741d051bf703bd69c6cb447af8fd1d"><code>52b44d6</code></a> feat(lint/html): add <code>noSvelteLegacyConst</code> (<a href="https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome/issues/11247">#11247</a>)</li> <li><a href="https://github.com/biomejs/biome/commit/0a0fbc15d67c410c80dfae398903f845544fcd65"><code>0a0fbc1</code></a> feat(lint/js): add <code>useReactCompiler</code> (<a href="https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome/issues/10710">#10710</a>)</li> <li>See full diff in <a href="https://github.com/biomejs/biome/commits/@biomejs/biome@2.5.8/packages/@biomejs/biome">compare view</a></li> </ul> </details> <br /> Updates `dependency-cruiser` from 18.1.0 to 18.1.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/sverweij/dependency-cruiser/releases">dependency-cruiser's releases</a>.</em></p> <blockquote> <h2>v18.1.1</h2> <h2>👷 maintenance</h2> <ul> <li>1ee565bb/ 942cf969 build(npm): updates external dependencies</li> <li>f0061d15 fix: removes all unused catch parameters</li> <li>cbe062ae/ c0250f8d chore(tools): uses node permission model</li> <li>01c47439 fix(build): re-adds esbuild to the devDependencies</li> <li>e57d9fc2 chore: replaces eslint with oxlint (<a href="https://redirect.github.com/sverweij/dependency-cruiser/issues/1074">#1074</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/da355e4cc82383f7b9744e0beb2f64d3c20f2e25"><code>da355e4</code></a> 18.1.1</li> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/c0250f8dd06f622fba990fcd9b1d5da8c4bfaa1b"><code>c0250f8</code></a> chore(tools): makes the tools work again on node 22</li> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/942cf969aa6174f1a4bfa91542dc6da37e5cdbcd"><code>942cf96</code></a> build(npm): updates external dependencies</li> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/cbe062ae2b1994a7ce38bec9939562a33b193b84"><code>cbe062a</code></a> chore(tools): uses node permission model</li> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/01c474397603d0a3db8288793c6bf362c18c7784"><code>01c4743</code></a> fix(build): re-adds esbuild to the devDependencies</li> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/e57d9fc2f06a860eee3d7bf3667da05d52145a3e"><code>e57d9fc</code></a> chore: replaces eslint with oxlint (<a href="https://redirect.github.com/sverweij/dependency-cruiser/issues/1074">#1074</a>)</li> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/f0061d1545e2c16a8ee0212f36306e2f41bad056"><code>f0061d1</code></a> fix: removes all unused catch parameters</li> <li><a href="https://github.com/sverweij/dependency-cruiser/commit/1ee565bb8ee935385b4288891849740125829f99"><code>1ee565b</code></a> build(npm): updates external dependencies</li> <li>See full diff in <a href="https://github.com/sverweij/dependency-cruiser/compare/v18.1.0...v18.1.1">compare view</a></li> </ul> </details> <br /> Updates `pkg-pr-new` from 0.0.86 to 0.0.87 <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/stackblitz-labs/pkg.pr.new/commit/d293ab292f1e71640630a6e4e4683235b92cdef7"><code>d293ab2</code></a> release: v0.0.87</li> <li>See full diff in <a href="https://github.com/stackblitz-labs/pkg.pr.new/commits/v0.0.87/packages/cli">compare view</a></li> </ul> </details> <br /> Updates `skills` from 1.5.21 to 1.5.22 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vercel-labs/skills/releases">skills's releases</a>.</em></p> <blockquote> <h2>v1.5.22</h2> <h2>Changelog</h2> <ul> <li>fix: discover skills nested under two categories (<a href="https://redirect.github.com/vercel-labs/skills/issues/1866">#1866</a>)</li> <li>fix(update): normalize GitHub shorthand for project deletion checks (<a href="https://redirect.github.com/vercel-labs/skills/issues/1865">#1865</a>)</li> <li>fix: preserve locked GitHub host during updates (<a href="https://redirect.github.com/vercel-labs/skills/issues/1837">#1837</a>)</li> <li>Surface skills added upstream to well-known sources during update (<a href="https://redirect.github.com/vercel-labs/skills/issues/1824">#1824</a>)</li> <li>Make skills update work for well-known installs (incl. skills.sh packs) (<a href="https://redirect.github.com/vercel-labs/skills/issues/1821">#1821</a>)</li> <li>Preselect all skills when installing a skills.sh pack (<a href="https://redirect.github.com/vercel-labs/skills/issues/1820">#1820</a>)</li> <li>Add MiniMax Code agent support (<a href="https://redirect.github.com/vercel-labs/skills/issues/1814">#1814</a>)</li> <li>fix(remove): keep the lock entry while another agent still uses the skill (<a href="https://redirect.github.com/vercel-labs/skills/issues/1786">#1786</a>)</li> <li>fix(find): show all registry results in non-interactive search (<a href="https://redirect.github.com/vercel-labs/skills/issues/1748">#1748</a>)</li> <li>fix: store local path sources in lockfile using portable source (<a href="https://redirect.github.com/vercel-labs/skills/issues/1743">#1743</a>)</li> </ul> <h2>Contributors</h2> <p><a href="https://github.com/AndreaCovelli"><code>@AndreaCovelli</code></a>,<a href="https://github.com/IsmaelMartinez"><code>@IsmaelMartinez</code></a> <a href="https://github.com/SenseiMarv"><code>@SenseiMarv</code></a>,<a href="https://github.com/Ygilany"><code>@Ygilany</code></a> <a href="https://github.com/byapparov"><code>@byapparov</code></a>,<a href="https://github.com/hetaoBackend"><code>@hetaoBackend</code></a> <a href="https://github.com/mlekhi"><code>@mlekhi</code></a>,<a href="https://github.com/quuu"><code>@quuu</code></a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vercel-labs/skills/commit/a4d243c3d4f86cdf9385dd1b6a0733f6937e70b5"><code>a4d243c</code></a> v1.5.22</li> <li><a href="https://github.com/vercel-labs/skills/commit/ab4fc49265c443279a5deae20297e631470da68c"><code>ab4fc49</code></a> fix(find): show all returned search results (<a href="https://redirect.github.com/vercel-labs/skills/issues/1748">#1748</a>)</li> <li><a href="https://github.com/vercel-labs/skills/commit/644686b10ba6a6b563a1518e1a124a52e84460af"><code>644686b</code></a> Merge pull request <a href="https://redirect.github.com/vercel-labs/skills/issues/1743">#1743</a> from SenseiMarv/fix/store-local-path-sources-using-p...</li> <li><a href="https://github.com/vercel-labs/skills/commit/7533583f24a9a9be6fd5f783912f55c15a08b31e"><code>7533583</code></a> Merge branch 'main' into fix/store-local-path-sources-using-portable-source</li> <li><a href="https://github.com/vercel-labs/skills/commit/50d3b75443c24d2e224f5961cdd75e793c99d912"><code>50d3b75</code></a> fix project update GitHub shorthand clone (<a href="https://redirect.github.com/vercel-labs/skills/issues/1865">#1865</a>)</li> <li><a href="https://github.com/vercel-labs/skills/commit/653739a1ed1316cc2492ea81fbfcee14a45e4802"><code>653739a</code></a> fix: preserve locked GitHub host during updates (<a href="https://redirect.github.com/vercel-labs/skills/issues/1837">#1837</a>)</li> <li><a href="https://github.com/vercel-labs/skills/commit/65658a84d05961bbd0e2ea1afedb976946131315"><code>65658a8</code></a> Merge pull request <a href="https://redirect.github.com/vercel-labs/skills/issues/1786">#1786</a> from IsmaelMartinez/fix/remove-agent-subset-keeps-lock</li> <li><a href="https://github.com/vercel-labs/skills/commit/375f497e5c0e2d9ef743de372ce53545b1d77620"><code>375f497</code></a> Merge pull request <a href="https://redirect.github.com/vercel-labs/skills/issues/1866">#1866</a> from vercel-labs/fix/deeper-nested-skill-discovery</li> <li><a href="https://github.com/vercel-labs/skills/commit/dc045b90613a7c4d9c0feebbb96a27abedadf86b"><code>dc045b9</code></a> docs: update nested discovery depth</li> <li><a href="https://github.com/vercel-labs/skills/commit/6eeafb76573a798e330687c10fd83592bd619f8e"><code>6eeafb7</code></a> fix: discover skills nested under two categories</li> <li>Additional commits viewable in <a href="https://github.com/vercel-labs/skills/compare/v1.5.21...v1.5.22">compare view</a></li> </ul> </details> <br /> Updates `turbo` from 2.10.8 to 2.10.9 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vercel/turborepo/releases">turbo's releases</a>.</em></p> <blockquote> <h2>Turborepo v2.10.9</h2> <!-- raw HTML omitted --> <h2>What's Changed</h2> <h3>Changelog</h3> <ul> <li>chore: Release Turborepo 2.10.8 by <a href="https://github.com/github-actions"><code>@github-actions</code></a>[bot] in <a href="https://redirect.github.com/vercel/turborepo/pull/13626">vercel/turborepo#13626</a></li> <li>perf: Walk literal-prefix tree globs without wax compilation by <a href="https://github.com/charpeni"><code>@charpeni</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13522">vercel/turborepo#13522</a></li> <li>fix: Accept semver ranges in devEngines.packageManager.version by <a href="https://github.com/bangseongbeom"><code>@bangseongbeom</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13623">vercel/turborepo#13623</a></li> <li>docs: Explain affected package invalidation reasons by <a href="https://github.com/ghoullier"><code>@ghoullier</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13594">vercel/turborepo#13594</a></li> <li>perf(lockfiles): Borrow field-name scalars in the pnpm fast parser by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13648">vercel/turborepo#13648</a></li> <li>perf(repository): Avoid discarded alias allocation in Relationship by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13650">vercel/turborepo#13650</a></li> <li>perf(lockfiles): Drop redundant human_name clone for pnpm v7/v9 by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13649">vercel/turborepo#13649</a></li> <li>perf: Index workspace nodes by name in project_relationships by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13647">vercel/turborepo#13647</a></li> <li>perf: Share resolution identity lists across identical workspace closures by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13641">vercel/turborepo#13641</a></li> <li>docs: Fix duplicated word in runtime dependencies guide summary by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13630">vercel/turborepo#13630</a></li> <li>refactor: Remove turborepo-lsp dependency on turborepo-lib by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13631">vercel/turborepo#13631</a></li> <li>perf: Index Bun nested lockfile entries by name for fallback resolution by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13633">vercel/turborepo#13633</a></li> <li>perf: Memoize framework inference per package during task hashing by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13634">vercel/turborepo#13634</a></li> <li>perf: Avoid materializing transient declarations in external_dependencies by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13646">vercel/turborepo#13646</a></li> <li>perf: Enable shared closure DP for npm and yarn1 lockfiles by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13635">vercel/turborepo#13635</a></li> <li>perf: Parse pnpm explicit-key entries in the lockfile fast path by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13640">vercel/turborepo#13640</a></li> <li>perf: Parallelize resolution fingerprint hashing by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13642">vercel/turborepo#13642</a></li> <li>perf: Build resolution identity lists in parallel by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13643">vercel/turborepo#13643</a></li> <li>perf: Intern resolution identities as Arc<str> across closures by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13645">vercel/turborepo#13645</a></li> <li>fix: Compose affected tasks with package filters by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13656">vercel/turborepo#13656</a></li> <li>docs: Explain worktree cache path isolation by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13657">vercel/turborepo#13657</a></li> <li>fix: Upgrade brace-expansion to 5.0.9 by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13658">vercel/turborepo#13658</a></li> <li>docs: Correct verified inaccuracies in the Turborepo Agent Skill by <a href="https://github.com/charpeni"><code>@charpeni</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13644">vercel/turborepo#13644</a></li> <li>chore: Update Next.js to 16.3.0 by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13659">vercel/turborepo#13659</a></li> <li>fix: Don't use <code>eprintln!</code> in the panic hook by <a href="https://github.com/molofsky"><code>@molofsky</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13637">vercel/turborepo#13637</a></li> <li>fix: Invalidate only when Git ignore sources change by <a href="https://github.com/smasato"><code>@smasato</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13632">vercel/turborepo#13632</a></li> <li>docs: Update Geistdocs to 1.19.4 by <a href="https://github.com/christopherkindl"><code>@christopherkindl</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13680">vercel/turborepo#13680</a></li> <li>docs: Exclude Turborepo from its own OSS products menu by <a href="https://github.com/christopherkindl"><code>@christopherkindl</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13681">vercel/turborepo#13681</a></li> <li>docs: Use the geistdocs Turborepo logo in the navbar by <a href="https://github.com/christopherkindl"><code>@christopherkindl</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13682">vercel/turborepo#13682</a></li> <li>docs: Update redirected vercel.com/nextjs.org links to current targets by <a href="https://github.com/molebox"><code>@molebox</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13685">vercel/turborepo#13685</a></li> <li>refactor: Generalize native command arguments by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13664">vercel/turborepo#13664</a></li> <li>refactor: Move native contracts to tasks by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13665">vercel/turborepo#13665</a></li> <li>docs: Fix loadTransformers reference in turbo-codemod README by <a href="https://github.com/latent-9"><code>@latent-9</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13683">vercel/turborepo#13683</a></li> <li>refactor: Model native task execution explicitly by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13666">vercel/turborepo#13666</a></li> <li>feat: Compose aggregate native task dependencies by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13667">vercel/turborepo#13667</a></li> <li>fix: Respect aggregate task overrides by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13668">vercel/turborepo#13668</a></li> <li>test: Stabilize watch task inputs regression test by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13686">vercel/turborepo#13686</a></li> <li>feat: Parse Python quality tool declarations by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13669">vercel/turborepo#13669</a></li> <li>feat: Resolve Python quality plans by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13670">vercel/turborepo#13670</a></li> <li>refactor: Extract uv native task specs by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13671">vercel/turborepo#13671</a></li> <li>feat: Synthesize Python quality tasks by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13672">vercel/turborepo#13672</a></li> <li>test: Cover Python quality task commands by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13673">vercel/turborepo#13673</a></li> <li>feat: Hash Python quality task inputs by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13674">vercel/turborepo#13674</a></li> <li>test: Cover Python quality task graph by <a href="https://github.com/anthonyshew"><code>@anthonyshew</code></a> in <a href="https://redirect.github.com/vercel/turborepo/pull/13675">vercel/turborepo#13675</a></li> <li>chore: Release Turborepo 2.10.9-canary.1 by <a href="https://github.com/github-actions"><code>@github-actions</code></a>[bot] in <a href="https://redirect.github.com/vercel/turborepo/pull/13687">vercel/turborepo#13687</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/vercel/turborepo/commit/33237d4be13d7b74768c2cf3353b19cfa8d1af7c"><code>33237d4</code></a> publish 2.10.9 to registry</li> <li><a href="https://github.com/vercel/turborepo/commit/3b0e57f1289b2a6b3d6dd402bce928469d3b25fa"><code>3b0e57f</code></a> fix: Prevent Windows process cleanup PID reuse (<a href="https://redirect.github.com/vercel/turborepo/issues/13695">#13695</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/efe4e1bdf665f2950cf89d7968907de36c2f0737"><code>efe4e1b</code></a> fix: Prune Bun wildcard workspace dev dependencies (<a href="https://redirect.github.com/vercel/turborepo/issues/13694">#13694</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/a98e5cde97796088c6107684a64a40a967cd1ef0"><code>a98e5cd</code></a> docs: Document dependency-driven Python tasks (<a href="https://redirect.github.com/vercel/turborepo/issues/13676">#13676</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/c09a92f526b6dca9ea0243922f680803779759cd"><code>c09a92f</code></a> chore: Release Turborepo 2.10.9-canary.1 (<a href="https://redirect.github.com/vercel/turborepo/issues/13687">#13687</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/09bd548dddbff2a29086bdef7cb07b02d5e5458a"><code>09bd548</code></a> test: Cover Python quality task graph (<a href="https://redirect.github.com/vercel/turborepo/issues/13675">#13675</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/3584a5fb8edac9efc826fdea57e92088505fc76a"><code>3584a5f</code></a> feat: Hash Python quality task inputs (<a href="https://redirect.github.com/vercel/turborepo/issues/13674">#13674</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/0d43ff3cbf5ac8873c646a84b2fd7ae53097e08d"><code>0d43ff3</code></a> test: Cover Python quality task commands (<a href="https://redirect.github.com/vercel/turborepo/issues/13673">#13673</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/94708adc6bc19b41805741cc5a15ac5467a481cf"><code>94708ad</code></a> feat: Synthesize Python quality tasks (<a href="https://redirect.github.com/vercel/turborepo/issues/13672">#13672</a>)</li> <li><a href="https://github.com/vercel/turborepo/commit/e14f04ec6c2dc2791b0a3beb32df7515b31b3d4b"><code>e14f04e</code></a> refactor: Extract uv native task specs (<a href="https://redirect.github.com/vercel/turborepo/issues/13671">#13671</a>)</li> <li>Additional commits viewable in <a href="https://github.com/vercel/turborepo/compare/v2.10.8...v2.10.9">compare view</a></li> </ul> </details> <br /> Updates `wrangler` from 4.118.0 to 4.119.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/cloudflare/workers-sdk/releases">wrangler's releases</a>.</em></p> <blockquote> <h2>wrangler@4.119.0</h2> <h3>Minor Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/cloudflare/workers-sdk/pull/14952">#14952</a> <a href="https://github.com/cloudflare/workers-sdk/commit/20470fa8b09761c50b5c2c1d6a5f2652b61bd271"><code>20470fa</code></a> Thanks <a href="https://github.com/nelsonjsduarte"><code>@nelsonjsduarte</code></a>! - Add <code>--parse-type</code> flag to <code>wrangler ai-search create</code></p> <p><code>wrangler ai-search create</code> now accepts <code>--parse-type</code> to control how a website data source discovers URLs. <code>sitemap</code> (the default) reads XML sitemaps; <code>discover</code> follows links recursively.</p> <p>Previously the parse type could only be chosen through the interactive wizard, which was skipped whenever <code>--source</code> was supplied — so it was impossible to create a <code>discover</code> instance from a script.</p> <pre lang="sh"><code>wrangler ai-search create my-instance \ --type web-crawler \ --source https://example.com \ --parse-type discover </code></pre> <p>The interactive wizard now offers <code>Discover</code> alongside <code>Sitemap</code>. <code>--parse-type</code> is only valid with <code>--type web-crawler</code>; passing it with <code>--type builtin</code> or <code>--type r2</code> is rejected, since the API stores the value for those source types but never reads it. When the flag is omitted in non-interactive mode the field is left unset and the API default (<code>sitemap</code>) applies.</p> </li> <li> <p><a href="https://redirect.github.com/cloudflare/workers-sdk/pull/14941">#14941</a> <a href="https://github.com/cloudflare/workers-sdk/commit/266172b98c27770e6d48d3fd42790e2125115e5e"><code>266172b</code></a> Thanks <a href="https://github.com/nickpatt"><code>@nickpatt</code></a>! - Improve the Local Explorer's Observability views</p> <p><code>console.log</code> messages now render the way the console would (JSON-encoded strings are unwrapped and multi-argument logs are joined), traces and events can be looked up by trace or span id from the search bar, and an event's "View trace" button jumps to the exact invocation that emitted it — even when a trace_id spans several invocations (e.g. a subrequest or self fetch).</p> </li> <li> <p><a href="https://redirect.github.com/cloudflare/workers-sdk/pull/14064">#14064</a> <a href="https://github.com/cloudflare/workers-sdk/commit/a9e5abb8c0c2e7895b0bb09c6c8e8ffd3dbc3bc0"><code>a9e5abb</code></a> Thanks <a href="https://github.com/petebacondarwin"><code>@petebacondarwin</code></a>! - Add support for OAuth 2.0 Device Authorization Grant to <code>wrangler login</code></p> <p>Run <code>wrangler login --device</code> to authenticate without a local callback server. Useful in containers, remote SSH sessions, Codespaces, and any other environment where <code>localhost:8976</code> is unreachable from your browser.</p> <p>The new flow:</p> <ul> <li>prints the verification URL and user code to the terminal,</li> <li>attempts to open the verification URL in your default browser automatically (suppressed via <code>--browser=false</code>),</li> <li>and polls the token endpoint until you approve the request (with a 5-minute hard cap).</li> </ul> <p>The verification URL is supplied by the authorization server, so it is rejected unless it is an <code>https</code> URL on the same auth domain the device code was requested from — it is never printed or opened otherwise.</p> <p><code>--callback-host</code> and <code>--callback-port</code> cannot be combined with <code>--device</code>, since this flow does not start a local callback server.</p> </li> </ul> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/cloudflare/workers-sdk/pull/14984">#14984</a> <a href="https://github.com/cloudflare/workers-sdk/commit/9c7453837e3293787c0cb1778520f630aea7e5ca"><code>9c74538</code></a> Thanks <a href="https://github.com/apps/dependabot"><code>@dependabot</code></a>! - Update dependencies of "miniflare", "wrangler"</p> <p>The following dependency versions have been updated:</p> <table> <thead> <tr> <th>Dependency</th> <th>From</th> <th>To</th> </tr> </thead> <tbody> <tr> <td><code>@cloudflare/workers-types</code></td> <td>^5.20260730.1</td> <td>^5.20260731.1</td> </tr> <tr> <td>workerd</td> <td>1.20260730.1</td> <td>1.20260731.1</td> </tr> </tbody> </table> </li> <li> <p><a href="https://redirect.github.com/cloudflare/workers-sdk/pull/15012">#15012</a> <a href="https://github.com/cloudflare/workers-sdk/commit/0d33cb8dfb1d6289cb180f16e0e60cd7073a1b1b"><code>0d33cb8</code></a> Thanks <a href="https://github.com/apps/dependabot"><code>@dependabot</code></a>! - Update dependencies of "miniflare", "wrangler"</p> <p>The following dependency versions have been updated:</p> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/cloudflare/workers-sdk/commit/2938c01a9da2424a3f2d3c73bd870c7b75b39753"><code>2938c01</code></a> Version Packages (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/15021">#15021</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/b6a862966aaaa4d2bc7845a349636a6af65313fe"><code>b6a8629</code></a> Revert "Version Packages (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/14977">#14977</a>)" (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/15033">#15033</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/42c4227798c21cfde8dbfb087be1bb9078dab185"><code>42c4227</code></a> Version Packages (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/14977">#14977</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/511635c70821d33c64bb377e2c4a6be27683801f"><code>511635c</code></a> [wrangler] Skip the CAA half of the unenv-preset testDns E2E (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/15016">#15016</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/ebd1dfd3778dd3fdb9a63a5596852287eb4029b1"><code>ebd1dfd</code></a> [vite-plugin] Surface Local Explorer API to headless agents, matching wrangle...</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/a9e5abb8c0c2e7895b0bb09c6c8e8ffd3dbc3bc0"><code>a9e5abb</code></a> [wrangler] Add OAuth 2.0 Device Authorization Grant support (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/14064">#14064</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/20470fa8b09761c50b5c2c1d6a5f2652b61bd271"><code>20470fa</code></a> [wrangler] Add --parse-type to ai-search create (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/14952">#14952</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/5fd61271cdb7c661eace968ae4cbae40d2fbdc37"><code>5fd6127</code></a> [miniflare] De-flake rate limit tests at bucket boundaries (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler/issues/14961">#14961</a>)</li> <li>See full diff in <a href="https://github.com/cloudflare/workers-sdk/commits/wrangler@4.119.0/packages/wrangler">compare view</a></li> </ul> </details> <br /> Updates `@cloudflare/vitest-pool-workers` from 0.20.1 to 0.20.3 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/cloudflare/workers-sdk/releases">@cloudflare/vitest-pool-workers's releases</a>.</em></p> <blockquote> <h2><code>@cloudflare/vitest-pool-workers</code><a href="https://github.com/0"><code>@0</code></a>.20.3</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/cloudflare/workers-sdk/pull/15013">#15013</a> <a href="https://github.com/cloudflare/workers-sdk/commit/8cf78c83cb4c64be8b458d7bd618b47e7c6e7d25"><code>8cf78c8</code></a> Thanks <a href="https://github.com/dario-piotrowicz"><code>@dario-piotrowicz</code></a>! - Update undici from 7.28.0 to 7.29.0</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/cloudflare/workers-sdk/commit/35c87e97199fb4548d4d9aaac024c3e07be5734e"><code>35c87e9</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/b4f0c9760bcab1e04cf1a9c8859feed8b4fc6487"><code>b4f0c97</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/8cf78c83cb4c64be8b458d7bd618b47e7c6e7d25"><code>8cf78c8</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a60ff4dea0bbae8775726d9cf885655b56460a30"><code>a60ff4d</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/99eb50ce1d3420a50ae0e95958bf49d65874706e"><code>99eb50c</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/35c87e97199fb4548d4d9aaac024c3e07be5734e"><code>35c87e9</code></a>]:</p> <ul> <li>wrangler@4.120.0</li> <li><a href="mailto:miniflare@5.20260801.1-alpha">miniflare@5.20260801.1-alpha</a></li> </ul> </li> </ul> <h2><code>@cloudflare/vitest-pool-workers</code><a href="https://github.com/0"><code>@0</code></a>.20.2</h2> <h3>Patch Changes</h3> <ul> <li>Updated dependencies [<a href="https://github.com/cloudflare/workers-sdk/commit/20470fa8b09761c50b5c2c1d6a5f2652b61bd271"><code>20470fa</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/9c7453837e3293787c0cb1778520f630aea7e5ca"><code>9c74538</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/266172b98c27770e6d48d3fd42790e2125115e5e"><code>266172b</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a88d1691d57bf44616ad15556a51b7f8ca17375c"><code>a88d169</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a88d1691d57bf44616ad15556a51b7f8ca17375c"><code>a88d169</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/daf65f28cecf35e251dc6e476d5bbd82972d68de"><code>daf65f2</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a9e5abb8c0c2e7895b0bb09c6c8e8ffd3dbc3bc0"><code>a9e5abb</code></a>]: <ul> <li>wrangler@4.119.0</li> <li><a href="mailto:miniflare@5.20260801.0-alpha">miniflare@5.20260801.0-alpha</a></li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/cloudflare/workers-sdk/blob/main/packages/vitest-pool-workers/CHANGELOG.md">@cloudflare/vitest-pool-workers's changelog</a>.</em></p> <blockquote> <h2>0.20.3</h2> <h3>Patch Changes</h3> <ul> <li> <p><a href="https://redirect.github.com/cloudflare/workers-sdk/pull/15013">#15013</a> <a href="https://github.com/cloudflare/workers-sdk/commit/8cf78c83cb4c64be8b458d7bd618b47e7c6e7d25"><code>8cf78c8</code></a> Thanks <a href="https://github.com/dario-piotrowicz"><code>@dario-piotrowicz</code></a>! - Update undici from 7.28.0 to 7.29.0</p> </li> <li> <p>Updated dependencies [<a href="https://github.com/cloudflare/workers-sdk/commit/35c87e97199fb4548d4d9aaac024c3e07be5734e"><code>35c87e9</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/b4f0c9760bcab1e04cf1a9c8859feed8b4fc6487"><code>b4f0c97</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/8cf78c83cb4c64be8b458d7bd618b47e7c6e7d25"><code>8cf78c8</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a60ff4dea0bbae8775726d9cf885655b56460a30"><code>a60ff4d</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/99eb50ce1d3420a50ae0e95958bf49d65874706e"><code>99eb50c</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/35c87e97199fb4548d4d9aaac024c3e07be5734e"><code>35c87e9</code></a>]:</p> <ul> <li>wrangler@4.120.0</li> <li><a href="mailto:miniflare@5.20260801.1-alpha">miniflare@5.20260801.1-alpha</a></li> </ul> </li> </ul> <h2>0.20.2</h2> <h3>Patch Changes</h3> <ul> <li>Updated dependencies [<a href="https://github.com/cloudflare/workers-sdk/commit/20470fa8b09761c50b5c2c1d6a5f2652b61bd271"><code>20470fa</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/9c7453837e3293787c0cb1778520f630aea7e5ca"><code>9c74538</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/266172b98c27770e6d48d3fd42790e2125115e5e"><code>266172b</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a88d1691d57bf44616ad15556a51b7f8ca17375c"><code>a88d169</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a88d1691d57bf44616ad15556a51b7f8ca17375c"><code>a88d169</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/daf65f28cecf35e251dc6e476d5bbd82972d68de"><code>daf65f2</code></a>, <a href="https://github.com/cloudflare/workers-sdk/commit/a9e5abb8c0c2e7895b0bb09c6c8e8ffd3dbc3bc0"><code>a9e5abb</code></a>]: <ul> <li>wrangler@4.119.0</li> <li><a href="mailto:miniflare@5.20260801.0-alpha">miniflare@5.20260801.0-alpha</a></li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/cloudflare/workers-sdk/commit/b0aea76e0a7862b4ecfbe44232fb0a56ba3a2525"><code>b0aea76</code></a> Version Packages (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/vitest-pool-workers/issues/15036">#15036</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/2938c01a9da2424a3f2d3c73bd870c7b75b39753"><code>2938c01</code></a> Version Packages (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/vitest-pool-workers/issues/15021">#15021</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/b6a862966aaaa4d2bc7845a349636a6af65313fe"><code>b6a8629</code></a> Revert "Version Packages (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/vitest-pool-workers/issues/14977">#14977</a>)" (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/vitest-pool-workers/issues/15033">#15033</a>)</li> <li><a href="https://github.com/cloudflare/workers-sdk/commit/42c4227798c21cfde8dbfb087be1bb9078dab185"><code>42c4227</code></a> Version Packages (<a href="https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/vitest-pool-workers/issues/14977">#14977</a>)</li> <li>See full diff in <a href="https://github.com/cloudflare/workers-sdk/commits/@cloudflare/vitest-pool-workers@0.20.3/packages/vitest-pool-workers">compare view</a></li> </ul> </details> <br /> Updates `@cloudflare/workers-types` from 5.20260714.1 to 5.20260804.1 <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/cloudflare/workerd/commits">compare view</a></li> </ul> </details> <br /> Updates `@prisma/compute-sdk` from 0.38.0 to 0.39.0 <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/prisma/project-compute/commits">compare view</a></li> </ul> </details> <br /> Updates `@prisma/management-api-sdk` from 1.53.0 to 1.56.0 <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/prisma/pdp-control-plane/commits/HEAD/packages/management-api-sdk">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: willbot <w.a.madden+machine@gmail.com> | 22 天前 | |
TML-2624: renew the contract package coverage waiver (#30155) Renews the expired coverage waiver for `packages/1-framework/0-foundation/contract`. The 90-day waiver added 2026-05-29 lapsed on 2026-08-27, which flipped the Test job's coverage gate red on every open PR (first observed on #30154, a PR that doesn't touch the package). The underlying situation is unchanged — 93.75% branches vs the 94% floor, the same 15 uncovered branches as when the waiver was written — so this renews rather than fixes, following the file's existing renewal precedent (sqlite 2026-07-27, sql-orm-client 2026-08-21, 2-sql entries 2026-08-17). **Linear:** TML-2624 (the debt's tracking ticket; the recovery path — dedicated `canonicalization.ts` branch tests — stays named in the entry). **Scope:** Only `coverage.config.json`, one entry, two fields (`addedDate` → 2026-08-28; renewal sentence appended to `notes`). No code, no thresholds, no other entries. **Verification:** Diff shows the two-field change. Ran CI's gate locally on main±fix: the only delta is the disappearance of `ERROR: Coverage for branches (93.75%) does not meet … threshold (94%)`; `pnpm coverage:report` exits 0 with the entry back under non-blocking warnings, expires 2026-11-26. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Renewed the coverage waiver for the foundation contract package. * Updated waiver records to reflect the recent expiration and unchanged coverage metrics. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 11 天前 | |
ci: combine package tests and coverage (#30082) ## Linked issue n/a — this infrastructure migration has no Linear ticket. ## At a glance ```json "coverage:packages": "turbo run build --filter='!./examples/**' --filter='!./test/**' && vitest run --coverage", "coverage:report": "node scripts/coverage-report.mjs" ``` One root Vitest invocation now runs package tests and collects coverage, replacing the duplicated package-test and coverage CI jobs. ## Decision This PR ships three related changes: 1. Package tests and package coverage run together in one root Vitest multi-project invocation on Vitest `5.0.0-rc.2`. 2. Each package owns its complete coverage policy in an adjacent `coverage.config.json`, while root composition and post-processing preserve package thresholds and time-limited warning-only exceptions. 3. The obsolete, type-test-only SQL lane query-builder package and its public facade export are removed instead of retaining a permanently unmeasurable 95% runtime-coverage policy. ## Reviewer notes - The broad config diff is mostly moving existing coverage include/exclude/threshold blocks from `vitest.config.ts` into adjacent JSON policies and removing now-redundant package coverage scripts. - Vitest 5 removes `describe.sequential`; affected suites now use `{ concurrent: false }`. Compile-only `.test-d.ts` suites also declare compile-time test cases so Vitest 5 recognizes them. - `examples/prisma-8-cloudflare-worker` intentionally remains on Vitest 4 because `@cloudflare/vitest-pool-workers@0.20.3` requires Vitest 4 peers. - Eight existing package coverage deficits remain visible as active, non-blocking warning-only entries. Expired warnings and ordinary threshold failures still block CI. ## How it fits together 1. `scripts/coverage-config.js` discovers and validates package policies deterministically, rebases package globs to the repository root, and composes process-wide V8 collection settings. 2. The root `vitest.config.ts` references every package project and applies the composed coverage settings to a single test process. 3. `scripts/coverage-report.mjs` reads the root `coverage/coverage-final.json`, attributes files to their owning package, calculates all four metrics, and enforces each package's policy and warning expiry. 4. `.github/workflows/ci.yml` runs `pnpm coverage:packages` in the test job, reports package coverage even when collection finds a test failure, and removes the standalone coverage job. Test failures remain blocking. 5. Vitest 5 compatibility updates keep type tests, sequential suites, and CLI module mocks deterministic under the new runner behavior. ## Behavior changes & evidence - **Package tests execute once in CI while still producing coverage.** The combined command and workflow live in [`package.json`](package.json) and [`.github/workflows/ci.yml`](.github/workflows/ci.yml); [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs) guards the single-run workflow shape. - **Coverage ownership remains package-local and threshold enforcement remains package-aware.** Composition is implemented in [`scripts/coverage-config.js`](scripts/coverage-config.js), reporting in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs), and exercised by [`scripts/coverage-report.test.mjs`](scripts/coverage-report.test.mjs). - **Vitest 5 runs the workspace without the previous V8 merge bottleneck.** The workspace pins are in [`package.json`](package.json) and [`pnpm-lock.yaml`](pnpm-lock.yaml); representative compatibility fixes are covered by [`packages/1-framework/3-tooling/cli/test/migration-cli.test.ts`](packages/1-framework/3-tooling/cli/test/migration-cli.test.ts) and the migrated type-test suites. - **The obsolete SQL lane query-builder is no longer published.** Its package is removed, along with the facade dependency/export in [`packages/9-public/@prisma/orm-family-sql/package.json`](packages/9-public/@prisma/orm-family-sql/package.json) and publish-surface mapping in [`packages/0-shared/publish-surface/src/shells.ts`](packages/0-shared/publish-surface/src/shells.ts). ## Compatibility / migration / risk This is a pre-1.0 breaking cleanup: `@internal/sql-lane-query-builder` and `@prisma/orm-family-sql/lane-query-builder` are removed. Repository references and generated facade wiring were removed together, and the public SQL family shell rebuilds without them. Coverage semantics remain package-specific; only orchestration and report aggregation change. ## Testing performed - `CI=true TEST_TIMEOUT_MULTIPLIER=2 pnpm coverage:packages` — 1,155 files passed; 15,311 tests passed, 3 expected failures, no type errors - `pnpm coverage:report` — 69 package policies, 0 blocking failures, 8 active warnings, 0 expired warnings - `pnpm test:scripts` — 476 tests passed - `pnpm lint:deps` - `pnpm lint:manifests` - `pnpm build --filter=@prisma/orm-family-sql...` - Publish-surface tests and typecheck — 56 tests passed - Focused package tests/typechecks for CLI, Mongo runtime, SQL ORM client, SQLite codec testkit, integration tests, examples, and shell tarballs - `pnpm install --frozen-lockfile --ignore-scripts` - Targeted Biome checks and `git diff --check` ## Skill update n/a — the removed prototype query-builder export was not referenced by any user-facing skill; its package, public README, architecture docs, and publish surface were updated directly. ## Alternatives considered - **Keep Vitest 4 and optimize around it:** the single V8 run remained CPU-bound for more than 37 minutes because the relevant V8 merge optimization is only available in Vitest 5; the Vitest 4 backport was not merged. - **Switch to Istanbul coverage:** benchmarking was slower and introduced CLI language-server instrumentation timeouts, so V8 remains the provider. - **Run packages sequentially:** this preserves policy isolation but repeats runner startup and cannot eliminate duplicate test execution in CI; root collection plus package-aware post-processing keeps policy ownership without that cost. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no Linear ticket exists, so this uses the conventional commit title required by `CONTRIBUTING.md`. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Breaking Changes** - Removed the SQL lane query-builder package and its public package export. - Updated SQL documentation and package entrypoint references. - **Testing & Quality** - Centralized package coverage reporting with package-specific thresholds, exclusions, and warning policies. - Improved coverage validation, threshold reporting, and CI integration. - Updated serialized integration-test execution for compatibility with the current test runner. - **Documentation** - Expanded testing guidance for package coverage workflows and CI behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 18 天前 | |
Route migration/db commands through the control-api seam (TML-3173) (#29911) After this PR, no CLI command module reaches `@internal/migration-tools` at runtime — every operation goes through the control-api seam. At the top of a command module, the change looks like this: ```ts // before — commands/migrate.ts reaches business logic directly import { findLatestMigration, isGraphNode, parseContractRef } from '@internal/migration-tools/...'; // after — the same operations, through the seam; only published types remain importable import type { RefEntry, Refs } from '@internal/migration-tools/refs'; import { refuseMarkerOutsideGraph, resolveContractRef } from '../control-api/operations/...'; ``` Why this matters: the CLI implementation is destined to move to the consolidated `prisma` CLI repo while the control client stays here as the product's programmatic API. That move is only possible if commands hold no business logic — this PR makes the seam airtight. (Stacked on the project's shaping PR #29909; the reviewable diff is the four TML-3173 commits.) ## How it's built up - **Fourteen command modules re-routed** (db-init, db-sign, db-update, migrate, the migration interrogatives, ref), plus the shared status-overlay helper. Command modules keep argv parsing and rendering; policy moves down. - **New control-api operations** wrap each migration-tools touchpoint together with its existing CLI error mapping, returning `Result<T, CliStructuredError>` (the established db-verify pattern): ref/contract resolution, graph queries, invariant refusals, caught-error mapping, snapshot resolution, safe refs read, ref advancement. - **Whole policy cores moved verbatim** where the command was mostly business logic (`ref`, `migration-new`, `migration-plan`, `migration-check`, `migration-list`, `migrate --show`), with render callbacks (`onContextResolved`, `onSeeded`, `onPreflightComplete`) so the commands still print at exactly the same points. - **Behavior is pinned, not asserted**: zero changes under `test/integration/` (~50 journey suites green), goldens untouched except one forced import repath, and the cast ratchet improves (841 → 837). ## Verification `@internal/cli` build + 1,423 package tests green; full integration suite 314/317 files green (the 3 failures are environmental: a host-timezone artifact that passes under `TZ=UTC`, and two hook timeouts that pass in isolation); `lint:deps`, `lint:casts` green. ## Caveat worth knowing The dependency-cruiser rule added here (`cli-commands-no-runtime-migration-tools`) is currently **dormant**: the repo's cruise excludes `node_modules`/`dist`, so no cross-package edges exist for any boundary rule to fire on — a pre-existing repo-wide blind spot (TML-3178). The operative enforcement is the runtime-import grep, which returns clean. Coverage of the moved cores is a known pre-existing gap tracked in TML-3179. ## Alternatives considered - *Route only enough to satisfy a lint* — rejected: the point is the host-repo port, so whole cores moved where commands were mostly policy. - *A bespoke import-scanner script instead of the dep-cruiser rule* — deferred: one declarative rule in the established tool beats another ad-hoc scanner; the blind spot that currently mutes it is filed to be fixed repo-wide (TML-3178). - *Renaming the moved `execute*Command` functions now* — deliberately not: keeping names makes the diff mechanically reviewable; renames come with the command→result→renderer reshape in the next slice. Refs: TML-3173 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added shared capabilities for migration planning, checking, graph visualization, references, and contract resolution. * Added offline `migrate --show` planning with preflight results. * Improved migration creation, planning, status, listing, and reference workflows. * Expanded the public control API with migration and contract operations. * **Bug Fixes** * Standardized structured CLI error handling and validation for invalid paths, markers, invariants, and contract snapshots. * **Documentation** * Clarified error guidance for `db update` and invalid contract files. * **Tests** * Added comprehensive coverage for planning, references, graph validation, snapshot resolution, and error handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 1 个月前 | |
TML-3196: lower the PostgreSQL floor from 17 to 15 (ADR 244) (#29971) ## Linked issue Refs [TML-3196](https://linear.app/prisma-company/issue/TML-3196/pin-minimum-postgres-version-for-prisma-8). Resolves the overdue minimum-Postgres-version decision from `ROADMAP.md` (target date July 22). ## At a glance ```diff "prismaNext": { - "minServerVersion": "17" + "minServerVersion": "15" } ``` Every downstream surface follows from this field and its CLI mirror: `prisma-next init` scaffolds now generate `# Requires PostgreSQL >= 15.` in `.env.example` and "**PostgreSQL 15 or newer.**" in the quick reference, and the `--probe-db` warning threshold moves with it. ## Decision This PR pins the minimum supported PostgreSQL version for Prisma 8 at **15** (previously 17), and ships the decision as: 1. The floor change itself — `prismaNext.minServerVersion` on the Postgres target package plus the CLI's `MIN_SERVER_VERSION` mirror (drift-tested), with the CLI scaffold snapshot updated. 2. **[ADR 244 — PostgreSQL floor lowered to 15](docs/architecture%20docs/adrs/ADR%20244%20-%20PostgreSQL%20floor%20lowered%20to%2015.md)** — the full rationale: the feature audit, the CI reality, the support calendar and market context, and a record of what Postgres 16 and 17 would offer so a future raise starts from evidence. 3. An amendment to [ADR 222](docs/architecture%20docs/adrs/ADR%20222%20-%20Version%20support%20policy.md) correcting its enforcement record: the floor is proven by the `postgres:15` service containers in `.github/workflows/ci.yml`, not by `docker-compose.yaml` as ADR 222 originally claimed. 4. Alignment of local dev with the floor: `docker-compose.yaml` and the `gotchas.md` reproduction recipe move from `postgres:17-alpine` to `postgres:15-alpine`. ## Reviewer notes - **No CI change is needed.** All five Postgres service containers already run `postgres:15`; this PR makes the declared floor match what CI has been exercising all along. - **The feature audit says 12, the floor says 15 — deliberately.** The lowest version our emitted SQL, introspection, and migration DDL can run on is 12 (bounded by `ALTER TYPE ... ADD VALUE` inside the migration transaction). We declare 15 because it is the oldest version we actually test, and 14 dies in November 2026. - **ADR 222's "Why these specific floors" section still describes the 17-era reasoning.** That prose is left as a historical record; the amendment note, floor table, and bump procedure are what changed. - The full CLI suite is flaky under sandbox parallelism (a clean checkout fails a varying handful of tests run-to-run, each passing in isolation). The floor-guarding tests were run focused and deterministically — see below. - `examples/react-router-demo/.env.example` already told users "Any Postgres 15+"; it now agrees with the declared floor rather than contradicting it. ## How it fits together 1. **Source of truth:** `packages/3-targets/3-targets/postgres/package.json` declares `minServerVersion: "15"`. 2. **Mirror:** `MIN_SERVER_VERSION.postgres` in `packages/1-framework/3-tooling/cli/src/commands/init/templates/env.ts` follows; the drift test in `tsconfig-env.test.ts` asserts the two match, and the scaffold templates, quick reference, and `--probe-db` threshold all read the mirror. 3. **Record:** ADR 244 documents the decision; ADR 222's floor table, status line, and bump procedure are amended; `docs/Supported Versions.md` states 15 and links both ADRs. 4. **Infrastructure:** local dev (`docker-compose.yaml`, `gotchas.md`) runs the floor version, matching CI. 5. **Project bookkeeping:** `ROADMAP.md`, `projects/prisma-8-rc1/plan.md`, and `design-notes.md` record the decision as made on August 11, unblocking the scoreboard verdicts it was holding. ## Behavior changes & evidence - Fresh `prisma-next init` output states the 15 floor: `.env.example` says `# Requires PostgreSQL >= 15.` and `prisma-next.md` says "PostgreSQL 15 or newer." — [`env.ts`](packages/1-framework/3-tooling/cli/src/commands/init/templates/env.ts); evidence: [`templates.test.ts.snap`](packages/1-framework/3-tooling/cli/test/commands/init/__snapshots__/templates.test.ts.snap). - `init --probe-db` warns below 15 instead of below 17 (threshold flows from the mirror; no code change) — evidence: [`probe-db.test.ts`](packages/1-framework/3-tooling/cli/test/commands/init/probe-db.test.ts). - Servers on Postgres 15 and 16 are now inside the supported range — [`docs/Supported Versions.md`](docs/Supported%20Versions.md), [ADR 244](docs/architecture%20docs/adrs/ADR%20244%20-%20PostgreSQL%20floor%20lowered%20to%2015.md). ## Testing performed - `pnpm build` (86 tasks, all green) after the constant change. - `pnpm --filter @internal/cli test tsconfig-env templates probe-db` — 113/113 passed (drift test, scaffold snapshots, probe threshold). - Full `@internal/cli` suite run twice: the only failures were sandbox-parallelism flakes that also occur on a clean checkout and pass in isolation (ruled pre-existing). ## Skill update n/a — the user-facing scaffold text is generated from the `MIN_SERVER_VERSION` constant updated in this PR; no skill under `packages/0-shared/skills/` states a Postgres floor (verified by grep). ## Follow-ups - [TML-2320](https://linear.app/prisma-company/issue/TML-2320/runtime-version-check-warning-on-first-dbconnect-fr85-follow-up) — runtime version-check warning on first connect; today the only guard is the opt-in `init --probe-db` warning. - If we ever want to emit 16/17-only SQL (`ANY_VALUE`, `JSON_TABLE`, `MERGE ... RETURNING`), ADR 244 prescribes per-server capability gating in the Postgres adapter rather than raising the floor. ## Alternatives considered - **Keep the 17 floor** — rejected: CI never tested 17 (every job runs `postgres:15`), so the declaration claimed less compatibility than we actually prove, and it excluded the Prisma 7 migrating audience on 15/16 that the incremental-migration promise targets. - **Lower to 14 or to the feature floor of 12** — rejected: we test neither, declaring them would violate ADR 222's governing principle ("never claim broader compatibility than our test infrastructure exercises"); 14 reaches end of life in November 2026; going below 12 would require moving the native-enum `ADD VALUE` operation out of the migration transaction. - **Raise to 16 instead** — rejected: a full audit found nothing in 16 our code paths need (`ANY_VALUE` and the standard SQL/JSON constructors are conveniences; the 16 planner speedups benefit users on newer servers without any floor change). The architecturally interesting features (`JSON_TABLE`, `MERGE ... RETURNING`) are in 17, and capability gating is the cheaper path to them. - **Add a per-version CI matrix now** — deferred: the floor version is the version CI runs, which restores the policy's honesty without new infrastructure; matrix rows can come with the first capability-gated feature. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](CONTRIBUTING.md#developer-certificate-of-origin-dco). The DCO status check will block merge if any commit is missing a `Signed-off-by:` trailer. - [x] I read [CONTRIBUTING.md](CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated (scaffold snapshot refreshed; the drift test needed no change — it reads both sources dynamically). - [x] The PR title is in `TML-NNNN: <sentence-case title>` form (Linear ticket prefix + concise title naming the concrete deliverable). See `.claude/skills/create-pr/SKILL.md` for the full convention. - [x] The **Skill update** section above is filled in (or stated `n/a — internal only`). https://claude.ai/code/session_01WxsDtFe21Td8TQWznuywoW <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * PostgreSQL 15 is now the minimum supported server version. * Project setup and PostgreSQL tooling now target PostgreSQL 15 by default. * **Documentation** * Added guidance documenting the PostgreSQL 15 support policy and upgrade rationale. * Updated roadmap, supported-version references, architecture records, and troubleshooting instructions. * **Chores** * Updated local and CI PostgreSQL environments to use PostgreSQL 15. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 26 天前 | |
migration plan refuses to silently plan from an empty database when migrations exist (#30122) Here is the failure this PR removes. A project has one migration on disk and asks for the next one: ```console $ prisma migration plan --name add-user-role ✔ Planned migration 20260824_add-user-role from: (baseline) to: f3a9c1… ``` That plan looks fine and exits 0 — but `from: (baseline)` means "starting from an empty database", so the package contains `CREATE TABLE` for the entire schema. Applying it to any real database fails on the first statement. Nothing warned. A field tester shipped exactly this; our own gotchas file documents the trap. **The decision: `migration plan` now refuses to plan from an empty database when migrations already exist, unless you explicitly ask for that.** Silence becomes a structured error: ```console $ prisma migration plan --name add-user-role ✖ MIGRATION.PLAN_ORIGIN_UNKNOWN: no starting point for this plan. → Record where your database is: prisma migration ref set db 8c2fe0… → Or name the starting contract: prisma migration plan --from 8c2fe0… → Or plan from an empty database on purpose: --from @empty ``` To see why the silence existed, follow how `plan` picks its starting point. It is deliberately offline — it never connects to a database — so it reads the starting contract from `--from` if given, otherwise from the `db` ref: a small committed file recording which contract your dev database has been brought to. `db init` and `db update` maintain that file as you iterate. But a project that never runs those commands (the Composer-style workflow, where deploys apply migrations) never has a `db` ref — and plan's last resort was "assume empty database", silently, even with history sitting on disk. First plans are the legitimate case for that assumption, so the refusal only fires when migrations already exist on disk; a first plan in a fresh project still proceeds silently, including the auto-baseline (the from-empty starter migration `plan` writes alongside your first real change). The refusal immediately proved its worth inside this repo: three e2e journeys were walking the exact trap — planning follow-up migrations with no ref and no `--from`, producing from-empty migrations while their comments claimed incremental ones. The divergence journey was not testing divergence at all. They now chain with `--from` and prove what they claim. Also here: the gotchas entry is marked resolved; the roadmap's stale-ref data-loss item is narrowed, not closed (a ref that exists but points at the wrong contract is a different case this refusal does not cover); and a docs sweep against ADR 218 fixed six statements teaching the old behavior — four claiming `db update` advances no ref, two describing `migration plan` as advancing refs (that is TML-2560, still unimplemented; they now say so). Verification: 1436 CLI tests, 124 journey tests, typecheck, lint, and the error-reference check all green; every behavior above exercised against the built binary. **Alternatives considered.** *Warn instead of refuse*: a warning above a plausible-looking plan gets scrolled past — and the roadmap already classifies the sibling case as data-loss risk; an error with exits gets acted on, by agents especially. *Advance the ref at plan time so the situation can't arise*: rejected — the `db` ref means "where the dev database has been brought", and moving it for an unapplied plan corrupts that meaning; plan-time advancement as an explicit flag is tracked separately (TML-2560). *Teach the workflow and change nothing*: the prisma-8 skill rewrite does teach it (sibling PR), but the error channel reaches whoever the skill doesn't. Coordination: the sibling skill PR truthfully states today's lack of this refusal (one doc line, one journey-test assertion). Whichever PR merges second updates those two spots. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added `@empty` as the supported origin for planning migrations from an empty database. * `db update` on the default development database now advances the `db` reference automatically. * **Bug Fixes** * Migration planning now reports `MIGRATION.PLAN_ORIGIN_UNKNOWN` when migrations exist without a known origin. * Prevented `@empty` from being used as a migration destination. * **Documentation** * Updated CLI help, error guidance, roadmap, and migration documentation to reflect the new behavior and terminology. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 14 天前 | |
TML-2685: forbid bare as-casts via cast-utils + Biome plugin + CI ratchet (#598) | 3 个月前 | |
fix(skills): jj-aware artifact guard and v2-named schema helpers (TML-3223) (#30089) ## Linked issue Refs TML-3223 part 2 — the skills audit's script findings. ## Summary Two script-level findings from the audit, independent of the docs PR (#30088). **The artifact guard could not run in the repo that ships it.** `guard-review-artifacts-ignored.mjs` shells out to `git rev-parse`, so in a non-colocated Jujutsu workspace it failed before checking anything — and the review-fetch and review-triage phases both gate on it, so both were blocked here. Git stays the primary path, unchanged and exact. When git cannot answer, the guard walks up to the `.jj` directory and accepts an artifact directory under that workspace root's `wip/` tree, which `.gitignore` covers wholesale; anything outside it is refused. Demonstrated in this workspace, both states: ``` $ node …/guard-review-artifacts-ignored.mjs --dir wip/reviews/x ok: review artifacts are under the ignored wip/ tree: wip/reviews/x # exit 0 $ node …/guard-review-artifacts-ignored.mjs --dir docs error: without git, review artifacts must live under the ignored wip/ tree: …/wip # exit 1 ``` **The schema helpers were named for the version they no longer enforce.** `normalizeReviewStateV1` / `assertReviewStateV1` check `version: 2`. Renamed to `…V2` across the definition and its six call sites; `rg ReviewStateV1` returns nothing. Both SKILL.md files that describe the guard as a git check now describe both paths. ## Testing performed `pnpm test:scripts` (green — 0 failures), `pnpm lint:skills` (green), plus the guard demonstration above. ## Skill update This PR is skill maintenance: one guard script, one schema module and its consumers, and the two SKILL.md sentences that describe them. ## Notes for the reviewer The rename is pure — no behavior change, no signature change. The guard's git path is byte-identical; everything new sits behind the branch git previously threw from. https://claude.ai/code/session_01NnNjsNcPMtbJZhnZz5Zzbe <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added safe review-artifact validation for Jujutsu workspaces without a Git directory. * Artifacts can be stored under the workspace’s ignored `wip/` directory, while unsafe paths and symlink escapes are rejected. * **Improvements** * Updated review-state processing to use the current schema across workflows. * Preserved existing Git-based safety checks and command-line behavior. * **Tests** * Added coverage for valid, missing, boundary-violating, and unsafe workspace artifact paths. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Oleksii Orlenko <robot@aqrln.net> | 8 天前 | |
TML-3227: central attribute-spec registration machinery (registry-core) (#30154) First slice of the attribute-registry project: every consumer of PSL attribute knowledge — family interpreters and the language server — gets one shared registration surface, delivering the central-registration follow-up that ADR 231 deferred. This slice builds the machinery end-to-end and proves it LSP-consumable; registering the actual SQL/Mongo built-in sets and block-level attributes follow as parallel slices (TML-3228/3229/3230). ## Changes - **Contribution surface (`@internal/framework-components`)**: `AuthoringContributions` gains an optional `attributeSpecs` key (`{ model, field }` records) whose entries transit core erased as `unknown` — core cannot name `AttributeSpec` (it lives in the PSL authoring layer), the same erasure pattern the descriptor `spec` field already uses. `AssembledAuthoringContributions.attributeSpecs` is required; assembly merges per level with duplicate-name, non-function-entry, and prototype-polluting-name rejection (`mergeAuthoringAttributeSpecs` in `framework-authoring.ts`). - **Uniform factory ctx + assembled view (`@internal/psl-parser`)**: `AttributeSpecContext` (`{ symbols, model, controlMutationDefaults }`) and `FieldAttributeSpecContext` (adds required `field`) are the framework-owned context every spec factory takes. `assembleAttributeSpecs` merges family built-ins with target-contributed descriptor specs into `AssembledAttributeSpecs` — **plain frozen data, no interface or accessor methods**. Interpreters never consume this view: each family keeps total, `InferAttr`-typed access through its own registered `const` namespace; the assembled records serve consumers that genuinely face unknown names (LSP enumeration, upcoming unknown-attribute diagnostics). The one `blindCast` in `assemble.ts` is the project's single documented narrow restoring the erased factory types. - **ADR 236 descriptor migration**: `AuthoringModelAttributeDescriptor.spec` is re-contracted from "spec value" to "spec factory over the uniform ctx". Postgres `@@rls` supplies a typed factory const; the SQL interpreter's contributed-attribute loop invokes the factory with a ctx built from facts already at the site (symbol table, declaring `ModelSymbol`, default-function registry) — the existing narrow was reshaped in place, and a new test pins the ctx threading by identity (it fails if the registry slot is wired to anything but the composed stack's registry). ADR 236's text now describes the factory shape. - **LSP-consumability proof**: two test-only proofs, split by a real layering constraint (Domain 1 may not name Domain 3). `packages/1-framework/3-tooling/language-server/test/attribute-spec-consumability.test.ts` proves the plumbing with a synthetic target pack registered at a nested path claiming `rls` — simultaneously proving enumeration must go through `assembleAttributeSpecs`, since namespace path segments are not attribute names. `test/integration/test/authoring/attribute-specs.lsp-consumability.test.ts` proves the real postgres `@@rls` descriptor reaches a resolved LSP project through `resolveConfigInputs` — it goes red if the postgres pack stops registering `@@rls`. Zero production changes in the language server. ## Why - **Factories, not spec values**: the attribute surface isn't fully static (SQL builds `@default` specs per field, Mongo builds index specs per model), so the uniform entry shape is `(ctx) => AttributeSpec` with static specs as nullary factories — one shape, no consumer branching (project design decision, ADR 231's dynamic-composition principle). - **Plain data over a registry service**: accessor methods overloaded on a string `level` add nothing — the level is statically known at every call site — and a generic `get(): F | undefined` would force `undefined` checks on interpreters whose key sets are total. Data view for unknown-name consumers, `const` namespaces for interpreters. - **`AttributeSpec<never>` as the erased factory return type**: `Out` is contravariant (via `refine`), so `AttributeSpec<unknown>` rejects every real spec; `never` follows the codebase's own precedent (`AuthoringModelAttributeDescriptor<Out = never>`). Caught by compiler probe before implementation. - **Emitted contracts are untouched**: `pnpm fixtures:check` is byte-clean — this is authoring-time machinery only. Slice workspace (spec, plan, design decisions): `projects/attribute-registry/slices/registry-core/`. Refs: TML-3227 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for registering and consuming contributed model- and field-level attribute specifications. * Attribute specifications can now be created with relevant schema context, including the declaring model or field. * Added support for resolving contributed attributes by their declared names across tooling and integrations. * **Bug Fixes** * Improved validation for malformed, duplicate, or unsafe attribute registrations. * Ensured assembled attribute specifications remain stable and protected from unintended modification. * **Documentation** * Updated architecture guidance with the new attribute specification contribution workflow. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 11 天前 | |
ci: combine package tests and coverage (#30082) ## Linked issue n/a — this infrastructure migration has no Linear ticket. ## At a glance ```json "coverage:packages": "turbo run build --filter='!./examples/**' --filter='!./test/**' && vitest run --coverage", "coverage:report": "node scripts/coverage-report.mjs" ``` One root Vitest invocation now runs package tests and collects coverage, replacing the duplicated package-test and coverage CI jobs. ## Decision This PR ships three related changes: 1. Package tests and package coverage run together in one root Vitest multi-project invocation on Vitest `5.0.0-rc.2`. 2. Each package owns its complete coverage policy in an adjacent `coverage.config.json`, while root composition and post-processing preserve package thresholds and time-limited warning-only exceptions. 3. The obsolete, type-test-only SQL lane query-builder package and its public facade export are removed instead of retaining a permanently unmeasurable 95% runtime-coverage policy. ## Reviewer notes - The broad config diff is mostly moving existing coverage include/exclude/threshold blocks from `vitest.config.ts` into adjacent JSON policies and removing now-redundant package coverage scripts. - Vitest 5 removes `describe.sequential`; affected suites now use `{ concurrent: false }`. Compile-only `.test-d.ts` suites also declare compile-time test cases so Vitest 5 recognizes them. - `examples/prisma-8-cloudflare-worker` intentionally remains on Vitest 4 because `@cloudflare/vitest-pool-workers@0.20.3` requires Vitest 4 peers. - Eight existing package coverage deficits remain visible as active, non-blocking warning-only entries. Expired warnings and ordinary threshold failures still block CI. ## How it fits together 1. `scripts/coverage-config.js` discovers and validates package policies deterministically, rebases package globs to the repository root, and composes process-wide V8 collection settings. 2. The root `vitest.config.ts` references every package project and applies the composed coverage settings to a single test process. 3. `scripts/coverage-report.mjs` reads the root `coverage/coverage-final.json`, attributes files to their owning package, calculates all four metrics, and enforces each package's policy and warning expiry. 4. `.github/workflows/ci.yml` runs `pnpm coverage:packages` in the test job, reports package coverage even when collection finds a test failure, and removes the standalone coverage job. Test failures remain blocking. 5. Vitest 5 compatibility updates keep type tests, sequential suites, and CLI module mocks deterministic under the new runner behavior. ## Behavior changes & evidence - **Package tests execute once in CI while still producing coverage.** The combined command and workflow live in [`package.json`](package.json) and [`.github/workflows/ci.yml`](.github/workflows/ci.yml); [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs) guards the single-run workflow shape. - **Coverage ownership remains package-local and threshold enforcement remains package-aware.** Composition is implemented in [`scripts/coverage-config.js`](scripts/coverage-config.js), reporting in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs), and exercised by [`scripts/coverage-report.test.mjs`](scripts/coverage-report.test.mjs). - **Vitest 5 runs the workspace without the previous V8 merge bottleneck.** The workspace pins are in [`package.json`](package.json) and [`pnpm-lock.yaml`](pnpm-lock.yaml); representative compatibility fixes are covered by [`packages/1-framework/3-tooling/cli/test/migration-cli.test.ts`](packages/1-framework/3-tooling/cli/test/migration-cli.test.ts) and the migrated type-test suites. - **The obsolete SQL lane query-builder is no longer published.** Its package is removed, along with the facade dependency/export in [`packages/9-public/@prisma/orm-family-sql/package.json`](packages/9-public/@prisma/orm-family-sql/package.json) and publish-surface mapping in [`packages/0-shared/publish-surface/src/shells.ts`](packages/0-shared/publish-surface/src/shells.ts). ## Compatibility / migration / risk This is a pre-1.0 breaking cleanup: `@internal/sql-lane-query-builder` and `@prisma/orm-family-sql/lane-query-builder` are removed. Repository references and generated facade wiring were removed together, and the public SQL family shell rebuilds without them. Coverage semantics remain package-specific; only orchestration and report aggregation change. ## Testing performed - `CI=true TEST_TIMEOUT_MULTIPLIER=2 pnpm coverage:packages` — 1,155 files passed; 15,311 tests passed, 3 expected failures, no type errors - `pnpm coverage:report` — 69 package policies, 0 blocking failures, 8 active warnings, 0 expired warnings - `pnpm test:scripts` — 476 tests passed - `pnpm lint:deps` - `pnpm lint:manifests` - `pnpm build --filter=@prisma/orm-family-sql...` - Publish-surface tests and typecheck — 56 tests passed - Focused package tests/typechecks for CLI, Mongo runtime, SQL ORM client, SQLite codec testkit, integration tests, examples, and shell tarballs - `pnpm install --frozen-lockfile --ignore-scripts` - Targeted Biome checks and `git diff --check` ## Skill update n/a — the removed prototype query-builder export was not referenced by any user-facing skill; its package, public README, architecture docs, and publish surface were updated directly. ## Alternatives considered - **Keep Vitest 4 and optimize around it:** the single V8 run remained CPU-bound for more than 37 minutes because the relevant V8 merge optimization is only available in Vitest 5; the Vitest 4 backport was not merged. - **Switch to Istanbul coverage:** benchmarking was slower and introduced CLI language-server instrumentation timeouts, so V8 remains the provider. - **Run packages sequentially:** this preserves policy isolation but repeats runner startup and cannot eliminate duplicate test execution in CI; root collection plus package-aware post-processing keeps policy ownership without that cost. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no Linear ticket exists, so this uses the conventional commit title required by `CONTRIBUTING.md`. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Breaking Changes** - Removed the SQL lane query-builder package and its public package export. - Updated SQL documentation and package entrypoint references. - **Testing & Quality** - Centralized package coverage reporting with package-specific thresholds, exclusions, and warning policies. - Improved coverage validation, threshold reporting, and CI integration. - Updated serialized integration-test execution for compatibility with the current test runner. - **Documentation** - Expanded testing guidance for package coverage workflows and CI behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 18 天前 | |
Add declarative config for rules footprint thresholds Move hardcoded THRESHOLDS from the script to a JSON config file at .cursor/rules-footprint.config.json. This follows the project pattern of preferring declarative configuration over embedded constants. Include a JSON schema for validation and editor autocomplete support. | 7 个月前 | |
fix(sql-orm-client): route M:N scalar includes through junctions (#29888) ## Linked issue n/a — small bug fix; no Linear ticket exists. ## At a glance ```ts const group = await db.public.Group.where({ title: GROUP_TITLE }) .include('users', (u) => u.where({ blocked: true }).count()) .first(); expect(group?.users).toBe(1); ``` Previously this N:M count emitted a direct `user.groupId = group.id` predicate even though `groupId` exists only on the junction table. ## Decision This PR routes scalar relation includes such as `count()`, `sum()`, `avg()`, `min()`, and `max()` through the relation's junction metadata whenever the relation is N:M. It reuses the same junction artifact builder as row includes, so parent correlation, child joins, namespaces, and composite keys follow one established implementation. ## Summary N:M scalar includes no longer reference nonexistent direct foreign-key columns on child tables. Five Prisma compatibility tests now pass as ordinary regression coverage, and the feature-support scorecard marks the proven Postgres capability as working. ## Reviewer notes - The behavioral change is isolated to `buildIncludeChildScalarSelect`; non-junction relations retain their existing direct predicate. - Junction joins are attached in both aggregate paths: the direct aggregate and the shaped inner select used by pagination or distinct refinements. - The first full-suite CI run hit an unrelated 200 ms timeout in `sqlite-include-canonical-json.test.ts`; the timeout retry then collided with rows seeded by the first attempt. That file passes locally in isolation and alongside the affected ports. - There is intentionally no Linear link or `TML-NNNN` title prefix because no ticket exists for this small bug fix. ## How it fits together 1. [`query-plan-select.ts`](packages/3-extensions/sql-orm-client/src/query-plan-select.ts) resolves the complete parent-local column set for scalar includes, matching row-include behavior. 2. N:M relations call the existing junction artifact builder to produce the junction-to-parent correlation and child-to-junction join; direct relations continue to use `targetColumn`. 3. The planner carries the junction join into both unshaped aggregate selects and shaped aggregate inputs, preserving `where`, pagination, and distinct semantics. 4. The affected Prisma ports become ordinary tests, and [`failing.md`](test/integration/test/ports/prisma/failing.md) drops the five resolved entries. 5. [`scorecard/11-aggregation-and-grouping.md`](scorecard/11-aggregation-and-grouping.md) promotes explicit-M:N relation counts to supported for Postgres, with [`scorecard.md`](scorecard.md) keeping the aggregate tallies synchronized. ## Behavior changes & evidence - **Filtered N:M counts now traverse the junction and return the expected count.** Implementation: [`query-plan-select.ts`](packages/3-extensions/sql-orm-client/src/query-plan-select.ts). Evidence: [`filter-count-relations.test.ts`](test/integration/test/ports/prisma/functional/filter-count-relations/filter-count-relations.test.ts). - **Multiple scalar N:M includes can be selected in one query without invalid child-column references.** Implementation: [`query-plan-select.ts`](packages/3-extensions/sql-orm-client/src/query-plan-select.ts). Evidence: [`issues-11974.test.ts`](test/integration/test/ports/prisma/functional/issues-11974/issues-11974.test.ts). - **N:M counts remain correct after a related row is deleted.** Implementation: [`query-plan-select.ts`](packages/3-extensions/sql-orm-client/src/query-plan-select.ts). Evidence: [`issues-12557.test.ts`](test/integration/test/ports/prisma/functional/issues-12557/issues-12557.test.ts). - **The feature-support matrix now reports this proven Postgres capability as working.** Documentation: [`scorecard/11-aggregation-and-grouping.md`](scorecard/11-aggregation-and-grouping.md) and [`scorecard.md`](scorecard.md). Evidence remains the three live Postgres suites above. ## Compatibility / migration / risk No public API or contract shape changes. Existing direct relations retain their current query plan. Risk is limited to N:M scalar-include SQL generation and is covered by live Postgres integration tests. ## Testing performed - `pnpm --filter @internal/sql-orm-client build` - `pnpm --filter @internal/sql-orm-client typecheck` - `pnpm --filter @internal/sql-orm-client test` — 681 tests passed - `pnpm --filter integration-tests exec vitest run test/ports/prisma/functional/issues-11974/issues-11974.test.ts test/ports/prisma/functional/issues-12557/issues-12557.test.ts test/ports/prisma/functional/filter-count-relations/filter-count-relations.test.ts test/sql-orm-client/sqlite-include-canonical-json.test.ts` — 15 tests passed; zero type errors - `pnpm check:upgrade-coverage --mode pr` - `pnpm lint:skills` - `pnpm lint` — 99/99 Turbo tasks passed - `node --test scripts/check-upgrade-coverage.test.mjs` — 46 tests passed - `pnpm biome check packages/3-extensions/sql-orm-client/src/query-plan-select.ts test/integration/test/ports/prisma/functional/issues-11974/issues-11974.test.ts test/integration/test/ports/prisma/functional/issues-12557/issues-12557.test.ts test/integration/test/ports/prisma/functional/filter-count-relations/filter-count-relations.test.ts test/integration/test/ports/prisma/failing.md --error-on-warnings` - `git diff --check` ## Skill update No public API, CLI, configuration, error-code, or terminology surface changed. The required extension-author declaration records this as an incidental `changes: []` transition in [`skills/extension-author/prisma-8-extension-upgrade/upgrades/0.17-to-0.18/instructions.md`](skills/extension-author/prisma-8-extension-upgrade/upgrades/0.17-to-0.18/instructions.md). ## Alternatives considered - **Teach each scalar reducer to construct its own junction SQL.** Rejected because it would duplicate namespace, self-relation, and composite-key behavior already centralized in `buildManyToManyJunctionArtifacts`. - **Aggregate directly over junction rows for `count()`.** Rejected because filtered counts and the other scalar reducers need the target child table; one child-plus-junction path keeps reducer behavior consistent. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — n/a because no Linear ticket exists. - [x] The **Skill update** section above is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for relation-scoped counts in `include()` queries over explicit many-to-many relationships on Postgres. * Improved handling of filtered and paginated many-to-many relation counts. * **Bug Fixes** * Corrected relation-count query behavior for supported many-to-many scenarios. * **Documentation** * Updated upgrade guidance and feature support scorecards to reflect the new Postgres capability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 1 个月前 | |
ci: combine package tests and coverage (#30082) ## Linked issue n/a — this infrastructure migration has no Linear ticket. ## At a glance ```json "coverage:packages": "turbo run build --filter='!./examples/**' --filter='!./test/**' && vitest run --coverage", "coverage:report": "node scripts/coverage-report.mjs" ``` One root Vitest invocation now runs package tests and collects coverage, replacing the duplicated package-test and coverage CI jobs. ## Decision This PR ships three related changes: 1. Package tests and package coverage run together in one root Vitest multi-project invocation on Vitest `5.0.0-rc.2`. 2. Each package owns its complete coverage policy in an adjacent `coverage.config.json`, while root composition and post-processing preserve package thresholds and time-limited warning-only exceptions. 3. The obsolete, type-test-only SQL lane query-builder package and its public facade export are removed instead of retaining a permanently unmeasurable 95% runtime-coverage policy. ## Reviewer notes - The broad config diff is mostly moving existing coverage include/exclude/threshold blocks from `vitest.config.ts` into adjacent JSON policies and removing now-redundant package coverage scripts. - Vitest 5 removes `describe.sequential`; affected suites now use `{ concurrent: false }`. Compile-only `.test-d.ts` suites also declare compile-time test cases so Vitest 5 recognizes them. - `examples/prisma-8-cloudflare-worker` intentionally remains on Vitest 4 because `@cloudflare/vitest-pool-workers@0.20.3` requires Vitest 4 peers. - Eight existing package coverage deficits remain visible as active, non-blocking warning-only entries. Expired warnings and ordinary threshold failures still block CI. ## How it fits together 1. `scripts/coverage-config.js` discovers and validates package policies deterministically, rebases package globs to the repository root, and composes process-wide V8 collection settings. 2. The root `vitest.config.ts` references every package project and applies the composed coverage settings to a single test process. 3. `scripts/coverage-report.mjs` reads the root `coverage/coverage-final.json`, attributes files to their owning package, calculates all four metrics, and enforces each package's policy and warning expiry. 4. `.github/workflows/ci.yml` runs `pnpm coverage:packages` in the test job, reports package coverage even when collection finds a test failure, and removes the standalone coverage job. Test failures remain blocking. 5. Vitest 5 compatibility updates keep type tests, sequential suites, and CLI module mocks deterministic under the new runner behavior. ## Behavior changes & evidence - **Package tests execute once in CI while still producing coverage.** The combined command and workflow live in [`package.json`](package.json) and [`.github/workflows/ci.yml`](.github/workflows/ci.yml); [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs) guards the single-run workflow shape. - **Coverage ownership remains package-local and threshold enforcement remains package-aware.** Composition is implemented in [`scripts/coverage-config.js`](scripts/coverage-config.js), reporting in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs), and exercised by [`scripts/coverage-report.test.mjs`](scripts/coverage-report.test.mjs). - **Vitest 5 runs the workspace without the previous V8 merge bottleneck.** The workspace pins are in [`package.json`](package.json) and [`pnpm-lock.yaml`](pnpm-lock.yaml); representative compatibility fixes are covered by [`packages/1-framework/3-tooling/cli/test/migration-cli.test.ts`](packages/1-framework/3-tooling/cli/test/migration-cli.test.ts) and the migrated type-test suites. - **The obsolete SQL lane query-builder is no longer published.** Its package is removed, along with the facade dependency/export in [`packages/9-public/@prisma/orm-family-sql/package.json`](packages/9-public/@prisma/orm-family-sql/package.json) and publish-surface mapping in [`packages/0-shared/publish-surface/src/shells.ts`](packages/0-shared/publish-surface/src/shells.ts). ## Compatibility / migration / risk This is a pre-1.0 breaking cleanup: `@internal/sql-lane-query-builder` and `@prisma/orm-family-sql/lane-query-builder` are removed. Repository references and generated facade wiring were removed together, and the public SQL family shell rebuilds without them. Coverage semantics remain package-specific; only orchestration and report aggregation change. ## Testing performed - `CI=true TEST_TIMEOUT_MULTIPLIER=2 pnpm coverage:packages` — 1,155 files passed; 15,311 tests passed, 3 expected failures, no type errors - `pnpm coverage:report` — 69 package policies, 0 blocking failures, 8 active warnings, 0 expired warnings - `pnpm test:scripts` — 476 tests passed - `pnpm lint:deps` - `pnpm lint:manifests` - `pnpm build --filter=@prisma/orm-family-sql...` - Publish-surface tests and typecheck — 56 tests passed - Focused package tests/typechecks for CLI, Mongo runtime, SQL ORM client, SQLite codec testkit, integration tests, examples, and shell tarballs - `pnpm install --frozen-lockfile --ignore-scripts` - Targeted Biome checks and `git diff --check` ## Skill update n/a — the removed prototype query-builder export was not referenced by any user-facing skill; its package, public README, architecture docs, and publish surface were updated directly. ## Alternatives considered - **Keep Vitest 4 and optimize around it:** the single V8 run remained CPU-bound for more than 37 minutes because the relevant V8 merge optimization is only available in Vitest 5; the Vitest 4 backport was not merged. - **Switch to Istanbul coverage:** benchmarking was slower and introduced CLI language-server instrumentation timeouts, so V8 remains the provider. - **Run packages sequentially:** this preserves policy isolation but repeats runner startup and cannot eliminate duplicate test execution in CI; root collection plus package-aware post-processing keeps policy ownership without that cost. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — no Linear ticket exists, so this uses the conventional commit title required by `CONTRIBUTING.md`. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Breaking Changes** - Removed the SQL lane query-builder package and its public package export. - Updated SQL documentation and package entrypoint references. - **Testing & Quality** - Centralized package coverage reporting with package-specific thresholds, exclusions, and warning policies. - Improved coverage validation, threshold reporting, and CI integration. - Updated serialized integration-test execution for compatibility with the current test runner. - **Documentation** - Expanded testing guidance for package coverage workflows and CI behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 18 天前 | |
ci: shard package tests without weakening coverage gates (#30156) ## Linked issue n/a — infrastructure change without a Linear ticket. ## At a glance ```yaml # Package Tests (1/4 ... 4/4) - run: pnpm coverage:packages --reporter=blob --shard=${{ matrix.index }}/4 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # Coverage - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with: pattern: package-coverage-* merge-multiple: true - run: pnpm coverage:packages:merge - run: pnpm coverage:report ``` Package tests now execute on four runners, while a separate `Coverage` job evaluates thresholds once against the combined native Vitest report. `Test Examples` runs concurrently, and a lightweight final `Test` job preserves the required status name. ## Summary The package-test portion of `Test` was the remaining serial CI bottleneck. This change shards that work horizontally while keeping one authoritative coverage gate and the existing required `Test` status context. ## Decision This PR ships three connected CI changes: 1. Run package tests and V8 coverage across four native Vitest shards, each uploading one uniquely named blob artifact. 2. Download and require all four blob reports in a separate `Coverage` fan-in job, merge their coverage counters with Vitest, and only then apply the existing package-level thresholds and warning policy. 3. Run examples concurrently and preserve assertion failures, inert-diff behavior, and the required `Test` check name through a lightweight final gate. ## Reviewer notes - Shards use SHA-pinned `actions/upload-artifact`; `Coverage` uses SHA-pinned `actions/download-artifact` with `pattern: package-coverage-*` and `merge-multiple: true`. Both are GitHub-created actions in the `actions` organization, so the existing GitHub-actions category permits them without individual allow-list entries. - Uploads set `include-hidden-files: true` because Vitest writes blobs below `.vitest/blob`, and `if-no-files-found: error` prevents a shard from silently publishing nothing. - GitHub does not expose artifacts from an earlier workflow attempt to rerun jobs. Use **Re-run all jobs**, not **Re-run failed jobs**; a partial rerun fails safely when `Coverage` verifies the four expected files. - Coverage thresholds and file reporters are deliberately disabled only in partial shard processes. The merge process runs without the shard marker and therefore restores the complete policy. - The stable required status remains `Test`; the four `Package Tests (N/4)` jobs, `Coverage`, and `Test Examples` are implementation details behind its final result. - The hosted four-runner transport can only execute in GitHub Actions. A local two-shard smoke test proved Vitest's blob names, merged counters, and final-only 100% threshold behavior. ## How it fits together 1. [`vitest.config.ts`](vitest.config.ts) recognizes shard collection through `VITEST_COVERAGE_SHARD`, keeps the full include/exclude policy, and suppresses only partial-run thresholds and coverage output. 2. [`.github/workflows/ci.yml`](.github/workflows/ci.yml) runs `vitest --coverage --reporter=blob --shard=N/4` on four PostgreSQL-backed runners. Each shard still reports test failures, uploads exactly one hidden blob file, and explicitly propagates a failing outcome after the upload. 3. `Coverage` downloads all `package-coverage-*` artifacts into `.vitest/blob` and checks for `blob-1-4.json` through `blob-4-4.json` before doing any merge. 4. [`pnpm coverage:packages:merge`](package.json) invokes Vitest's native `--merge-reports` path, which combines Istanbul counters rather than averaging percentages and replays failed tests. 5. The existing [`pnpm coverage:report`](scripts/coverage-report.mjs) attributes merged source entries to packages and enforces their thresholds. `Test Examples` runs concurrently, while the final `Test` job fails if any package shard, coverage, example, or prerequisite job failed. ## Behavior changes & evidence - **Package tests execute across four CI runners instead of one.** The matrix and fan-in are in [`.github/workflows/ci.yml`](.github/workflows/ci.yml), with the expected orchestration locked by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **Coverage gates see the complete combined run.** Shard-aware configuration lives in [`vitest.config.ts`](vitest.config.ts), while the native merge command is declared in [`package.json`](package.json) and existing package aggregation remains in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs). - **Missing shards, assertion failures, and partial reruns cannot silently pass.** Unique artifact names, hidden-file uploads, all four required filenames, and the final failure fan-in are asserted by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **The CI contract is documented for future changes.** The rationale and operational flow are recorded in [`docs/oss/ci-pipeline.md`](docs/oss/ci-pipeline.md) and the package coverage guides. ## Testing performed - `pnpm build` — 85 tasks passed - `pnpm test:scripts` — 498 tests passed - `node --test scripts/coverage-config.test.mjs scripts/coverage-report.test.mjs` — 34 tests passed - `pnpm lint:workflows` - `pnpm exec biome check vitest.config.ts scripts/coverage-config.test.mjs package.json turbo.json` - `pnpm exec turbo run build --dry=json` - Parsed `.github/workflows/ci.yml` with the installed `yaml` package - `git diff --check` - Synthetic two-shard Vitest 5 smoke test — generated both expected blob files, merged both source maps, replayed both tests, and passed combined 100% thresholds ## Skill update n/a — internal CI orchestration only; no user-facing CLI, API, configuration, error, or terminology changes. ## Alternatives considered - **Use cache transport:** cache prefix matching restores only one matching entry rather than all shard outputs, which would require four explicit restores. Cache fallback also suggests cross-attempt reuse that GitHub's artifact model intentionally avoids. - **Merge raw JSON manually:** Vitest's blob merger already preserves test failures, project metadata, and Istanbul hit counters, avoiding a custom coverage-merging implementation. - **Apply thresholds in every shard:** each shard sees only partial execution, so this would create false failures and would not represent repository coverage. - **Keep the single runner and increase workers:** package coverage is already worker-capped to protect PGlite/PostgreSQL stability; horizontal runners improve wall time without oversubscribing one machine. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — n/a, this infrastructure change has no Linear ticket and follows the repository's conventional-title precedent. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Package tests now run across four parallel CI shards. * Added coverage report merging for sharded test runs. * Coverage thresholds are applied after all shard results are combined. * Example tests now run as a dedicated CI check. * **Documentation** * Updated testing and CI guides with the new sharded coverage workflow and command. * **Chores** * Excluded Vitest cache files from version control. * Improved CI checks and diagnostics for incomplete or failed test shards. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 11 天前 | |
ci: shard package tests without weakening coverage gates (#30156) ## Linked issue n/a — infrastructure change without a Linear ticket. ## At a glance ```yaml # Package Tests (1/4 ... 4/4) - run: pnpm coverage:packages --reporter=blob --shard=${{ matrix.index }}/4 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # Coverage - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with: pattern: package-coverage-* merge-multiple: true - run: pnpm coverage:packages:merge - run: pnpm coverage:report ``` Package tests now execute on four runners, while a separate `Coverage` job evaluates thresholds once against the combined native Vitest report. `Test Examples` runs concurrently, and a lightweight final `Test` job preserves the required status name. ## Summary The package-test portion of `Test` was the remaining serial CI bottleneck. This change shards that work horizontally while keeping one authoritative coverage gate and the existing required `Test` status context. ## Decision This PR ships three connected CI changes: 1. Run package tests and V8 coverage across four native Vitest shards, each uploading one uniquely named blob artifact. 2. Download and require all four blob reports in a separate `Coverage` fan-in job, merge their coverage counters with Vitest, and only then apply the existing package-level thresholds and warning policy. 3. Run examples concurrently and preserve assertion failures, inert-diff behavior, and the required `Test` check name through a lightweight final gate. ## Reviewer notes - Shards use SHA-pinned `actions/upload-artifact`; `Coverage` uses SHA-pinned `actions/download-artifact` with `pattern: package-coverage-*` and `merge-multiple: true`. Both are GitHub-created actions in the `actions` organization, so the existing GitHub-actions category permits them without individual allow-list entries. - Uploads set `include-hidden-files: true` because Vitest writes blobs below `.vitest/blob`, and `if-no-files-found: error` prevents a shard from silently publishing nothing. - GitHub does not expose artifacts from an earlier workflow attempt to rerun jobs. Use **Re-run all jobs**, not **Re-run failed jobs**; a partial rerun fails safely when `Coverage` verifies the four expected files. - Coverage thresholds and file reporters are deliberately disabled only in partial shard processes. The merge process runs without the shard marker and therefore restores the complete policy. - The stable required status remains `Test`; the four `Package Tests (N/4)` jobs, `Coverage`, and `Test Examples` are implementation details behind its final result. - The hosted four-runner transport can only execute in GitHub Actions. A local two-shard smoke test proved Vitest's blob names, merged counters, and final-only 100% threshold behavior. ## How it fits together 1. [`vitest.config.ts`](vitest.config.ts) recognizes shard collection through `VITEST_COVERAGE_SHARD`, keeps the full include/exclude policy, and suppresses only partial-run thresholds and coverage output. 2. [`.github/workflows/ci.yml`](.github/workflows/ci.yml) runs `vitest --coverage --reporter=blob --shard=N/4` on four PostgreSQL-backed runners. Each shard still reports test failures, uploads exactly one hidden blob file, and explicitly propagates a failing outcome after the upload. 3. `Coverage` downloads all `package-coverage-*` artifacts into `.vitest/blob` and checks for `blob-1-4.json` through `blob-4-4.json` before doing any merge. 4. [`pnpm coverage:packages:merge`](package.json) invokes Vitest's native `--merge-reports` path, which combines Istanbul counters rather than averaging percentages and replays failed tests. 5. The existing [`pnpm coverage:report`](scripts/coverage-report.mjs) attributes merged source entries to packages and enforces their thresholds. `Test Examples` runs concurrently, while the final `Test` job fails if any package shard, coverage, example, or prerequisite job failed. ## Behavior changes & evidence - **Package tests execute across four CI runners instead of one.** The matrix and fan-in are in [`.github/workflows/ci.yml`](.github/workflows/ci.yml), with the expected orchestration locked by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **Coverage gates see the complete combined run.** Shard-aware configuration lives in [`vitest.config.ts`](vitest.config.ts), while the native merge command is declared in [`package.json`](package.json) and existing package aggregation remains in [`scripts/coverage-report.mjs`](scripts/coverage-report.mjs). - **Missing shards, assertion failures, and partial reruns cannot silently pass.** Unique artifact names, hidden-file uploads, all four required filenames, and the final failure fan-in are asserted by [`scripts/coverage-config.test.mjs`](scripts/coverage-config.test.mjs). - **The CI contract is documented for future changes.** The rationale and operational flow are recorded in [`docs/oss/ci-pipeline.md`](docs/oss/ci-pipeline.md) and the package coverage guides. ## Testing performed - `pnpm build` — 85 tasks passed - `pnpm test:scripts` — 498 tests passed - `node --test scripts/coverage-config.test.mjs scripts/coverage-report.test.mjs` — 34 tests passed - `pnpm lint:workflows` - `pnpm exec biome check vitest.config.ts scripts/coverage-config.test.mjs package.json turbo.json` - `pnpm exec turbo run build --dry=json` - Parsed `.github/workflows/ci.yml` with the installed `yaml` package - `git diff --check` - Synthetic two-shard Vitest 5 smoke test — generated both expected blob files, merged both source maps, replayed both tests, and passed combined 100% thresholds ## Skill update n/a — internal CI orchestration only; no user-facing CLI, API, configuration, error, or terminology changes. ## Alternatives considered - **Use cache transport:** cache prefix matching restores only one matching entry rather than all shard outputs, which would require four explicit restores. Cache fallback also suggests cross-attempt reuse that GitHub's artifact model intentionally avoids. - **Merge raw JSON manually:** Vitest's blob merger already preserves test failures, project metadata, and Istanbul hit counters, avoiding a custom coverage-merging implementation. - **Apply thresholds in every shard:** each shard sees only partial execution, so this would create false failures and would not represent repository coverage. - **Keep the single runner and increase workers:** package coverage is already worker-capped to protect PGlite/PostgreSQL stability; horizontal runners improve wall time without oversubscribing one machine. ## Checklist - [x] All commits are signed off (`git commit -s`) per the DCO. - [x] I read `CONTRIBUTING.md` and the change is scoped to one logical concern. - [x] Tests are updated. - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form — n/a, this infrastructure change has no Linear ticket and follows the repository's conventional-title precedent. - [x] The **Skill update** section is filled in. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Package tests now run across four parallel CI shards. * Added coverage report merging for sharded test runs. * Coverage thresholds are applied after all shard results are combined. * Example tests now run as a dedicated CI check. * **Documentation** * Updated testing and CI guides with the new sharded coverage workflow and command. * **Chores** * Excluded Vitest cache files from version control. * Improved CI checks and diagnostics for incomplete or failed test shards. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Steven McClankerton <tatarintsev@prisma.io> Co-authored-by: Steven McClankerton <tatarintsev@prisma.io> | 11 天前 |
正在寻找 Prisma ORM 7? 它位于本仓库的
v7分支,npm 上的prisma和@prisma/*包也继续从该分支发布。
Prisma Next 目前处于早期访问阶段,我们正在社区的共同参与下公开构建。随着您的反馈不断塑造 API 的形态,相关接口仍会持续演进,因此我们暂不建议将其用于生产环境。欢迎加入我们:给仓库点个 Star,在 X 上关注 @prisma,或通过 Prisma 博客了解最新动态。
Prisma Next 是 Prisma ORM 的 TypeScript 重写版本,旨在默认提供可扩展、可组合且对 AI 代理友好的特性。阅读完整公告:Prisma ORM 的下一次演进。
前提条件
- Node.js 24 或更高版本
- 一个包管理器(
npm、pnpm或yarn)
快速开始
1. 搭建新项目
交互式脚手架工具会帮您选择一个 JavaScript 框架(Next.js、Vite、Hono 等),并将 Prisma Next 与您选择的数据库(PostgreSQL 或 MongoDB)进行集成:
npm create prisma@next
最终,你将得到一个可运行的应用程序、一份入门合约,并且代理技能已注册完毕。
2. 或者,将 Prisma Next 添加至现有项目
在项目根目录下运行以下命令:
npx @prisma/cli@next orm init
prisma orm init 会生成 prisma.config.ts,在 src/prisma/ 下搭建一个起始契约和 db.ts,安装运行时,输出契约,并注册代理技能。它不会改动你的框架或构建配置。
3. 让 AI 代理帮你搞定 Prisma Next 的一切
两种安装方式都会在项目根目录留下一份顶层的 prisma-next.md 入门指南,供任何代理优先阅读。init 还会在每个工作流的两个位置额外生成一份 SKILL.md,以便不同的代理运行时能在各自预期的路径下找到它们:
.claude/skills/<skill-name>/SKILL.md— 供 Claude Code 使用.agents/skills/<skill-name>/SKILL.md— 适用于 Cursor、Copilot Agent 及其他运行时的通用位置
项目根目录下的 skills-lock.json 会跟踪已安装的技能版本。当你的提示词匹配时,编辑器的 AI 助手会自动加载对应的技能。
你只需要描述你的需求。例如:
"添加一个与
users关联的posts模型,然后写一个查询,加载每个用户最近的三篇文章。"
代理会加载 prisma-8 技能,打开其契约和查询参考,然后端到端地完成整个改动。
完整的技能目录及每个技能的覆盖范围,请参阅 skills/README.md。
发现了 Bug、缺少某个功能,或者有问题想咨询团队?
问问你的代理即可。prisma-8 技能的反馈流程会帮你起草一份结构化的 GitHub Issue,或者提供一个 Prisma Discord 链接用于实时问答。你可以在提交之前进行审查和确认。
给扩展开发者的说明
Prisma Next 的核心非常精简。其周边的一切,包括 Postgres 支持本身,都构建在同样对任何开发者开放的公共 SPI 之上。如果你一直想将自己的工具、数据库或库与 Prisma 集成,这就是入口。
目前已经有一些扩展在发布中:
@internal/extension-pgvector:用于语义搜索的向量列和相似度运算符。@internal/extension-paradedb:支持多种分词器的类型化 BM25 索引,用于全文搜索。@internal/extension-postgis:地理空间类型和查询。@cipherstash/prisma-next:可搜索加密和数据级访问控制。
想发布自己的扩展?编写 Prisma Next 扩展 这篇博客详细介绍了 SPI、你的扩展可以接入的层次,以及团队如何在 Prisma Next 目录中推荐新扩展。
支持的数据库
Prisma 8 将 PostgreSQL 提升至全面可用(GA) 阶段——目前仅此一项:
- PostgreSQL — 首要目标;在 Prisma 8 中达到全面可用
- MongoDB — 早期访问;验证了框架在 SQL 之外同样适用
- SQLite — 目前作为概念验证
MySQL 将在后续版本中支持。请参阅 路线图 了解在 8.0.0-rc.1 发布前需要完成的事项。
参与贡献
请参阅 CONTRIBUTING.md 了解环境搭建、命令、DCO 签署及 PR 要求。对于实质性改动,请先提交 issue,以便我们在您投入开发时间之前提供方向性反馈。
安全问题:请遵循 SECURITY.md 中的私有漏洞报告流程,请勿将其作为公开 issue 提交。
社区
使用 Prisma Next 构建了有趣的项目?在 X 上标记 @prisma。优秀的社区作品将获得致谢并在此展示链接。
- Discord:在 Discord 的
prisma-next频道与我们交流 - X:@prisma
- 博客:prisma.io/blog
许可证
Apache 2.0。详情请参阅 LICENSE。
项目介绍
下一代ORM,适用于Node.js和TypeScript | 支持PostgreSQL、MySQL、MariaDB、SQL Server、SQLite、MongoDB及CockroachDB【此简介由AI生成】