| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat: support nullable scalar-list elements (#30051) ## Linked issue n/a — operator-approved project without a Linear or GitHub ticket. ## At a glance ```prisma model Post { tags String[] authors String?[] reviewers String[]? editors String?[]? } ``` ```ts const authors = field.text().many({ elementsNullable: true }); ``` The position of `?` now independently controls whether the list itself and each element may be `null`; the TypeScript authoring surface exposes the same distinction through `many({ elementsNullable })`. ## Decision This PR ships nullable scalar-list elements across the shared contract model, SQL/PostgreSQL, and MongoDB. It records element nullability as semantic metadata on `ContractField` and, for native SQL arrays, `StorageColumn`; keeps that meaning separate from explicit `noCheck('elementNotNull')` enforcement waivers; and derives generated types, database checks, BSON validators, runtime codec behavior, ORM mutations, and result shapes from the semantic marker. [ADR 248](docs/architecture%20docs/adrs/ADR%20248%20-%20List%20cardinality%20has%20independent%20container%20and%20element%20nullability.md) records the model and its consequences. ## Reviewer notes - `elementNullable` and `noCheck('elementNotNull')` intentionally mean different things. The former permits `null` in generated element types and makes the check inapplicable; the latter leaves strict element types intact while waiving database enforcement. - Nullable elements do not inject an automatic `noCheck`. PostgreSQL check derivation reads `StorageColumn.many.elementNullable` and omits the candidate directly. - `StorageColumn.many.elementNullable` is required because SQL builder and emitter type paths consume storage columns without consulting the domain field. It is not projected into schema IR; migrations observe the resulting check set. - `many({ elementsNullable })` accepts literal `true` or `false`. Widened booleans and empty option objects are rejected because they cannot produce a sound static result type. - The parser formatter and the semantic printer preserve all four PSL forms. The semantic printer is updated to preserve nullable elements in the contract-print surface added on main. ## How it fits together 1. The PSL parser and typed AST distinguish `?` before `[]` from the trailing `?`, and `ContractField.many: false | { elementNullable: boolean }` carries the new semantic axis through validation and canonicalization. 2. Type generation applies element `| null` before wrapping the value in `ReadonlyArray`, then applies whole-field `| null` independently. SQL and Mongo TypeScript builders expose the same matrix through `many({ elementsNullable })`. 3. Native SQL arrays copy the semantic marker onto `StorageColumn`. PostgreSQL derives `elementNotNull` only for strict-element arrays, while explicit `noCheck` filtering remains a separate later step. Enum membership removes `NULL` before testing containment. 4. Mongo BSON item schemas admit `null` only when declared. ORM mutation and filter paths preserve bare `null` elements while codec-wrapping non-null values, and contract-derived result shapes carry the element flag into decoding. 5. Focused lifecycle and integration tests prove PostgreSQL check add/drop behavior, nullable defaults, Mongo enum/value-object handling, codec bypass, and exact result metadata. ## Behavior changes & evidence - **All four list-nullability cells parse, round-trip, and generate exact TypeScript shapes.** The parser and contract marker live in [parse.ts](packages/1-framework/2-authoring/psl-parser/src/parse.ts), [type-annotation.ts](packages/1-framework/2-authoring/psl-parser/src/syntax/ast/type-annotation.ts), and [domain-types.ts](packages/1-framework/0-foundation/contract/src/domain-types.ts). Evidence includes [nullable-list-round-trip.test.ts](packages/1-framework/2-authoring/psl-parser/test/format/nullable-list-round-trip.test.ts) and [domain-type-generation.test.ts](packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts). - **SQL authoring and PostgreSQL enforcement distinguish semantic nullability from explicit waivers.** The storage marker and authoring surface are implemented in [storage-column.ts](packages/2-sql/1-core/contract/src/ir/storage-column.ts), [contract-dsl.ts](packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts), and [check-expressions.ts](packages/3-targets/3-targets/postgres/src/core/check-expressions.ts). Evidence includes [check-constraint.authoring.test.ts](packages/2-sql/2-authoring/contract-ts/test/check-constraint.authoring.test.ts) and [check-lifecycle-e2e.integration.test.ts](packages/3-targets/6-adapters/postgres/test/migrations/check-lifecycle-e2e.integration.test.ts). - **Mongo validates, writes, and reads nullable elements without passing `null` through element codecs.** BSON derivation, mutation wrapping, and result metadata live in [derive-json-schema.ts](packages/2-mongo-family/2-authoring/contract-psl/src/derive-json-schema.ts), [collection.ts](packages/2-mongo-family/5-query-builders/orm/src/collection.ts), and [result-shape.ts](packages/2-mongo-family/5-query-builders/query-builder/src/result-shape.ts). Evidence includes [interpreter.test.ts](packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.test.ts), [collection.test.ts](packages/2-mongo-family/5-query-builders/orm/test/collection.test.ts), and [result-shape.test.ts](packages/2-mongo-family/5-query-builders/query-builder/test/result-shape.test.ts). ## Compatibility / migration / risk `ContractField.many` is optional: omitted or `false` means scalar; lists use `many: { elementNullable: false | true }`. Generated scalar domain-field declarations omit `many`. SQL storage-column cardinality remains required and unchanged. Serialized model and value-object fields may omit `many`; deserialization normalizes omission to `false`, and canonical emission omits that scalar default. Explicit malformed values remain rejected, and list descriptors preserve `elementNullable: false`. Native SQL storage uses the same nested representation in memory. Existing boolean-list JSON must be regenerated or migrated; scalar domain JSON remains compatible. Existing strict-list database constraints remain unchanged. Changing a PostgreSQL field from strict to nullable elements drops the generated check; reversing it restores the check and can fail if existing arrays contain NULL elements. SQLite still has no scalar-list capability. ## Rebase validation Follow-up `2a68294332` limits optionality to `ContractField` and updates its direct consumers and generated domain declarations; storage-column types and emission are unchanged. Framework emitter (239), SQL emitter (192), PostgreSQL printer (127), domain validation (43), and focused Mongo tests pass, as do affected package typechecks. A fresh scalar-list contract emission exactly matches the updated declaration fixture. Follow-up `7b9cf2992b` removes the domain cardinality path-pattern exceptions and defaults omitted serialized `many` to `false` in SQL and Mongo. Focused package suites, authoring parity (72 tests), and all five affected package typechecks pass. Canonical fixture regeneration completed; contract JSON changes only remove scalar domain `many: false`, with hashes and list descriptors unchanged. Latest rebase: onto `main` at `9b5e188bcd`, pushed at `434c300640`. Main advanced during the initial rebase validation. The final replay preserves its canonical date/time-default handling, updates new temporal fixtures to nested cardinality, and bypasses scalar canonicalization for null defaults/elements. Focused canonicalization/planner tests (20), temporal integration/parity tests (45), and canonical-form CLI journey tests (4) pass; affected package typechecks pass. The full build passed after conflict resolution. Earlier broad validation below predates these final focused fixes. - Full workspace build: 87/87 tasks passed (reduced concurrency and increased Node heap). - Package typecheck, including integration and E2E: 156/156 tasks passed. - Package lint: 89/89 tasks passed; dependency checks and `git diff --check` passed. - SQL and Mongo package suites passed in package-local runs; PostgreSQL adapter: 991 passed, 3 expected failures, 1 skipped. - Emitter: 238 passed. Language server: 642 passed. - CLI: 1,759 tests passed in a local-filesystem copy; the remaining Git-dependent test passed in the checkout. The copy avoids a reproduced FUSE file-copy error. - Integration: final full run had 2,765 passing tests and one stale historical-fixture hash failure. Recomputed the hash using the contract serializer and verified that last roundtrip test passes. The prior contract-import, CLI, and scalar-list regressions also pass. - E2E: 123 tests passed. - Authoring regeneration: 68 tests passed; integration fixture emission completed. Validation limits: aggregate root package runs timed out; three packaging suites are blocked by pnpm's provenance-downgrade rejection of `@vercel/detect-agent@1.2.5` (security checks were not disabled). Full example validation also requires environment setup, including an available Prisma 7 schema engine on Nix and Cloudflare database configuration. `fixtures:check` timed out during its authoring stage; it is not reported as passing. ## Skill update This breaking cardinality representation now includes upgrade fragments for both affected audiences: - [Application upgrade instructions](upgrade-instructions/pending/nullable-scalar-lists/app/instructions.md) - [Extension upgrade instructions](upgrade-instructions/pending/nullable-scalar-lists/extension/instructions.md) The instructions cover re-emission, explicit scalar/list metadata, native SQL versus JSON-backed lists, enforcement-waiver semantics, and consistent historical snapshot/reference updates. ## CI and review follow-up Follow-up commits through `740bcbe027` regenerate the 28 migration snapshot artifacts reported by CI and add the missing upgrade declarations. `pnpm fixtures:check` and `pnpm check:upgrade-coverage --mode pr --prev origin/main --head HEAD` now pass locally. Review fixes include matching Mongo list fields before scalar fields, rejecting unknown list-metadata properties in runtime and generated SQL schemas, preserving explicit malformed cardinality in test fixtures, and keeping raw columns with omitted cardinality scalar. Regression tests passed: Mongo query builder 442, SQL contract 400, SQL authoring 549, SQL emitter 192, SQL family 403, and the focused PostgreSQL check-lifecycle suite 22. Downstream Mongo ORM typechecking and dependency checks passed. The three review threads were subsequently verified and resolved without posting replies. ## Alternatives considered - **Infer nullable elements from a missing `elementNotNull` check.** Rejected because checks may be explicitly waived or absent from external databases; enforcement state is not a reliable type declaration. - **Represent nullable elements as automatic `noCheck('elementNotNull')`.** Rejected because an enforcement waiver deliberately leaves strict declared types unchanged and cannot carry the semantic information SQL typing needs. - **Keep the marker only on `ContractField`.** Rejected because native SQL storage consumers infer element types without consulting the domain field. - **Add the marker to schema IR.** Rejected because the physical migration observable is already the derived check set; a second schema-IR signal could disagree with it. ## 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 — explicit operator exception: this project has no ticket. - [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 independent nullability controls for collections and their elements. - Added syntax and contract-builder options for nullable list elements. - Propagated element nullability through generated types, defaults, schemas, codecs, and database mappings. - Added support for nullable elements in SQL and MongoDB arrays, including enum and value-object lists. - **Bug Fixes** - Improved validation and diagnostics for invalid nullability combinations and malformed type annotations. - Preserved `null` values during MongoDB queries and updates. - Prevented invalid non-null constraints for nullable collection elements. <!-- 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> | 3 天前 | |
feat: support nullable scalar-list elements (#30051) ## Linked issue n/a — operator-approved project without a Linear or GitHub ticket. ## At a glance ```prisma model Post { tags String[] authors String?[] reviewers String[]? editors String?[]? } ``` ```ts const authors = field.text().many({ elementsNullable: true }); ``` The position of `?` now independently controls whether the list itself and each element may be `null`; the TypeScript authoring surface exposes the same distinction through `many({ elementsNullable })`. ## Decision This PR ships nullable scalar-list elements across the shared contract model, SQL/PostgreSQL, and MongoDB. It records element nullability as semantic metadata on `ContractField` and, for native SQL arrays, `StorageColumn`; keeps that meaning separate from explicit `noCheck('elementNotNull')` enforcement waivers; and derives generated types, database checks, BSON validators, runtime codec behavior, ORM mutations, and result shapes from the semantic marker. [ADR 248](docs/architecture%20docs/adrs/ADR%20248%20-%20List%20cardinality%20has%20independent%20container%20and%20element%20nullability.md) records the model and its consequences. ## Reviewer notes - `elementNullable` and `noCheck('elementNotNull')` intentionally mean different things. The former permits `null` in generated element types and makes the check inapplicable; the latter leaves strict element types intact while waiving database enforcement. - Nullable elements do not inject an automatic `noCheck`. PostgreSQL check derivation reads `StorageColumn.many.elementNullable` and omits the candidate directly. - `StorageColumn.many.elementNullable` is required because SQL builder and emitter type paths consume storage columns without consulting the domain field. It is not projected into schema IR; migrations observe the resulting check set. - `many({ elementsNullable })` accepts literal `true` or `false`. Widened booleans and empty option objects are rejected because they cannot produce a sound static result type. - The parser formatter and the semantic printer preserve all four PSL forms. The semantic printer is updated to preserve nullable elements in the contract-print surface added on main. ## How it fits together 1. The PSL parser and typed AST distinguish `?` before `[]` from the trailing `?`, and `ContractField.many: false | { elementNullable: boolean }` carries the new semantic axis through validation and canonicalization. 2. Type generation applies element `| null` before wrapping the value in `ReadonlyArray`, then applies whole-field `| null` independently. SQL and Mongo TypeScript builders expose the same matrix through `many({ elementsNullable })`. 3. Native SQL arrays copy the semantic marker onto `StorageColumn`. PostgreSQL derives `elementNotNull` only for strict-element arrays, while explicit `noCheck` filtering remains a separate later step. Enum membership removes `NULL` before testing containment. 4. Mongo BSON item schemas admit `null` only when declared. ORM mutation and filter paths preserve bare `null` elements while codec-wrapping non-null values, and contract-derived result shapes carry the element flag into decoding. 5. Focused lifecycle and integration tests prove PostgreSQL check add/drop behavior, nullable defaults, Mongo enum/value-object handling, codec bypass, and exact result metadata. ## Behavior changes & evidence - **All four list-nullability cells parse, round-trip, and generate exact TypeScript shapes.** The parser and contract marker live in [parse.ts](packages/1-framework/2-authoring/psl-parser/src/parse.ts), [type-annotation.ts](packages/1-framework/2-authoring/psl-parser/src/syntax/ast/type-annotation.ts), and [domain-types.ts](packages/1-framework/0-foundation/contract/src/domain-types.ts). Evidence includes [nullable-list-round-trip.test.ts](packages/1-framework/2-authoring/psl-parser/test/format/nullable-list-round-trip.test.ts) and [domain-type-generation.test.ts](packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts). - **SQL authoring and PostgreSQL enforcement distinguish semantic nullability from explicit waivers.** The storage marker and authoring surface are implemented in [storage-column.ts](packages/2-sql/1-core/contract/src/ir/storage-column.ts), [contract-dsl.ts](packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts), and [check-expressions.ts](packages/3-targets/3-targets/postgres/src/core/check-expressions.ts). Evidence includes [check-constraint.authoring.test.ts](packages/2-sql/2-authoring/contract-ts/test/check-constraint.authoring.test.ts) and [check-lifecycle-e2e.integration.test.ts](packages/3-targets/6-adapters/postgres/test/migrations/check-lifecycle-e2e.integration.test.ts). - **Mongo validates, writes, and reads nullable elements without passing `null` through element codecs.** BSON derivation, mutation wrapping, and result metadata live in [derive-json-schema.ts](packages/2-mongo-family/2-authoring/contract-psl/src/derive-json-schema.ts), [collection.ts](packages/2-mongo-family/5-query-builders/orm/src/collection.ts), and [result-shape.ts](packages/2-mongo-family/5-query-builders/query-builder/src/result-shape.ts). Evidence includes [interpreter.test.ts](packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.test.ts), [collection.test.ts](packages/2-mongo-family/5-query-builders/orm/test/collection.test.ts), and [result-shape.test.ts](packages/2-mongo-family/5-query-builders/query-builder/test/result-shape.test.ts). ## Compatibility / migration / risk `ContractField.many` is optional: omitted or `false` means scalar; lists use `many: { elementNullable: false | true }`. Generated scalar domain-field declarations omit `many`. SQL storage-column cardinality remains required and unchanged. Serialized model and value-object fields may omit `many`; deserialization normalizes omission to `false`, and canonical emission omits that scalar default. Explicit malformed values remain rejected, and list descriptors preserve `elementNullable: false`. Native SQL storage uses the same nested representation in memory. Existing boolean-list JSON must be regenerated or migrated; scalar domain JSON remains compatible. Existing strict-list database constraints remain unchanged. Changing a PostgreSQL field from strict to nullable elements drops the generated check; reversing it restores the check and can fail if existing arrays contain NULL elements. SQLite still has no scalar-list capability. ## Rebase validation Follow-up `2a68294332` limits optionality to `ContractField` and updates its direct consumers and generated domain declarations; storage-column types and emission are unchanged. Framework emitter (239), SQL emitter (192), PostgreSQL printer (127), domain validation (43), and focused Mongo tests pass, as do affected package typechecks. A fresh scalar-list contract emission exactly matches the updated declaration fixture. Follow-up `7b9cf2992b` removes the domain cardinality path-pattern exceptions and defaults omitted serialized `many` to `false` in SQL and Mongo. Focused package suites, authoring parity (72 tests), and all five affected package typechecks pass. Canonical fixture regeneration completed; contract JSON changes only remove scalar domain `many: false`, with hashes and list descriptors unchanged. Latest rebase: onto `main` at `9b5e188bcd`, pushed at `434c300640`. Main advanced during the initial rebase validation. The final replay preserves its canonical date/time-default handling, updates new temporal fixtures to nested cardinality, and bypasses scalar canonicalization for null defaults/elements. Focused canonicalization/planner tests (20), temporal integration/parity tests (45), and canonical-form CLI journey tests (4) pass; affected package typechecks pass. The full build passed after conflict resolution. Earlier broad validation below predates these final focused fixes. - Full workspace build: 87/87 tasks passed (reduced concurrency and increased Node heap). - Package typecheck, including integration and E2E: 156/156 tasks passed. - Package lint: 89/89 tasks passed; dependency checks and `git diff --check` passed. - SQL and Mongo package suites passed in package-local runs; PostgreSQL adapter: 991 passed, 3 expected failures, 1 skipped. - Emitter: 238 passed. Language server: 642 passed. - CLI: 1,759 tests passed in a local-filesystem copy; the remaining Git-dependent test passed in the checkout. The copy avoids a reproduced FUSE file-copy error. - Integration: final full run had 2,765 passing tests and one stale historical-fixture hash failure. Recomputed the hash using the contract serializer and verified that last roundtrip test passes. The prior contract-import, CLI, and scalar-list regressions also pass. - E2E: 123 tests passed. - Authoring regeneration: 68 tests passed; integration fixture emission completed. Validation limits: aggregate root package runs timed out; three packaging suites are blocked by pnpm's provenance-downgrade rejection of `@vercel/detect-agent@1.2.5` (security checks were not disabled). Full example validation also requires environment setup, including an available Prisma 7 schema engine on Nix and Cloudflare database configuration. `fixtures:check` timed out during its authoring stage; it is not reported as passing. ## Skill update This breaking cardinality representation now includes upgrade fragments for both affected audiences: - [Application upgrade instructions](upgrade-instructions/pending/nullable-scalar-lists/app/instructions.md) - [Extension upgrade instructions](upgrade-instructions/pending/nullable-scalar-lists/extension/instructions.md) The instructions cover re-emission, explicit scalar/list metadata, native SQL versus JSON-backed lists, enforcement-waiver semantics, and consistent historical snapshot/reference updates. ## CI and review follow-up Follow-up commits through `740bcbe027` regenerate the 28 migration snapshot artifacts reported by CI and add the missing upgrade declarations. `pnpm fixtures:check` and `pnpm check:upgrade-coverage --mode pr --prev origin/main --head HEAD` now pass locally. Review fixes include matching Mongo list fields before scalar fields, rejecting unknown list-metadata properties in runtime and generated SQL schemas, preserving explicit malformed cardinality in test fixtures, and keeping raw columns with omitted cardinality scalar. Regression tests passed: Mongo query builder 442, SQL contract 400, SQL authoring 549, SQL emitter 192, SQL family 403, and the focused PostgreSQL check-lifecycle suite 22. Downstream Mongo ORM typechecking and dependency checks passed. The three review threads were subsequently verified and resolved without posting replies. ## Alternatives considered - **Infer nullable elements from a missing `elementNotNull` check.** Rejected because checks may be explicitly waived or absent from external databases; enforcement state is not a reliable type declaration. - **Represent nullable elements as automatic `noCheck('elementNotNull')`.** Rejected because an enforcement waiver deliberately leaves strict declared types unchanged and cannot carry the semantic information SQL typing needs. - **Keep the marker only on `ContractField`.** Rejected because native SQL storage consumers infer element types without consulting the domain field. - **Add the marker to schema IR.** Rejected because the physical migration observable is already the derived check set; a second schema-IR signal could disagree with it. ## 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 — explicit operator exception: this project has no ticket. - [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 independent nullability controls for collections and their elements. - Added syntax and contract-builder options for nullable list elements. - Propagated element nullability through generated types, defaults, schemas, codecs, and database mappings. - Added support for nullable elements in SQL and MongoDB arrays, including enum and value-object lists. - **Bug Fixes** - Improved validation and diagnostics for invalid nullability combinations and malformed type annotations. - Preserved `null` values during MongoDB queries and updates. - Prevented invalid non-null constraints for nullable collection elements. <!-- 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> | 3 天前 | |
docs: rewrite README for Prisma 8, fix orm init dist-tag, sweep "Prisma Next" prose (#30248) ## Linked issue n/a — no Linear ticket. Follow-up to the README banner swap in #30225. ## At a glance The README's getting-started commands, before and after, checked against [prisma.io/docs/getting-started](https://www.prisma.io/docs/getting-started): ```bash # before npm create prisma@next npx @prisma/cli@next orm init # after npm create prisma npx prisma orm init npx prisma skills sync ``` The `prisma` package has no `next` dist-tag any more (`latest` is `8.0.0-rc.13`, `prev` is `7.10.0`), so the old commands no longer resolve. ## Summary The README still introduced the product as "Prisma Next" in Early Access, pointed at the removed `next` dist-tag, listed extensions by their `@internal/*` workspace names, and linked to `prisma/prisma`. The rest of the repo had about a thousand prose mentions of the working name. This PR fixes all of it and one real bug the sweep turned up. ## Decision Five commits, each reviewable on its own (the fifth only records the sweep against the in-flight upgrade-instruction files for the coverage check): 1. **Rewrite the README against the live docs.** Every instruction in it now matches the getting-started, quickstart, `orm init`, `skills`, and extensions pages in prisma/web. 2. **Fix `orm init` to install `prisma@latest`.** The CLI added `prisma@next` as a dev dependency. That tag no longer exists on npm, so `orm init` fails at the install step for anyone running it today. The engine fallback moves from `@prisma/cli-engine@next` (0.2.3, stale) to `@latest` (0.3.0). 3. **Replace "Prisma Next" with "Prisma 8" in prose repo-wide.** Docs, doc comments, READMEs, package descriptions, skill references, and user-facing strings. 4. **Carry the pnpm trust-policy exemptions into the tarball smoke tests.** The scratch installs those tests run trip a trust-downgrade check on `undici-types@6.21.0` (no provenance, while 6.13.0 and 6.18.2 had it). The repo already exempts it for the workspace install; the test kit now restates `trustPolicy` and `trustPolicyExclude` in the scratch project the way it restates the release-age settings. Reproduced on main with a fresh metadata cache, so this is a pre-existing failure that any run without cached metadata hits. ## Reviewer notes - **Rebased on #30229.** That PR's release-candidate banner and its `scorecard.md` link replace the roadmap reference in the README, and `ROADMAP.md` stays deleted. The prose sweep re-applied cleanly on top of its CONTRIBUTING, SECURITY, and governance edits. - **Dated records keep the old name**, matching the allowances `scripts/lint-legacy-name.mjs` already defines for the `prisma-next` identifier: `CHANGELOG.md`, `docs/releases/`, the ADRs, `projects/`, and `drive/`. Rewriting those would misreport what was true at the time, and a mechanical pass produced sentences like "Prisma Next becomes Prisma 8" turning into "Prisma 8 becomes Prisma 8". - **Identifiers are untouched.** `prisma-next` package names, paths, env vars (`PRISMA_NEXT_*`), `PrismaNext*` types, the `images/prisma-next.png` file, and the `prisma-next.md` primer (the docs still call it that) are all unchanged. Renaming any of those is a behaviour change with an upgrade path, not a docs fix. - **The sweep is mechanical.** The third commit is a `sed` of `Prisma Next` and `Prisma-next` to `Prisma 8` over 345 files. Three sentences that became self-referential (`ROADMAP.md`, `ROADMAP.html`, `scorecard.md`) were rewritten by hand. - **`README.md` supported-databases section** now says PostgreSQL and MongoDB are first-class and SQLite is planned next, which is what [/docs/orm](https://www.prisma.io/docs/orm) says. The previous text referenced work "before the 8.0.0-rc.1 release". - **Discord channel name dropped.** The README linked to a `prisma-next` channel I could not verify; it now links to Discord generically. ## Behavior changes & evidence - **`orm init` installs `prisma@latest`** instead of `prisma@next`, and falls back to `@prisma/cli-engine@latest` when the manifest does not pin the engine. [packages/1-framework/3-tooling/cli/src/orm/init.ts](packages/1-framework/3-tooling/cli/src/orm/init.ts), [packages/1-framework/3-tooling/cli/src/orm/init-packages.ts](packages/1-framework/3-tooling/cli/src/orm/init-packages.ts). Evidence: [packages/1-framework/3-tooling/cli/test/orm/init-install.test.ts](packages/1-framework/3-tooling/cli/test/orm/init-install.test.ts), [test/integration/test/cli.init-skill-distribution.integration.test.ts](test/integration/test/cli.init-skill-distribution.integration.test.ts). - **Scaffolded quick-reference notes and the skill quickstart** tell users to run `prisma@latest orm init`. [packages/1-framework/3-tooling/cli/src/commands/init/templates/quick-reference-postgres.md](packages/1-framework/3-tooling/cli/src/commands/init/templates/quick-reference-postgres.md), [skills/prisma-8/references/quickstart.md](skills/prisma-8/references/quickstart.md). Evidence: [packages/1-framework/3-tooling/cli/test/commands/init/__snapshots__/templates.test.ts.snap](packages/1-framework/3-tooling/cli/test/commands/init/__snapshots__/templates.test.ts.snap). - **No other runtime change.** Every other edit is prose in docs, comments, `package.json` descriptions, and `//` comments in test fixture schemas, which the emitter drops. ## Testing performed - `pnpm test` in `packages/1-framework/3-tooling/cli`: 115 files, 1437 tests passed - `pnpm lint:legacy-name`, `pnpm lint:docs`, `pnpm lint:skills`, `pnpm lint:rules:footprint`, `pnpm lint:manifests`: all pass (the `errors` README warning is pre-existing) - `pnpm fixtures:check` could not run in this worktree because the examples' `prisma` binary is not installed. The only schema edits are `//` comments, which do not reach the emitted contract. ## Skill update `skills/prisma-8/references/quickstart.md` is updated in the second commit: its `orm init` commands moved from `@prisma/cli@next` to `prisma@latest`, the same change the README makes. ## Alternatives considered - **Rename the identifiers too** (`prisma-next.md`, `PRISMA_NEXT_*`, `PrismaNext*` types, the image file). Each is a user-visible surface with an upgrade path, and the docs still name `prisma-next.md`. Left for a deliberate rename with upgrade instructions. - **Sweep the ADRs, changelog, and project write-ups as well.** The repo's own legacy-name lint exempts them as dated records, and the mechanical pass mangled sentences that describe the rename itself. Following the existing policy keeps the diff honest. - **Keep `@latest` on the commands, as the docs pages write them.** The v8 line is `latest` now, so the tag adds nothing; the README uses the bare `npm create prisma` and `npx prisma …` forms. ## 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 CLI install-command tests and snapshots). - [ ] The PR title is in `TML-NNNN: <sentence-case title>` form. No Linear ticket exists for this change. - [x] The **Skill update** section above is filled in. ## Notes for the reviewer The first two commits are small and worth reading line by line. The third is large but uniform; spot-check a few files rather than reading all 345. 🤖 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> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> | 23 天前 | |
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> | 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> | 1 个月前 | |
TML-3296: sql is the tag of the SQL family's data type sql/expression (#30534) ## Linked issue Refs [TML-3296](https://linear.app/prisma-company/issue/TML-3296). First slice of the Linear project [SQL expression literals](https://linear.app/prisma-company/project/sql-expression-literals-c8a6659e7f4c); decision ticket [TML-3282](https://linear.app/prisma-company/issue/TML-3282). Follow-up slices: TML-3367, TML-3288, TML-3289. ## Summary The `sql` tag in PSL used to be a special case that bypassed the data type rule every other written value follows. This PR makes it the tag of a data type, `sql/expression`, owned and registered by the SQL family, so that later slices can give index predicates, check constraints and policies the same type and raw SQL is written one way everywhere. ## Skill update No skill change. The written form users see, `` @default(sql`...`) ``, is unchanged. The two upgrade fragments under `upgrade-instructions/pending/sql-is-a-data-type/` record the removed prefixed tags, the renamed diagnostic codes and the removed extension-author API; the release process folds them into the `prisma-8` upgrade skill. ## At a glance ```prisma model Post { id String @id @default(sql`gen_random_uuid()`) createdAt DateTime @default(sql`(now() + interval '1 hour')`) tags String[] @default(sql`'{}'::text[]`) } ``` These three defaults emit exactly the same `contract.json` as before. What changed is what the `sql` tag is. Before this PR it was a special "lowering entry": a tag that named no data type and turned its own text into a default expression. Now `sql` is the tag of a data type, `sql/expression`, defined once in `packages/2-sql/1-core/contract/src/sql-expression.ts`: ```ts export const SQL_EXPRESSION_DATA_TYPE_ID: DataTypeId = dataTypeId('sql/expression'); export const sqlExpressionDataType: DataType = dataType(SQL_EXPRESSION_DATA_TYPE_ID, {}); export const sqlExpressionAuthoringEntry: DataTypeAuthoringEntry = { written: { kind: 'tag', tag: 'sql', parse: (text) => text }, print: (value) => sqlTextFromCanonical(value), documentation: "A SQL expression in the target database's language. Prisma passes it to the database unchanged.", }; ``` ## Decision This PR ships three things. 1. **`sql/expression` is a data type, and the SQL family owns it.** The family descriptor registers the type and its authoring entry, so both SQL targets get the same one and a new SQL target has nothing to remember. The type declares no casts, and the family refuses any stack in which another data type declares a cast from it. [ADR 254](docs/architecture%20docs/adrs/ADR%20254%20-%20Data%20types%20and%20casts.md) records the rule; [ADR 129](docs/architecture%20docs/adrs/ADR%20129%20-%20Template-Tagged%20Literals%20for%20Extensions.md) is rewritten around "the tag names the data type of the text". 2. **The framework loses the lowering-entry kind.** Every entry in `authoring.dataTypes` is a `DataTypeAuthoringEntry` keyed by a registered data type id. The prefixed tags `pg.sql` and `sqlite.sql`, which each adapter registered as aliases, are gone. 3. **`@default` reads a `sql` literal as a value of `sql/expression`** and keeps its own checks on the SQL text (no `now()`, no `;`, no `SELECT`). Refusals that come from the cast rule use the general codes, and one code is renamed so its name says what it means. Later slices in the project make `@@index(where:)`, `@@check(expression:)` and policy predicates take the same type, so that raw SQL is written the same way everywhere in a schema. This slice only changes what `sql` is, so `fixtures:check` shows no `contract.json` change. ## Reviewer notes - **The largest change is in `packages/2-sql/2-authoring/contract-psl/src/psl-column-resolution.ts`.** The old `lowerTaggedLiteral` became `readTaggedLiteral`: it looks the tag up and canonicalizes the body, nothing else. `@default` then reads the value through the same `readValue` path as every other written value and only afterwards branches on whether the value's type is `sql/expression`. - **Codes changed, messages mostly did not.** `PSL_UNKNOWN_DEFAULT_LITERAL_TAG` is `PSL_UNKNOWN_LITERAL_TAG`, `PSL_INVALID_JSON_LITERAL` is folded into `PSL_INVALID_LITERAL`, and `PSL_DEFAULT_TYPE_INCOMPATIBLE` splits into `PSL_VALUE_TYPE_INCOMPATIBLE` (cast rule) and `PSL_DEFAULT_LIST_EXPECTED` (a single value on a list column). The table in the app upgrade fragment lists every row. - **The known-tags order flips.** The family assembles before the target, so the unknown-tag message and the completion list say `sql, json` where they said `json, sql, pg.sql`. - **A `sql` literal inside a list literal** used to have its own message. It is now refused by the cast rule like any other element the column type does not take, and reported at the `@default` attribute. The upgrade fragment says to write the whole list as one `sql` literal. - **The runtime error envelope is now published from the shared `/components` entry** of `@internal/framework-components` (`runtimeError`, `isRuntimeError`, `RuntimeErrorEnvelope`), because shared-plane code in `@internal/sql-contract` cannot import `/runtime`. The `/runtime` entry keeps exporting them too. - **The cast check runs when the SQL family creates its control instance**, which every CLI command goes through before it emits, prints, infers, plans or verifies. The language server does not create one, so it does not report this error. ADR 254 and the error reference say so. - **`contract infer` does not see family data types.** Its default mapping builds from the target's own lists. That is existing behaviour, it changes no output, and it is out of scope here. It is recorded in the project's design so the slice that touches the printer can decide. - **Three tarball tests cannot run on the author's machine** (`all-shells-tarball`, `module-identity`, `cross-shell-tarball`, plus the two `packaging` integration files): `pnpm install` in their scratch project refuses `@vercel/detect-agent@1.2.5` as a "high-risk trust downgrade". That is the registry. CI is the check for them. - **Project files.** `projects/sql-expression-literals/` holds the spec, design, plan, review reports and status of the whole project. It is transient and is deleted at project close-out, once its decisions have moved into the ADRs. ## Behavior changes & evidence - **The family registers `sql/expression`; the targets do not.** `packages/2-sql/9-family/src/core/control-descriptor.ts` carries `dataTypes` and `authoring.dataTypes`; `packages/3-targets/3-targets/postgres/src/core/data-type-entries.ts` and the SQLite twin list only their own types. Evidence: `test/integration/test/authoring/sql-expression-registration.test.ts` assembles a real stack per target (Postgres with all five shipped extension packs) and checks the registered declaration and entry are the family's. - **No data type may cast from `sql/expression`.** `assertNothingCastsFromSqlExpression` in `packages/2-sql/1-core/contract/src/sql-expression.ts`, called by `createSqlFamilyInstance`, throws `CONTRACT.DATA_TYPE_CASTS_FROM_SQL_EXPRESSION`, naming the type and the component that registered it. For that, `ControlStack` gains `declaredDataTypes`, the list `assembleDataTypes` already builds, with each type's contributor. Evidence: `packages/2-sql/9-family/test/control-instance.sql-expression-casts.test.ts`, `packages/3-targets/3-targets/postgres/test/data-types.test.ts`. - **The lowering-entry kind is gone.** `packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts` and `control-stack.ts`: every entry key must be a registered data type id. Evidence: `packages/1-framework/1-core/framework-components/test/data-type-assembly.test.ts`. - **`pg.sql` and `sqlite.sql` are unknown tags.** The adapters' `data-type-authoring.ts` files are deleted; `packages/3-targets/6-adapters/postgres/src/exports/control.ts` registers the target's entries unchanged. Evidence: `packages/2-sql/2-authoring/contract-psl/test/interpreter.defaults.tagged-literal.test.ts` (`Unknown literal tag "pg.sql". Known tags: sql, json.`). - **`@default` reads the `sql/expression` value and keeps its SQL checks.** `packages/2-sql/2-authoring/contract-psl/src/psl-column-resolution.ts`, `data-type-default.ts`. Evidence: `interpreter.defaults.tagged-literal.test.ts` (scalar and list columns, reserved `now()`, unsafe text, `sql` inside a list), `interpreter.defaults.data-types.test.ts` (every refusal kind with its code and whole message). - **`contract infer` prints raw defaults through the one tagged-literal printer**, including the double-quote form for a body holding a backtick. `packages/2-sql/9-family/src/core/psl-build/default-mapping.ts`. Evidence: `packages/2-sql/9-family/test/psl-build/default-mapping.test.ts`, `packages/3-targets/3-targets/postgres/test/psl-infer/inferred-psl.round-trip.test.ts`. - **Docs.** `docs/reference/error-reference.md` has the new codes and drops `PSL_INVALID_JSON_LITERAL`; the contract-psl README and the editor-tooling doc tell the body (what is written between the quotes) from the text (the canonical value). ## Compatibility / migration / risk - **Contracts:** no shape change and no `contract.json` change for any fixture. - **Schema authors:** `pg.sql` and `sqlite.sql` are refused; replace the tag with `sql` and leave the text. No migration follows, because the stored default is the same. - **Extension authors:** `AuthoringDataTypeEntry`, the lowering helpers, `TaggedLiteralValue`, `sqlDefaultLiteralTagEntry` and the adapters' `create*DataTypeEntries` are removed; the extension upgrade fragment has the replacement table. A third-party SQL target registers nothing for `sql`; one that registers `sql/expression` itself fails assembly with `CONTRACT.DATA_TYPE_DUPLICATE`. - **Code that asserts PSL diagnostic codes:** see the table in the app upgrade fragment. ## Testing performed On the final HEAD (a merge of `main` at `d501bfbe69` plus the round 2 review fixes): - `pnpm build`, `pnpm typecheck`, `pnpm lint`, `pnpm lint:deps`, `pnpm lint:casts` (delta 0), `pnpm lint:throws` (delta 0), `pnpm check:error-reference`, `pnpm lint:framework-vocabulary` (272 of 272), `pnpm fixtures:check` (tree clean) - `pnpm check:upgrade-coverage --mode pr` against the merge base - `pnpm test:packages`: 1418 files pass; the 3 tarball files fail on the registry refusal above; 5 files that timed out while another test run shared the machine pass alone - Targeted integration files (`test/authoring/**`, `test/number-defaults/**`, the CLI init-templates e2e and the Mongo insert-many file): 186 tests pass. The full `test:integration` suite runs in CI. - Manual QA: the script in `projects/sql-expression-literals/manual-qa.md` reads each new diagnostic as a user would; the run on this tip is recorded there - Two rounds of architect and code review, reports in `projects/sql-expression-literals/slice-reviews/`; every finding is fixed ## Follow-ups - TML-3367: an argument declares the data type it receives (the `dataTypeValue` building block). - TML-3288: `@@index`, `@@fullTextIndex`, `@@check` and policy predicates take `sql` literals. - TML-3289: the TypeScript builder takes `sql` values. ## Alternatives considered - **Each target registers `sql/expression`.** This is what the first version of the slice did. Rejected because the type is the same on every target and nothing casts from it, so the owner and the registrar should be one component; a new SQL target would otherwise have to remember to register it. - **Keep `pg.sql` and `sqlite.sql` as aliases.** Rejected: an alias is a second way to write the same value, and the stack already names the target. - **Keep a separate lowering-entry kind for tags that produce a default expression.** Rejected: it made `sql` the one written value that bypassed the type rule, which is the exception ADR 254 promised to remove, and it blocked giving index, check and policy predicates the same type. - **Enforce "nothing casts from `sql/expression`" in docs only.** Rejected after the first review: a pack that declared such a cast would turn a `sql` literal into a value of another type with no diagnostic, so the family checks it when it creates its control instance. - **Refuse a `sql` literal inside a list literal with its own message.** Rejected: it is an element the column's type does not take, and the cast rule already says so with the same code as every other such element. ## 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 is in `TML-NNNN: <sentence-case title>` form. - [x] The **Skill update** section above is filled in. ## Notes for the reviewer See Reviewer notes above. Agent: charon-96 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * SQL expressions are represented as a registered data type and can be written with the unprefixed `sql` tag. The `pg.sql` and `sqlite.sql` tags are no longer recognized. * Tagged literals are printed with quoting and escaping that preserves special characters and multiline text. * **Bug Fixes** * Improved diagnostics for unknown tags, incompatible values, invalid literals, and single values supplied where a list is required. * SQL expressions are rejected where data-type casts from SQL expressions are not supported. * **Documentation** * Updated authoring, error-reference, and upgrade guidance for tagged literals, SQL defaults, and diagnostic changes. <!-- 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> | 4 天前 | |
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> | 2 个月前 | |
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> | 2 个月前 | |
TML-3296: sql is the tag of the SQL family's data type sql/expression (#30534) ## Linked issue Refs [TML-3296](https://linear.app/prisma-company/issue/TML-3296). First slice of the Linear project [SQL expression literals](https://linear.app/prisma-company/project/sql-expression-literals-c8a6659e7f4c); decision ticket [TML-3282](https://linear.app/prisma-company/issue/TML-3282). Follow-up slices: TML-3367, TML-3288, TML-3289. ## Summary The `sql` tag in PSL used to be a special case that bypassed the data type rule every other written value follows. This PR makes it the tag of a data type, `sql/expression`, owned and registered by the SQL family, so that later slices can give index predicates, check constraints and policies the same type and raw SQL is written one way everywhere. ## Skill update No skill change. The written form users see, `` @default(sql`...`) ``, is unchanged. The two upgrade fragments under `upgrade-instructions/pending/sql-is-a-data-type/` record the removed prefixed tags, the renamed diagnostic codes and the removed extension-author API; the release process folds them into the `prisma-8` upgrade skill. ## At a glance ```prisma model Post { id String @id @default(sql`gen_random_uuid()`) createdAt DateTime @default(sql`(now() + interval '1 hour')`) tags String[] @default(sql`'{}'::text[]`) } ``` These three defaults emit exactly the same `contract.json` as before. What changed is what the `sql` tag is. Before this PR it was a special "lowering entry": a tag that named no data type and turned its own text into a default expression. Now `sql` is the tag of a data type, `sql/expression`, defined once in `packages/2-sql/1-core/contract/src/sql-expression.ts`: ```ts export const SQL_EXPRESSION_DATA_TYPE_ID: DataTypeId = dataTypeId('sql/expression'); export const sqlExpressionDataType: DataType = dataType(SQL_EXPRESSION_DATA_TYPE_ID, {}); export const sqlExpressionAuthoringEntry: DataTypeAuthoringEntry = { written: { kind: 'tag', tag: 'sql', parse: (text) => text }, print: (value) => sqlTextFromCanonical(value), documentation: "A SQL expression in the target database's language. Prisma passes it to the database unchanged.", }; ``` ## Decision This PR ships three things. 1. **`sql/expression` is a data type, and the SQL family owns it.** The family descriptor registers the type and its authoring entry, so both SQL targets get the same one and a new SQL target has nothing to remember. The type declares no casts, and the family refuses any stack in which another data type declares a cast from it. [ADR 254](docs/architecture%20docs/adrs/ADR%20254%20-%20Data%20types%20and%20casts.md) records the rule; [ADR 129](docs/architecture%20docs/adrs/ADR%20129%20-%20Template-Tagged%20Literals%20for%20Extensions.md) is rewritten around "the tag names the data type of the text". 2. **The framework loses the lowering-entry kind.** Every entry in `authoring.dataTypes` is a `DataTypeAuthoringEntry` keyed by a registered data type id. The prefixed tags `pg.sql` and `sqlite.sql`, which each adapter registered as aliases, are gone. 3. **`@default` reads a `sql` literal as a value of `sql/expression`** and keeps its own checks on the SQL text (no `now()`, no `;`, no `SELECT`). Refusals that come from the cast rule use the general codes, and one code is renamed so its name says what it means. Later slices in the project make `@@index(where:)`, `@@check(expression:)` and policy predicates take the same type, so that raw SQL is written the same way everywhere in a schema. This slice only changes what `sql` is, so `fixtures:check` shows no `contract.json` change. ## Reviewer notes - **The largest change is in `packages/2-sql/2-authoring/contract-psl/src/psl-column-resolution.ts`.** The old `lowerTaggedLiteral` became `readTaggedLiteral`: it looks the tag up and canonicalizes the body, nothing else. `@default` then reads the value through the same `readValue` path as every other written value and only afterwards branches on whether the value's type is `sql/expression`. - **Codes changed, messages mostly did not.** `PSL_UNKNOWN_DEFAULT_LITERAL_TAG` is `PSL_UNKNOWN_LITERAL_TAG`, `PSL_INVALID_JSON_LITERAL` is folded into `PSL_INVALID_LITERAL`, and `PSL_DEFAULT_TYPE_INCOMPATIBLE` splits into `PSL_VALUE_TYPE_INCOMPATIBLE` (cast rule) and `PSL_DEFAULT_LIST_EXPECTED` (a single value on a list column). The table in the app upgrade fragment lists every row. - **The known-tags order flips.** The family assembles before the target, so the unknown-tag message and the completion list say `sql, json` where they said `json, sql, pg.sql`. - **A `sql` literal inside a list literal** used to have its own message. It is now refused by the cast rule like any other element the column type does not take, and reported at the `@default` attribute. The upgrade fragment says to write the whole list as one `sql` literal. - **The runtime error envelope is now published from the shared `/components` entry** of `@internal/framework-components` (`runtimeError`, `isRuntimeError`, `RuntimeErrorEnvelope`), because shared-plane code in `@internal/sql-contract` cannot import `/runtime`. The `/runtime` entry keeps exporting them too. - **The cast check runs when the SQL family creates its control instance**, which every CLI command goes through before it emits, prints, infers, plans or verifies. The language server does not create one, so it does not report this error. ADR 254 and the error reference say so. - **`contract infer` does not see family data types.** Its default mapping builds from the target's own lists. That is existing behaviour, it changes no output, and it is out of scope here. It is recorded in the project's design so the slice that touches the printer can decide. - **Three tarball tests cannot run on the author's machine** (`all-shells-tarball`, `module-identity`, `cross-shell-tarball`, plus the two `packaging` integration files): `pnpm install` in their scratch project refuses `@vercel/detect-agent@1.2.5` as a "high-risk trust downgrade". That is the registry. CI is the check for them. - **Project files.** `projects/sql-expression-literals/` holds the spec, design, plan, review reports and status of the whole project. It is transient and is deleted at project close-out, once its decisions have moved into the ADRs. ## Behavior changes & evidence - **The family registers `sql/expression`; the targets do not.** `packages/2-sql/9-family/src/core/control-descriptor.ts` carries `dataTypes` and `authoring.dataTypes`; `packages/3-targets/3-targets/postgres/src/core/data-type-entries.ts` and the SQLite twin list only their own types. Evidence: `test/integration/test/authoring/sql-expression-registration.test.ts` assembles a real stack per target (Postgres with all five shipped extension packs) and checks the registered declaration and entry are the family's. - **No data type may cast from `sql/expression`.** `assertNothingCastsFromSqlExpression` in `packages/2-sql/1-core/contract/src/sql-expression.ts`, called by `createSqlFamilyInstance`, throws `CONTRACT.DATA_TYPE_CASTS_FROM_SQL_EXPRESSION`, naming the type and the component that registered it. For that, `ControlStack` gains `declaredDataTypes`, the list `assembleDataTypes` already builds, with each type's contributor. Evidence: `packages/2-sql/9-family/test/control-instance.sql-expression-casts.test.ts`, `packages/3-targets/3-targets/postgres/test/data-types.test.ts`. - **The lowering-entry kind is gone.** `packages/1-framework/1-core/framework-components/src/shared/framework-authoring.ts` and `control-stack.ts`: every entry key must be a registered data type id. Evidence: `packages/1-framework/1-core/framework-components/test/data-type-assembly.test.ts`. - **`pg.sql` and `sqlite.sql` are unknown tags.** The adapters' `data-type-authoring.ts` files are deleted; `packages/3-targets/6-adapters/postgres/src/exports/control.ts` registers the target's entries unchanged. Evidence: `packages/2-sql/2-authoring/contract-psl/test/interpreter.defaults.tagged-literal.test.ts` (`Unknown literal tag "pg.sql". Known tags: sql, json.`). - **`@default` reads the `sql/expression` value and keeps its SQL checks.** `packages/2-sql/2-authoring/contract-psl/src/psl-column-resolution.ts`, `data-type-default.ts`. Evidence: `interpreter.defaults.tagged-literal.test.ts` (scalar and list columns, reserved `now()`, unsafe text, `sql` inside a list), `interpreter.defaults.data-types.test.ts` (every refusal kind with its code and whole message). - **`contract infer` prints raw defaults through the one tagged-literal printer**, including the double-quote form for a body holding a backtick. `packages/2-sql/9-family/src/core/psl-build/default-mapping.ts`. Evidence: `packages/2-sql/9-family/test/psl-build/default-mapping.test.ts`, `packages/3-targets/3-targets/postgres/test/psl-infer/inferred-psl.round-trip.test.ts`. - **Docs.** `docs/reference/error-reference.md` has the new codes and drops `PSL_INVALID_JSON_LITERAL`; the contract-psl README and the editor-tooling doc tell the body (what is written between the quotes) from the text (the canonical value). ## Compatibility / migration / risk - **Contracts:** no shape change and no `contract.json` change for any fixture. - **Schema authors:** `pg.sql` and `sqlite.sql` are refused; replace the tag with `sql` and leave the text. No migration follows, because the stored default is the same. - **Extension authors:** `AuthoringDataTypeEntry`, the lowering helpers, `TaggedLiteralValue`, `sqlDefaultLiteralTagEntry` and the adapters' `create*DataTypeEntries` are removed; the extension upgrade fragment has the replacement table. A third-party SQL target registers nothing for `sql`; one that registers `sql/expression` itself fails assembly with `CONTRACT.DATA_TYPE_DUPLICATE`. - **Code that asserts PSL diagnostic codes:** see the table in the app upgrade fragment. ## Testing performed On the final HEAD (a merge of `main` at `d501bfbe69` plus the round 2 review fixes): - `pnpm build`, `pnpm typecheck`, `pnpm lint`, `pnpm lint:deps`, `pnpm lint:casts` (delta 0), `pnpm lint:throws` (delta 0), `pnpm check:error-reference`, `pnpm lint:framework-vocabulary` (272 of 272), `pnpm fixtures:check` (tree clean) - `pnpm check:upgrade-coverage --mode pr` against the merge base - `pnpm test:packages`: 1418 files pass; the 3 tarball files fail on the registry refusal above; 5 files that timed out while another test run shared the machine pass alone - Targeted integration files (`test/authoring/**`, `test/number-defaults/**`, the CLI init-templates e2e and the Mongo insert-many file): 186 tests pass. The full `test:integration` suite runs in CI. - Manual QA: the script in `projects/sql-expression-literals/manual-qa.md` reads each new diagnostic as a user would; the run on this tip is recorded there - Two rounds of architect and code review, reports in `projects/sql-expression-literals/slice-reviews/`; every finding is fixed ## Follow-ups - TML-3367: an argument declares the data type it receives (the `dataTypeValue` building block). - TML-3288: `@@index`, `@@fullTextIndex`, `@@check` and policy predicates take `sql` literals. - TML-3289: the TypeScript builder takes `sql` values. ## Alternatives considered - **Each target registers `sql/expression`.** This is what the first version of the slice did. Rejected because the type is the same on every target and nothing casts from it, so the owner and the registrar should be one component; a new SQL target would otherwise have to remember to register it. - **Keep `pg.sql` and `sqlite.sql` as aliases.** Rejected: an alias is a second way to write the same value, and the stack already names the target. - **Keep a separate lowering-entry kind for tags that produce a default expression.** Rejected: it made `sql` the one written value that bypassed the type rule, which is the exception ADR 254 promised to remove, and it blocked giving index, check and policy predicates the same type. - **Enforce "nothing casts from `sql/expression`" in docs only.** Rejected after the first review: a pack that declared such a cast would turn a `sql` literal into a value of another type with no diagnostic, so the family checks it when it creates its control instance. - **Refuse a `sql` literal inside a list literal with its own message.** Rejected: it is an element the column's type does not take, and the cast rule already says so with the same code as every other such element. ## 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 is in `TML-NNNN: <sentence-case title>` form. - [x] The **Skill update** section above is filled in. ## Notes for the reviewer See Reviewer notes above. Agent: charon-96 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * SQL expressions are represented as a registered data type and can be written with the unprefixed `sql` tag. The `pg.sql` and `sqlite.sql` tags are no longer recognized. * Tagged literals are printed with quoting and escaping that preserves special characters and multiline text. * **Bug Fixes** * Improved diagnostics for unknown tags, incompatible values, invalid literals, and single values supplied where a list is required. * SQL expressions are rejected where data-type casts from SQL expressions are not supported. * **Documentation** * Updated authoring, error-reference, and upgrade guidance for tagged literals, SQL defaults, and diagnostic changes. <!-- 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> | 4 天前 | |
db init, db update and migrate no longer strand the database when contract.d.ts is missing (#30293) ## Linked issue n/a — no Linear ticket; follows up the `db sign` preflight that landed in #30251 (after `db sign`, `migration plan` proposes only the change). ## Skill update n/a — no skill told users to keep `contract.d.ts` next to `contract.json` for the database commands, and the new error code carries its own fix (`prisma contract emit`). ## At a glance Before, with `contract.d.ts` missing, `db init` migrated the database, wrote the marker, then died on the snapshot write: ```text $ prisma db init … Database initialized ENOENT: no such file or directory, open '/app/prisma/contract.d.ts' $ echo $? 2 ``` No ref, no snapshot, and the next `migration plan` started from the wrong place. Now the command refuses before it connects: ```text $ prisma db init ✖ Failed to render contract types (CONTRACT.TYPES_RENDER_FAILED) The types for the contract at /app/prisma/contract.json could not be rendered: … Run prisma contract emit to see why the contract does not emit, fix it, then advance the ref again. ``` The snapshot's `contract.d.ts` is no longer read from disk at all. It is rendered from the `contract.json` being snapshotted: ```ts // packages/1-framework/3-tooling/cli/src/control-api/operations/ref-advancement.ts const rendered = await args.client.renderContractDts({ contract: args.contractJson, resolveImportSpecifier, }); ``` ## Decision This PR ships three things: 1. **`ControlClient.renderContractDts`.** Given a parsed `contract.json`, the client deserializes it through the family and renders `contract.d.ts` through the same `emit()` call `emit` uses, with the import specifiers the caller asks for. A snapshot is that JSON plus these declarations, so whoever writes a snapshot renders them from the JSON it is storing. 2. **Ref advancement renders before the database write.** `preflightRefAdvancement` validates the ref name, builds the project's import-specifier resolver, and renders the declarations through the client. `db sign`, `db init`, `db update`, and `migrate --advance-ref` all run it before anything is applied. The sibling-file read (`readContractIR`) and the after-the-fact `resolveRefAdvancementFields` are gone. 3. **A two-facade project manifest is a structured refusal.** Resolving the import root threw a bare `ImportRootError` when a `package.json` depends on both `@prisma/orm-postgres` and `@prisma/orm-mongo`. It now maps to `CLI.PROJECT_MANIFEST_INVALID`, naming the manifest. ## Reviewer notes - **Why render at all, given `migration.ts` imports the snapshot `.d.ts` by path.** That import is exactly why the file must exist on disk, and why it should be the declarations of that snapshot's JSON. Reading a sibling file only guaranteed that by convention. Rendering guarantees it by construction. - **`migrate` orders differently from `init` and `update`.** In [migrate.ts](packages/1-framework/3-tooling/cli/src/orm/migrate.ts) the preflight sits after `connect` and the marker read, right before `client.migrate`. A first cut hoisted it above `connect`, which made a missing `--to` snapshot beat the invariant pre-check that an existing test rightly expects to win. Reads before, the write after, is the property that matters. - **Environment drift is a deliberate behaviour change.** The rendered declarations reflect the packages installed now, not at emit time. If an extension was upgraded between `contract emit` and `db update`, the snapshot `.d.ts` differs from the project's `contract.d.ts`. The snapshot is then consistent with its JSON under the current install, which is the honest answer. - **Cost.** Each ref advance now runs the type render plus prettier, on a command that already connects to a database. - **The CLI test fixture package declares both facades.** That is why the two-facade error surfaced, and why the command tests now write their own single-facade manifest with `writeProjectManifest`. - **Deferred on purpose.** `migration plan` and `migration new` still read the sibling `.d.ts` when writing the destination snapshot ([migration-plan.ts](packages/1-framework/3-tooling/cli/src/control-api/operations/migration-plan.ts), [migration-new.ts](packages/1-framework/3-tooling/cli/src/control-api/operations/migration-new.ts)). They touch no database, and their offline tests use fake descriptors that cannot drive the real emitter. The `contractDts` field on the `contractAt` path stays for the same reason. ## How it fits together 1. **The client renders.** [client.ts](packages/1-framework/3-tooling/cli/src/control-api/client.ts) adds `renderContractDts` next to `emit`, both calling one private `emitArtifacts` so they cannot drift. Failures come back as `CONTRACT_VALIDATION_FAILED` (the family rejected the JSON) or `RENDER_FAILED` (the emitter refused it). The fixture client in [fixture-client.ts](packages/1-framework/3-tooling/cli/src/control-api/testing/fixture-client.ts) gets a matching default. 2. **The preflight maps.** [ref-advancement.ts](packages/1-framework/3-tooling/cli/src/control-api/operations/ref-advancement.ts) turns those into `CONTRACT.VALIDATION_FAILED` and the new `CONTRACT.TYPES_RENDER_FAILED`, both locating the contract JSON. `buildRefAdvancementFields` becomes the pure after-the-write tail for `init` and `update`. 3. **The commands split around the write.** [init.ts](packages/1-framework/3-tooling/cli/src/orm/db/init.ts) and [update.ts](packages/1-framework/3-tooling/cli/src/orm/db/update.ts) compute the ref name and preflight before `connect`, then build the fields after the apply. [sign.ts](packages/1-framework/3-tooling/cli/src/orm/db/sign.ts) creates the client before its existing preflight so it can render. `migrate` preflights after resolving the apply contract and before applying. 4. **The manifest refusal.** [project-import-root.ts](packages/1-framework/3-tooling/cli/src/utils/project-import-root.ts) catches `ImportRootError` where it reads the manifest, so every caller of the resolver gets a structured error. ## Behavior changes & evidence - **`db init`, `db update`, and `migrate --advance-ref` refuse before any database write when the snapshot cannot be rendered**, with a structured code and a fix, instead of migrating and then exiting on a bare ENOENT. Implementation: [init.ts](packages/1-framework/3-tooling/cli/src/orm/db/init.ts), [update.ts](packages/1-framework/3-tooling/cli/src/orm/db/update.ts), [migrate.ts](packages/1-framework/3-tooling/cli/src/orm/migrate.ts). Evidence: [db-init.test.ts](packages/1-framework/3-tooling/cli/test/orm/db-init.test.ts), [migrate.test.ts](packages/1-framework/3-tooling/cli/test/orm/migrate.test.ts). - **Every ref advance stores declarations rendered from the snapshotted JSON**, and none of the four commands needs `contract.d.ts` on disk any more. `db sign` without the file now succeeds. Implementation: [ref-advancement.ts](packages/1-framework/3-tooling/cli/src/control-api/operations/ref-advancement.ts). Evidence: [db-sign.ref-advancement.test.ts](packages/1-framework/3-tooling/cli/test/orm/db-sign.ref-advancement.test.ts), [ref-advancement.test.ts](packages/1-framework/3-tooling/cli/test/control-api/ref-advancement.test.ts). - **`renderContractDts` produces the text `emit` produces** for the same contract, and rewrites imports through the resolver it is given. Implementation: [client.ts](packages/1-framework/3-tooling/cli/src/control-api/client.ts). Evidence: [client.test.ts](packages/1-framework/3-tooling/cli/test/control-api/client.test.ts). - **A project depending on two database facades gets `CLI.PROJECT_MANIFEST_INVALID`** naming the manifest, instead of an uncaught error. Implementation: [project-import-root.ts](packages/1-framework/3-tooling/cli/src/utils/project-import-root.ts). Evidence: [project-import-root.test.ts](packages/1-framework/3-tooling/cli/test/utils/project-import-root.test.ts). - **Docs.** The migration-system subsystem doc says where a ref's snapshot declarations come from, and [error-reference.md](docs/reference/error-reference.md) documents `CONTRACT.TYPES_RENDER_FAILED`. ## Testing performed - `pnpm typecheck` in `@internal/cli` and `@internal/extension-sqlite` (against the rebuilt CLI dist) - `pnpm test` in `@internal/cli`: 116 files, 1472 tests - `pnpm test test/migrations/db-init-update.cli.test.ts` in the sqlite adapter (real stack) - `pnpm check:error-reference` - Review pass by a second agent; its findings (error-reference entry, two prose inaccuracies, a test path) are folded into the last commit ## Alternatives considered - **Keep reading the sibling `.d.ts`, just earlier.** This was the original proposal: give `init`, `update`, and `migrate` the same read-before-write preflight `db sign` got. It removes the stranded-database bug but keeps the snapshot's declarations coupled to whichever file happens to sit next to `contract.json`. Rendering makes the snapshot a pure function of its JSON and the installed stack. - **Stop storing `contract.d.ts` in the snapshot and render on read.** `migration.ts` imports `../../snapshots/<hash>/contract` by path and `tsc` has to find it without Prisma running, so the file must be materialised. Rendering at write time keeps that. - **A standalone renderer keyed off the config instead of a client method.** The CLI command tests mount fake control clients, and the fake families in those fixtures cannot drive the real emitter. Putting the renderer on the client gives those tests their seam and keeps the real path one function. - **Also switching `migration plan` and `migration new` to render.** Deferred; see reviewer notes. ## 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 — no Linear ticket exists for this change; the prefix will be added if one is assigned. - [x] The **Skill update** section above is filled in. ## Notes for the reviewer See the reviewer notes above. 🤖 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** - Ref-advancing commands now generate and store contract type declarations from the contract snapshot before migrations or reference updates. - Planning modes continue to show the proposed reference without applying changes. - **Bug Fixes** - Validation or type-generation failures now stop execution before database, migration, reference, or snapshot changes occur. - Invalid project manifests now produce structured, actionable CLI errors. - **Documentation** - Added reference documentation for contract type-generation failures and their effects. <!-- 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.1 <noreply@anthropic.com> | 20 天前 |
@internal/sql-contract
SQL contract types, validators, and IR factories for Prisma 8.
Overview
This package provides TypeScript type definitions, Arktype validators, and factory functions for constructing SQL contract structures. It is located in the shared plane, making it available to both migration-plane (authoring, emitter) and runtime-plane (lanes, runtime) packages.
Responsibilities
- SQL Contract Types: Defines SQL-specific contract types (
SqlContract,SqlStorage,StorageTable,SqlModelStorage,SqlModelFieldStorage,ForeignKeysConfig) that extend framework-level contract types - Contract Validation: Provides Arktype-based structural validators that the per-target
contractSerializerSPI consumes for runtime-safe contract validation - IR Factories: Provides pure factory functions for constructing contract IR structures in tests and authoring
- Shared Plane Access: Enables both migration-plane and runtime-plane packages to import SQL contract types without violating plane boundaries
StorageColumn Structure
Each StorageColumn in SQL contracts includes both:
nativeType(required): Native database type identifier (e.g.,'int4','text','vector') - used for database structure verification and migration planningcodecId(required): Codec identifier (e.g.,'pg/int4@1','pg/text@1','pg/vector@1') - used for query builders and runtime codecsnullable(required): Whether the column is nullabledefault(optional): Uses the sharedColumnDefaulttype from@internal/contractfor db-agnostic defaults (literal or function). Client-generated defaults live inexecution.mutations.defaults.
Both nativeType and codecId are required to ensure contracts are consumable by both the application (via codec IDs) and the database (via native types). See docs/briefs/Sql-Contract-Native-and-Codec-Types.md for details.
Package Contents
- TypeScript Types: Type definitions for
SqlContract,SqlStorage,StorageTable,SqlModelStorage,SqlModelFieldStorage,ForeignKeysConfig, and related types - Validators: Arktype-based validators for structural validation of contracts, storage, and models
- Factories: Pure factory functions for constructing contract IR structures in tests and authoring
Usage
TypeScript Types
Import SQL contract types:
import type {
SqlContract,
SqlStorage,
StorageTable,
SqlModelStorage,
ForeignKeysConfig,
} from '@internal/sql-contract/types';
Foreign Keys Configuration
SqlContract includes an optional foreignKeys field of type ForeignKeysConfig that controls whether the planner emits foreign key constraints and their backing indexes:
type ForeignKeysConfig = {
readonly constraints: boolean; // Emit FOREIGN KEY constraints
readonly indexes: boolean; // Emit FK-backing indexes
};
When omitted, defaults to { constraints: true, indexes: true }. See ADR 161 for design rationale.
Referential Actions
ForeignKey supports optional onDelete and onUpdate fields of type ReferentialAction:
type ReferentialAction = 'noAction' | 'restrict' | 'cascade' | 'setNull' | 'setDefault';
type ForeignKey = {
readonly columns: readonly string[];
readonly references: ForeignKeyReferences;
readonly name?: string;
readonly onDelete?: ReferentialAction;
readonly onUpdate?: ReferentialAction;
};
When omitted, the database applies its default behavior (Postgres: NO ACTION). See ADR 166 for design rationale.
The fk() factory accepts referential actions via an options object:
import { fk } from '@internal/sql-contract/factories';
// Simple FK (no referential actions)
const simple = fk(['userId'], 'user', ['id']);
// FK with onDelete cascade
const cascading = fk(['userId'], 'user', ['id'], { onDelete: 'cascade' });
// FK with name and both actions
const named = fk(['userId'], 'user', ['id'], {
name: 'post_userId_fkey',
onDelete: 'cascade',
onUpdate: 'noAction',
});
Semantic validation: validateStorageSemantics() rejects setNull when the FK column is NOT NULL (the database would fail at runtime).
Validators
Validate contract structures using Arktype validators:
import { validateSqlContractFully, validateStorage, validateModel } from '@internal/sql-contract/validators';
// Validate a complete contract
const contract = validateSqlContractFully<Contract>(contractJson);
// Validate storage structure
const storage = validateStorage(storageJson);
// Validate model structure
const model = validateModel(modelJson);
Validate JSON-emitted contracts with mapping + logic checks via the
target descriptor's contractSerializer SPI:
import postgresTarget from '@internal/target-postgres/control';
const contract = postgresTarget.contractSerializer.deserializeContract(contractJson);
deserializeContract parses the on-disk envelope, hydrates the SQL
Contract IR class hierarchy (SqlStorage → StorageTable → StorageColumn
/ PrimaryKey / …), and validates model-to-storage cross-references in
one pass. End-user app code typically calls the canonical façade instead
(e.g. postgres<Contract>({ contractJson, … })), which threads the same
SPI internally.
Factories
Use factory functions to construct contract IR structures in tests:
import { col, table, storage, model, contract, pk, unique, index, fk } from '@internal/sql-contract/factories';
// Create a column (nativeType, codecId, nullable)
const idColumn = col('int4', 'pg/int4@1', false);
// Create a table
const userTable = table(
{
id: col('int4', 'pg/int4@1'),
email: col('text', 'pg/text@1'),
},
{
pk: pk('id'),
uniques: [unique('email')],
indexes: [index('email')],
}
);
// Create storage
const s = storage({ user: userTable });
// Create a model
const userModel = model('user', {
id: { column: 'id' },
email: { column: 'email' },
});
// Create a complete contract
const c = contract({
target: 'postgres',
storageHash: 'abc123',
storage: s,
models: { User: userModel },
});
Exports
./types: TypeScript type definitions./validators: Arktype validators for structural validation./factories: Factory functions for constructing contract IR./pack-types: Shared extension/pack typing helpers
Architecture
flowchart TD
subgraph "SQL Contract Package (Shared Plane)"
TYPES[Type Definitions]
VALIDATORS[Validators]
FACTORIES[IR Factories]
end
subgraph "Migration Plane"
AUTHORING[Authoring]
EMITTER[Emitter]
end
subgraph "Runtime Plane"
LANES[Lanes]
RUNTIME[Runtime]
end
TYPES --> AUTHORING
TYPES --> EMITTER
TYPES --> LANES
TYPES --> RUNTIME
VALIDATORS --> AUTHORING
VALIDATORS --> EMITTER
VALIDATORS --> RUNTIME
FACTORIES --> AUTHORING
FACTORIES --> EMITTER
Related Packages
@internal/contract: Framework-level contract types (ContractBase)@internal/sql-contract-ts: SQL contract authoring surface (uses this package)@internal/emitter: Contract emission engine (uses validators)
Related Subsystems
- Data Contract: Detailed subsystem specification
- Contract Emitter & Types: Contract emission