| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
TML-3067: all error codes become dotted NAMESPACE.SUBCODE (ADR 239) (#1016) ## Linked issue Refs [TML-3067](https://linear.app/prisma-company/issue/TML-3067/error-consolidation-one-structural-error-scheme-with-dotted-namespace) — the error-consolidation work item of Prisma 8 RC1 ("Error-code scheme ratified" milestone). Codes freeze at RC. ## At a glance ```ts import { isStructuredError, structuredError } from '@prisma-next/utils/structured-error'; const err = structuredError('MIGRATION.FILE_MISSING', 'Migration file not found', { why: 'No migration.ts under "migrations/app/20260721".', fix: 'Run `prisma-next migration new` or check the path.', }); throw err; // throwable… return notOk(err); // …or a Result failure — same value, no conversion isStructuredError(err); // true — a structural field check, never instanceof ``` Before this PR the same failure appeared under five different schemes: numeric `PN-MIG-2002` from one class, dotted `MIGRATION.FILE_MISSING` from another, and a bare `'EXECUTION_FAILED'` enum on runner `Result`s — with no shared recognition mechanism. ## Decision This PR ships the error-consolidation slice ratified in [ADR 239](docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md) (supersedes ADR 027 + ADR 068): 1. **One code scheme.** Every published error code is now a dotted `NAMESPACE.SUBCODE` name from a closed, ADR-governed namespace list. All numeric `PN-DOMAIN-NNNN` codes are renamed — including two catalogues the original census missed (`PN-MIG-CHECK-*`, `PN-SCHEMA-0001`) — with a complete old→new crosswalk in the ADR. 2. **Structural recognition.** A `StructuredError` interface + `isStructuredError` predicate (field-shape check, never `instanceof`) in `@prisma-next/utils`, so errors survive the control/execution split, JSON round-trips, and duplicate library copies. `CliStructuredError` remains as a convenience class that implements the interface; the `domain` concept is deleted. 3. **User-facing vs internal.** New `InternalError` + `assertNever` for bugs; `invariant`/`assertDefined` now throw it. Never caught except at the outermost boundary. 4. **A ban with a ratchet.** A `no-bare-throw` Biome plugin flags `throw new Error(` at severity `info`; a CI ratchet (mirroring `no-bare-cast`) fails any PR that raises the count. ~950 pre-existing sites burn down in later per-plane sweeps. 5. **Exit codes aligned to the reserved table.** Expected structured failures exit `2` (user-abort `3`); `1` is reserved for internal errors. Previously every non-CLI structured error exited `1`, colliding with its documented "internal error" meaning. ## Reviewer notes - **The crosswalk is the review.** The freeze-critical artifact is the old→new table in ADR 239 — every rename in the diff must match it. The judgment-call mappings: marker/verify codes went to `CONTRACT` (not `CLI`/`RUN`) because they're about the contract↔DB relationship; planning/runner failures went to `MIGRATION`; config-shaped `PN-CLI-4xxx` codes went to `CONFIG`. - **Largest commit** is the rename (91 files) but it's almost entirely mechanical string + assertion updates; the one structural change is in `packages/1-framework/1-core/errors/src/control.ts` (domain removal, `implements StructuredError`). - **Three latent bugs fixed in passing**, visible as behavior changes: `PN-CLI-4012` was assigned to two unrelated errors (now split as `CLI.CONFIG_ARG_MISSING_PATH` / `CLI.INVALID_VERIFY_MODE`); mongo schema-verify reported the marker-required code for schema failures (now `CONTRACT.SCHEMA_VERIFICATION_FAILED`); driver envelopes hardcoded `category: 'RUNTIME'` for `DRIVER.*` codes (now `DRIVER`). - **Deleted surface:** relational-core's `planInvalid`/`planUnsupported` + its duplicate `RuntimeError` interface had zero production callers — deleted, not migrated. - **Local flakes ruled pre-existing:** `removed-verb-redirects`/`version` CLI tests (500 ms spawn timeout vs ~0.9 s local CLI startup) fail identically on a merge-base build; untouched by this branch. ## How it fits together 1. **Foundation** — `@prisma-next/utils` gains `structured-error` (interface, predicate, factory, `docsUrlFor` with a single `DOCS_BASE`) and `internal-error` (`InternalError`, `isInternalError`, `assertNever`). No code enumeration here: each namespace's codes live as a typed union in the module that owns the namespace. 2. **Rename** — the `@prisma-next/errors` factories, the init-command factories, the `migration check` catalogue, and every direct construction emit dotted codes; ~140 test assertions updated across the repo. 3. **Reconciliation** — the runtime envelope's category union gains `DRIVER`/`MIGRATION`/`ORM` (no more silent fold to `RUNTIME`); SQL and mongo runner `Result` codes become `MIGRATION.*`; dead PLAN surface deleted. 4. **Enforcement** — `biome-plugins/no-bare-throw.grit` + `scripts/lint-throws.mjs` wired into `biome.jsonc`, CI, and `test:scripts`, with fixtures proving fire/no-fire (TypeError/RangeError/InternalError and test files are exempt). 5. **Docs** — ADR 239 with the full crosswalk; ADR 027/068 marked superseded; `docs/Error Handling.md` and `docs/CLI Style Guide.md` updated; the 0.15-to-0.16 upgrade instructions record the rename with a detection glob for old code strings. ## Behavior changes & evidence - **All published codes are dotted.** Implementation: [packages/1-framework/1-core/errors/src/control.ts](packages/1-framework/1-core/errors/src/control.ts), [execution.ts](packages/1-framework/1-core/errors/src/execution.ts), [migration.ts](packages/1-framework/1-core/errors/src/migration.ts). Evidence: [packages/1-framework/1-core/errors/test](packages/1-framework/1-core/errors/test) and the CLI golden tests; repo-wide grep for `PN-DOMAIN-NNNN` outside `docs/` returns zero. - **Structural recognition ships.** Implementation: [packages/1-framework/0-foundation/utils/src/structured-error.ts](packages/1-framework/0-foundation/utils/src/structured-error.ts). Evidence: [test/structured-error.test.ts](packages/1-framework/0-foundation/utils/test/structured-error.test.ts) asserts a bare `{ code, message }` object (no prototype) is recognized. - **Bugs throw `InternalError`.** Implementation: [internal-error.ts](packages/1-framework/0-foundation/utils/src/internal-error.ts), [assertions.ts](packages/1-framework/0-foundation/utils/src/assertions.ts). Evidence: [test/internal-error.test.ts](packages/1-framework/0-foundation/utils/test/internal-error.test.ts). - **Structured failures exit 2, user-abort 3.** Implementation: [packages/1-framework/3-tooling/cli/src/utils/result-handler.ts](packages/1-framework/3-tooling/cli/src/utils/result-handler.ts), [commands/init/init.ts](packages/1-framework/3-tooling/cli/src/commands/init/init.ts). Evidence: CLI command tests updated alongside. - **Runner failures carry `MIGRATION.*` codes on `Result`.** Implementation: [packages/2-sql/9-family/src/core/migrations/types.ts](packages/2-sql/9-family/src/core/migrations/types.ts), postgres/sqlite/mongo runners. Evidence: runner unit + integration tests in all three target packages. - **Bare `throw new Error` is ratcheted.** Implementation: [biome-plugins/no-bare-throw.grit](biome-plugins/no-bare-throw.grit), [scripts/lint-throws.mjs](scripts/lint-throws.mjs). Evidence: [biome-plugins/fixtures](biome-plugins/fixtures) fire/no-fire files, [scripts/lint-throws.test.mjs](scripts/lint-throws.test.mjs). ## Testing performed - `pnpm build` — 68/68 tasks. - `pnpm test:packages` — 13,133+ passed; the only reds are the two pre-existing local-machine timeout suites noted above (untouched by this branch; reproduce at merge-base). - `pnpm lint:deps`, `pnpm test:scripts` (200/200, includes the new ratchet tests), `pnpm check:upgrade-coverage --mode pr` — clean. - Per-package suites for every touched package (errors, cli 1347/1347, framework-components, relational-core, sql/mongo families, targets, drivers, adapters). ## Skill update The 0.15-to-0.16 upgrade-skill instructions ([skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md](skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md)) gain an entry for the code rename with a detection glob over old `PN-*` strings. No shipped skill documents specific error codes (verified by grep). ## Follow-ups - Per-plane sweeps of the ~250 codeless user-facing throws (ORM, authoring, adapters) onto `structuredError`, ratcheting `lint:throws` down — trails RC per the ADR's freeze-scope; codes added later are non-breaking. - Centralize the hardcoded `prisma-next.dev` docs URLs in factories onto `docsUrlFor` (one-line domain flip at RC). ## Alternatives considered - **A single base class recognized by `instanceof`** — rejected; a shared prototype doesn't survive the control/execution split, JSON rehydration, or duplicate library copies. The old code already duck-typed around this; the ADR makes the workaround the mechanism. - **One physical union module listing every code** — rejected; it would invert `lint:deps` layering (foundation naming codes owned by targets/extensions). Per-namespace unions keep each code with its owner; the ADR crosswalk is the registry. - **Keeping numeric `PN-DOMAIN-NNNN`** — rejected in the scheme decision; dotted names are self-describing and already had 2:1 adoption. - **Converting all ~750 bare throws before RC** — rejected; only renames of *published* codes are breaking and must freeze. The ratchet lets the tail burn down safely after RC. ## 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. --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 2 个月前 | |
TML-2685: forbid bare as-casts via cast-utils + Biome plugin + CI ratchet (#598) | 3 个月前 | |
TML-2685: forbid bare as-casts via cast-utils + Biome plugin + CI ratchet (#598) | 3 个月前 | |
TML-2685: forbid bare as-casts via cast-utils + Biome plugin + CI ratchet (#598) | 3 个月前 | |
TML-3067: all error codes become dotted NAMESPACE.SUBCODE (ADR 239) (#1016) ## Linked issue Refs [TML-3067](https://linear.app/prisma-company/issue/TML-3067/error-consolidation-one-structural-error-scheme-with-dotted-namespace) — the error-consolidation work item of Prisma 8 RC1 ("Error-code scheme ratified" milestone). Codes freeze at RC. ## At a glance ```ts import { isStructuredError, structuredError } from '@prisma-next/utils/structured-error'; const err = structuredError('MIGRATION.FILE_MISSING', 'Migration file not found', { why: 'No migration.ts under "migrations/app/20260721".', fix: 'Run `prisma-next migration new` or check the path.', }); throw err; // throwable… return notOk(err); // …or a Result failure — same value, no conversion isStructuredError(err); // true — a structural field check, never instanceof ``` Before this PR the same failure appeared under five different schemes: numeric `PN-MIG-2002` from one class, dotted `MIGRATION.FILE_MISSING` from another, and a bare `'EXECUTION_FAILED'` enum on runner `Result`s — with no shared recognition mechanism. ## Decision This PR ships the error-consolidation slice ratified in [ADR 239](docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md) (supersedes ADR 027 + ADR 068): 1. **One code scheme.** Every published error code is now a dotted `NAMESPACE.SUBCODE` name from a closed, ADR-governed namespace list. All numeric `PN-DOMAIN-NNNN` codes are renamed — including two catalogues the original census missed (`PN-MIG-CHECK-*`, `PN-SCHEMA-0001`) — with a complete old→new crosswalk in the ADR. 2. **Structural recognition.** A `StructuredError` interface + `isStructuredError` predicate (field-shape check, never `instanceof`) in `@prisma-next/utils`, so errors survive the control/execution split, JSON round-trips, and duplicate library copies. `CliStructuredError` remains as a convenience class that implements the interface; the `domain` concept is deleted. 3. **User-facing vs internal.** New `InternalError` + `assertNever` for bugs; `invariant`/`assertDefined` now throw it. Never caught except at the outermost boundary. 4. **A ban with a ratchet.** A `no-bare-throw` Biome plugin flags `throw new Error(` at severity `info`; a CI ratchet (mirroring `no-bare-cast`) fails any PR that raises the count. ~950 pre-existing sites burn down in later per-plane sweeps. 5. **Exit codes aligned to the reserved table.** Expected structured failures exit `2` (user-abort `3`); `1` is reserved for internal errors. Previously every non-CLI structured error exited `1`, colliding with its documented "internal error" meaning. ## Reviewer notes - **The crosswalk is the review.** The freeze-critical artifact is the old→new table in ADR 239 — every rename in the diff must match it. The judgment-call mappings: marker/verify codes went to `CONTRACT` (not `CLI`/`RUN`) because they're about the contract↔DB relationship; planning/runner failures went to `MIGRATION`; config-shaped `PN-CLI-4xxx` codes went to `CONFIG`. - **Largest commit** is the rename (91 files) but it's almost entirely mechanical string + assertion updates; the one structural change is in `packages/1-framework/1-core/errors/src/control.ts` (domain removal, `implements StructuredError`). - **Three latent bugs fixed in passing**, visible as behavior changes: `PN-CLI-4012` was assigned to two unrelated errors (now split as `CLI.CONFIG_ARG_MISSING_PATH` / `CLI.INVALID_VERIFY_MODE`); mongo schema-verify reported the marker-required code for schema failures (now `CONTRACT.SCHEMA_VERIFICATION_FAILED`); driver envelopes hardcoded `category: 'RUNTIME'` for `DRIVER.*` codes (now `DRIVER`). - **Deleted surface:** relational-core's `planInvalid`/`planUnsupported` + its duplicate `RuntimeError` interface had zero production callers — deleted, not migrated. - **Local flakes ruled pre-existing:** `removed-verb-redirects`/`version` CLI tests (500 ms spawn timeout vs ~0.9 s local CLI startup) fail identically on a merge-base build; untouched by this branch. ## How it fits together 1. **Foundation** — `@prisma-next/utils` gains `structured-error` (interface, predicate, factory, `docsUrlFor` with a single `DOCS_BASE`) and `internal-error` (`InternalError`, `isInternalError`, `assertNever`). No code enumeration here: each namespace's codes live as a typed union in the module that owns the namespace. 2. **Rename** — the `@prisma-next/errors` factories, the init-command factories, the `migration check` catalogue, and every direct construction emit dotted codes; ~140 test assertions updated across the repo. 3. **Reconciliation** — the runtime envelope's category union gains `DRIVER`/`MIGRATION`/`ORM` (no more silent fold to `RUNTIME`); SQL and mongo runner `Result` codes become `MIGRATION.*`; dead PLAN surface deleted. 4. **Enforcement** — `biome-plugins/no-bare-throw.grit` + `scripts/lint-throws.mjs` wired into `biome.jsonc`, CI, and `test:scripts`, with fixtures proving fire/no-fire (TypeError/RangeError/InternalError and test files are exempt). 5. **Docs** — ADR 239 with the full crosswalk; ADR 027/068 marked superseded; `docs/Error Handling.md` and `docs/CLI Style Guide.md` updated; the 0.15-to-0.16 upgrade instructions record the rename with a detection glob for old code strings. ## Behavior changes & evidence - **All published codes are dotted.** Implementation: [packages/1-framework/1-core/errors/src/control.ts](packages/1-framework/1-core/errors/src/control.ts), [execution.ts](packages/1-framework/1-core/errors/src/execution.ts), [migration.ts](packages/1-framework/1-core/errors/src/migration.ts). Evidence: [packages/1-framework/1-core/errors/test](packages/1-framework/1-core/errors/test) and the CLI golden tests; repo-wide grep for `PN-DOMAIN-NNNN` outside `docs/` returns zero. - **Structural recognition ships.** Implementation: [packages/1-framework/0-foundation/utils/src/structured-error.ts](packages/1-framework/0-foundation/utils/src/structured-error.ts). Evidence: [test/structured-error.test.ts](packages/1-framework/0-foundation/utils/test/structured-error.test.ts) asserts a bare `{ code, message }` object (no prototype) is recognized. - **Bugs throw `InternalError`.** Implementation: [internal-error.ts](packages/1-framework/0-foundation/utils/src/internal-error.ts), [assertions.ts](packages/1-framework/0-foundation/utils/src/assertions.ts). Evidence: [test/internal-error.test.ts](packages/1-framework/0-foundation/utils/test/internal-error.test.ts). - **Structured failures exit 2, user-abort 3.** Implementation: [packages/1-framework/3-tooling/cli/src/utils/result-handler.ts](packages/1-framework/3-tooling/cli/src/utils/result-handler.ts), [commands/init/init.ts](packages/1-framework/3-tooling/cli/src/commands/init/init.ts). Evidence: CLI command tests updated alongside. - **Runner failures carry `MIGRATION.*` codes on `Result`.** Implementation: [packages/2-sql/9-family/src/core/migrations/types.ts](packages/2-sql/9-family/src/core/migrations/types.ts), postgres/sqlite/mongo runners. Evidence: runner unit + integration tests in all three target packages. - **Bare `throw new Error` is ratcheted.** Implementation: [biome-plugins/no-bare-throw.grit](biome-plugins/no-bare-throw.grit), [scripts/lint-throws.mjs](scripts/lint-throws.mjs). Evidence: [biome-plugins/fixtures](biome-plugins/fixtures) fire/no-fire files, [scripts/lint-throws.test.mjs](scripts/lint-throws.test.mjs). ## Testing performed - `pnpm build` — 68/68 tasks. - `pnpm test:packages` — 13,133+ passed; the only reds are the two pre-existing local-machine timeout suites noted above (untouched by this branch; reproduce at merge-base). - `pnpm lint:deps`, `pnpm test:scripts` (200/200, includes the new ratchet tests), `pnpm check:upgrade-coverage --mode pr` — clean. - Per-package suites for every touched package (errors, cli 1347/1347, framework-components, relational-core, sql/mongo families, targets, drivers, adapters). ## Skill update The 0.15-to-0.16 upgrade-skill instructions ([skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md](skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md)) gain an entry for the code rename with a detection glob over old `PN-*` strings. No shipped skill documents specific error codes (verified by grep). ## Follow-ups - Per-plane sweeps of the ~250 codeless user-facing throws (ORM, authoring, adapters) onto `structuredError`, ratcheting `lint:throws` down — trails RC per the ADR's freeze-scope; codes added later are non-breaking. - Centralize the hardcoded `prisma-next.dev` docs URLs in factories onto `docsUrlFor` (one-line domain flip at RC). ## Alternatives considered - **A single base class recognized by `instanceof`** — rejected; a shared prototype doesn't survive the control/execution split, JSON rehydration, or duplicate library copies. The old code already duck-typed around this; the ADR makes the workaround the mechanism. - **One physical union module listing every code** — rejected; it would invert `lint:deps` layering (foundation naming codes owned by targets/extensions). Per-namespace unions keep each code with its owner; the ADR crosswalk is the registry. - **Keeping numeric `PN-DOMAIN-NNNN`** — rejected in the scheme decision; dotted names are self-describing and already had 2:1 adoption. - **Converting all ~750 bare throws before RC** — rejected; only renames of *published* codes are breaking and must freeze. The ratchet lets the tail burn down safely after RC. ## 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. --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 2 个月前 | |
TML-3067: all error codes become dotted NAMESPACE.SUBCODE (ADR 239) (#1016) ## Linked issue Refs [TML-3067](https://linear.app/prisma-company/issue/TML-3067/error-consolidation-one-structural-error-scheme-with-dotted-namespace) — the error-consolidation work item of Prisma 8 RC1 ("Error-code scheme ratified" milestone). Codes freeze at RC. ## At a glance ```ts import { isStructuredError, structuredError } from '@prisma-next/utils/structured-error'; const err = structuredError('MIGRATION.FILE_MISSING', 'Migration file not found', { why: 'No migration.ts under "migrations/app/20260721".', fix: 'Run `prisma-next migration new` or check the path.', }); throw err; // throwable… return notOk(err); // …or a Result failure — same value, no conversion isStructuredError(err); // true — a structural field check, never instanceof ``` Before this PR the same failure appeared under five different schemes: numeric `PN-MIG-2002` from one class, dotted `MIGRATION.FILE_MISSING` from another, and a bare `'EXECUTION_FAILED'` enum on runner `Result`s — with no shared recognition mechanism. ## Decision This PR ships the error-consolidation slice ratified in [ADR 239](docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md) (supersedes ADR 027 + ADR 068): 1. **One code scheme.** Every published error code is now a dotted `NAMESPACE.SUBCODE` name from a closed, ADR-governed namespace list. All numeric `PN-DOMAIN-NNNN` codes are renamed — including two catalogues the original census missed (`PN-MIG-CHECK-*`, `PN-SCHEMA-0001`) — with a complete old→new crosswalk in the ADR. 2. **Structural recognition.** A `StructuredError` interface + `isStructuredError` predicate (field-shape check, never `instanceof`) in `@prisma-next/utils`, so errors survive the control/execution split, JSON round-trips, and duplicate library copies. `CliStructuredError` remains as a convenience class that implements the interface; the `domain` concept is deleted. 3. **User-facing vs internal.** New `InternalError` + `assertNever` for bugs; `invariant`/`assertDefined` now throw it. Never caught except at the outermost boundary. 4. **A ban with a ratchet.** A `no-bare-throw` Biome plugin flags `throw new Error(` at severity `info`; a CI ratchet (mirroring `no-bare-cast`) fails any PR that raises the count. ~950 pre-existing sites burn down in later per-plane sweeps. 5. **Exit codes aligned to the reserved table.** Expected structured failures exit `2` (user-abort `3`); `1` is reserved for internal errors. Previously every non-CLI structured error exited `1`, colliding with its documented "internal error" meaning. ## Reviewer notes - **The crosswalk is the review.** The freeze-critical artifact is the old→new table in ADR 239 — every rename in the diff must match it. The judgment-call mappings: marker/verify codes went to `CONTRACT` (not `CLI`/`RUN`) because they're about the contract↔DB relationship; planning/runner failures went to `MIGRATION`; config-shaped `PN-CLI-4xxx` codes went to `CONFIG`. - **Largest commit** is the rename (91 files) but it's almost entirely mechanical string + assertion updates; the one structural change is in `packages/1-framework/1-core/errors/src/control.ts` (domain removal, `implements StructuredError`). - **Three latent bugs fixed in passing**, visible as behavior changes: `PN-CLI-4012` was assigned to two unrelated errors (now split as `CLI.CONFIG_ARG_MISSING_PATH` / `CLI.INVALID_VERIFY_MODE`); mongo schema-verify reported the marker-required code for schema failures (now `CONTRACT.SCHEMA_VERIFICATION_FAILED`); driver envelopes hardcoded `category: 'RUNTIME'` for `DRIVER.*` codes (now `DRIVER`). - **Deleted surface:** relational-core's `planInvalid`/`planUnsupported` + its duplicate `RuntimeError` interface had zero production callers — deleted, not migrated. - **Local flakes ruled pre-existing:** `removed-verb-redirects`/`version` CLI tests (500 ms spawn timeout vs ~0.9 s local CLI startup) fail identically on a merge-base build; untouched by this branch. ## How it fits together 1. **Foundation** — `@prisma-next/utils` gains `structured-error` (interface, predicate, factory, `docsUrlFor` with a single `DOCS_BASE`) and `internal-error` (`InternalError`, `isInternalError`, `assertNever`). No code enumeration here: each namespace's codes live as a typed union in the module that owns the namespace. 2. **Rename** — the `@prisma-next/errors` factories, the init-command factories, the `migration check` catalogue, and every direct construction emit dotted codes; ~140 test assertions updated across the repo. 3. **Reconciliation** — the runtime envelope's category union gains `DRIVER`/`MIGRATION`/`ORM` (no more silent fold to `RUNTIME`); SQL and mongo runner `Result` codes become `MIGRATION.*`; dead PLAN surface deleted. 4. **Enforcement** — `biome-plugins/no-bare-throw.grit` + `scripts/lint-throws.mjs` wired into `biome.jsonc`, CI, and `test:scripts`, with fixtures proving fire/no-fire (TypeError/RangeError/InternalError and test files are exempt). 5. **Docs** — ADR 239 with the full crosswalk; ADR 027/068 marked superseded; `docs/Error Handling.md` and `docs/CLI Style Guide.md` updated; the 0.15-to-0.16 upgrade instructions record the rename with a detection glob for old code strings. ## Behavior changes & evidence - **All published codes are dotted.** Implementation: [packages/1-framework/1-core/errors/src/control.ts](packages/1-framework/1-core/errors/src/control.ts), [execution.ts](packages/1-framework/1-core/errors/src/execution.ts), [migration.ts](packages/1-framework/1-core/errors/src/migration.ts). Evidence: [packages/1-framework/1-core/errors/test](packages/1-framework/1-core/errors/test) and the CLI golden tests; repo-wide grep for `PN-DOMAIN-NNNN` outside `docs/` returns zero. - **Structural recognition ships.** Implementation: [packages/1-framework/0-foundation/utils/src/structured-error.ts](packages/1-framework/0-foundation/utils/src/structured-error.ts). Evidence: [test/structured-error.test.ts](packages/1-framework/0-foundation/utils/test/structured-error.test.ts) asserts a bare `{ code, message }` object (no prototype) is recognized. - **Bugs throw `InternalError`.** Implementation: [internal-error.ts](packages/1-framework/0-foundation/utils/src/internal-error.ts), [assertions.ts](packages/1-framework/0-foundation/utils/src/assertions.ts). Evidence: [test/internal-error.test.ts](packages/1-framework/0-foundation/utils/test/internal-error.test.ts). - **Structured failures exit 2, user-abort 3.** Implementation: [packages/1-framework/3-tooling/cli/src/utils/result-handler.ts](packages/1-framework/3-tooling/cli/src/utils/result-handler.ts), [commands/init/init.ts](packages/1-framework/3-tooling/cli/src/commands/init/init.ts). Evidence: CLI command tests updated alongside. - **Runner failures carry `MIGRATION.*` codes on `Result`.** Implementation: [packages/2-sql/9-family/src/core/migrations/types.ts](packages/2-sql/9-family/src/core/migrations/types.ts), postgres/sqlite/mongo runners. Evidence: runner unit + integration tests in all three target packages. - **Bare `throw new Error` is ratcheted.** Implementation: [biome-plugins/no-bare-throw.grit](biome-plugins/no-bare-throw.grit), [scripts/lint-throws.mjs](scripts/lint-throws.mjs). Evidence: [biome-plugins/fixtures](biome-plugins/fixtures) fire/no-fire files, [scripts/lint-throws.test.mjs](scripts/lint-throws.test.mjs). ## Testing performed - `pnpm build` — 68/68 tasks. - `pnpm test:packages` — 13,133+ passed; the only reds are the two pre-existing local-machine timeout suites noted above (untouched by this branch; reproduce at merge-base). - `pnpm lint:deps`, `pnpm test:scripts` (200/200, includes the new ratchet tests), `pnpm check:upgrade-coverage --mode pr` — clean. - Per-package suites for every touched package (errors, cli 1347/1347, framework-components, relational-core, sql/mongo families, targets, drivers, adapters). ## Skill update The 0.15-to-0.16 upgrade-skill instructions ([skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md](skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md)) gain an entry for the code rename with a detection glob over old `PN-*` strings. No shipped skill documents specific error codes (verified by grep). ## Follow-ups - Per-plane sweeps of the ~250 codeless user-facing throws (ORM, authoring, adapters) onto `structuredError`, ratcheting `lint:throws` down — trails RC per the ADR's freeze-scope; codes added later are non-breaking. - Centralize the hardcoded `prisma-next.dev` docs URLs in factories onto `docsUrlFor` (one-line domain flip at RC). ## Alternatives considered - **A single base class recognized by `instanceof`** — rejected; a shared prototype doesn't survive the control/execution split, JSON rehydration, or duplicate library copies. The old code already duck-typed around this; the ADR makes the workaround the mechanism. - **One physical union module listing every code** — rejected; it would invert `lint:deps` layering (foundation naming codes owned by targets/extensions). Per-namespace unions keep each code with its owner; the ADR crosswalk is the registry. - **Keeping numeric `PN-DOMAIN-NNNN`** — rejected in the scheme decision; dotted names are self-describing and already had 2:1 adoption. - **Converting all ~750 bare throws before RC** — rejected; only renames of *published* codes are breaking and must freeze. The ratchet lets the tail burn down safely after RC. ## 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. --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 2 个月前 | |
TML-3067: all error codes become dotted NAMESPACE.SUBCODE (ADR 239) (#1016) ## Linked issue Refs [TML-3067](https://linear.app/prisma-company/issue/TML-3067/error-consolidation-one-structural-error-scheme-with-dotted-namespace) — the error-consolidation work item of Prisma 8 RC1 ("Error-code scheme ratified" milestone). Codes freeze at RC. ## At a glance ```ts import { isStructuredError, structuredError } from '@prisma-next/utils/structured-error'; const err = structuredError('MIGRATION.FILE_MISSING', 'Migration file not found', { why: 'No migration.ts under "migrations/app/20260721".', fix: 'Run `prisma-next migration new` or check the path.', }); throw err; // throwable… return notOk(err); // …or a Result failure — same value, no conversion isStructuredError(err); // true — a structural field check, never instanceof ``` Before this PR the same failure appeared under five different schemes: numeric `PN-MIG-2002` from one class, dotted `MIGRATION.FILE_MISSING` from another, and a bare `'EXECUTION_FAILED'` enum on runner `Result`s — with no shared recognition mechanism. ## Decision This PR ships the error-consolidation slice ratified in [ADR 239](docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md) (supersedes ADR 027 + ADR 068): 1. **One code scheme.** Every published error code is now a dotted `NAMESPACE.SUBCODE` name from a closed, ADR-governed namespace list. All numeric `PN-DOMAIN-NNNN` codes are renamed — including two catalogues the original census missed (`PN-MIG-CHECK-*`, `PN-SCHEMA-0001`) — with a complete old→new crosswalk in the ADR. 2. **Structural recognition.** A `StructuredError` interface + `isStructuredError` predicate (field-shape check, never `instanceof`) in `@prisma-next/utils`, so errors survive the control/execution split, JSON round-trips, and duplicate library copies. `CliStructuredError` remains as a convenience class that implements the interface; the `domain` concept is deleted. 3. **User-facing vs internal.** New `InternalError` + `assertNever` for bugs; `invariant`/`assertDefined` now throw it. Never caught except at the outermost boundary. 4. **A ban with a ratchet.** A `no-bare-throw` Biome plugin flags `throw new Error(` at severity `info`; a CI ratchet (mirroring `no-bare-cast`) fails any PR that raises the count. ~950 pre-existing sites burn down in later per-plane sweeps. 5. **Exit codes aligned to the reserved table.** Expected structured failures exit `2` (user-abort `3`); `1` is reserved for internal errors. Previously every non-CLI structured error exited `1`, colliding with its documented "internal error" meaning. ## Reviewer notes - **The crosswalk is the review.** The freeze-critical artifact is the old→new table in ADR 239 — every rename in the diff must match it. The judgment-call mappings: marker/verify codes went to `CONTRACT` (not `CLI`/`RUN`) because they're about the contract↔DB relationship; planning/runner failures went to `MIGRATION`; config-shaped `PN-CLI-4xxx` codes went to `CONFIG`. - **Largest commit** is the rename (91 files) but it's almost entirely mechanical string + assertion updates; the one structural change is in `packages/1-framework/1-core/errors/src/control.ts` (domain removal, `implements StructuredError`). - **Three latent bugs fixed in passing**, visible as behavior changes: `PN-CLI-4012` was assigned to two unrelated errors (now split as `CLI.CONFIG_ARG_MISSING_PATH` / `CLI.INVALID_VERIFY_MODE`); mongo schema-verify reported the marker-required code for schema failures (now `CONTRACT.SCHEMA_VERIFICATION_FAILED`); driver envelopes hardcoded `category: 'RUNTIME'` for `DRIVER.*` codes (now `DRIVER`). - **Deleted surface:** relational-core's `planInvalid`/`planUnsupported` + its duplicate `RuntimeError` interface had zero production callers — deleted, not migrated. - **Local flakes ruled pre-existing:** `removed-verb-redirects`/`version` CLI tests (500 ms spawn timeout vs ~0.9 s local CLI startup) fail identically on a merge-base build; untouched by this branch. ## How it fits together 1. **Foundation** — `@prisma-next/utils` gains `structured-error` (interface, predicate, factory, `docsUrlFor` with a single `DOCS_BASE`) and `internal-error` (`InternalError`, `isInternalError`, `assertNever`). No code enumeration here: each namespace's codes live as a typed union in the module that owns the namespace. 2. **Rename** — the `@prisma-next/errors` factories, the init-command factories, the `migration check` catalogue, and every direct construction emit dotted codes; ~140 test assertions updated across the repo. 3. **Reconciliation** — the runtime envelope's category union gains `DRIVER`/`MIGRATION`/`ORM` (no more silent fold to `RUNTIME`); SQL and mongo runner `Result` codes become `MIGRATION.*`; dead PLAN surface deleted. 4. **Enforcement** — `biome-plugins/no-bare-throw.grit` + `scripts/lint-throws.mjs` wired into `biome.jsonc`, CI, and `test:scripts`, with fixtures proving fire/no-fire (TypeError/RangeError/InternalError and test files are exempt). 5. **Docs** — ADR 239 with the full crosswalk; ADR 027/068 marked superseded; `docs/Error Handling.md` and `docs/CLI Style Guide.md` updated; the 0.15-to-0.16 upgrade instructions record the rename with a detection glob for old code strings. ## Behavior changes & evidence - **All published codes are dotted.** Implementation: [packages/1-framework/1-core/errors/src/control.ts](packages/1-framework/1-core/errors/src/control.ts), [execution.ts](packages/1-framework/1-core/errors/src/execution.ts), [migration.ts](packages/1-framework/1-core/errors/src/migration.ts). Evidence: [packages/1-framework/1-core/errors/test](packages/1-framework/1-core/errors/test) and the CLI golden tests; repo-wide grep for `PN-DOMAIN-NNNN` outside `docs/` returns zero. - **Structural recognition ships.** Implementation: [packages/1-framework/0-foundation/utils/src/structured-error.ts](packages/1-framework/0-foundation/utils/src/structured-error.ts). Evidence: [test/structured-error.test.ts](packages/1-framework/0-foundation/utils/test/structured-error.test.ts) asserts a bare `{ code, message }` object (no prototype) is recognized. - **Bugs throw `InternalError`.** Implementation: [internal-error.ts](packages/1-framework/0-foundation/utils/src/internal-error.ts), [assertions.ts](packages/1-framework/0-foundation/utils/src/assertions.ts). Evidence: [test/internal-error.test.ts](packages/1-framework/0-foundation/utils/test/internal-error.test.ts). - **Structured failures exit 2, user-abort 3.** Implementation: [packages/1-framework/3-tooling/cli/src/utils/result-handler.ts](packages/1-framework/3-tooling/cli/src/utils/result-handler.ts), [commands/init/init.ts](packages/1-framework/3-tooling/cli/src/commands/init/init.ts). Evidence: CLI command tests updated alongside. - **Runner failures carry `MIGRATION.*` codes on `Result`.** Implementation: [packages/2-sql/9-family/src/core/migrations/types.ts](packages/2-sql/9-family/src/core/migrations/types.ts), postgres/sqlite/mongo runners. Evidence: runner unit + integration tests in all three target packages. - **Bare `throw new Error` is ratcheted.** Implementation: [biome-plugins/no-bare-throw.grit](biome-plugins/no-bare-throw.grit), [scripts/lint-throws.mjs](scripts/lint-throws.mjs). Evidence: [biome-plugins/fixtures](biome-plugins/fixtures) fire/no-fire files, [scripts/lint-throws.test.mjs](scripts/lint-throws.test.mjs). ## Testing performed - `pnpm build` — 68/68 tasks. - `pnpm test:packages` — 13,133+ passed; the only reds are the two pre-existing local-machine timeout suites noted above (untouched by this branch; reproduce at merge-base). - `pnpm lint:deps`, `pnpm test:scripts` (200/200, includes the new ratchet tests), `pnpm check:upgrade-coverage --mode pr` — clean. - Per-package suites for every touched package (errors, cli 1347/1347, framework-components, relational-core, sql/mongo families, targets, drivers, adapters). ## Skill update The 0.15-to-0.16 upgrade-skill instructions ([skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md](skills/upgrade/prisma-next-upgrade/upgrades/0.15-to-0.16/instructions.md)) gain an entry for the code rename with a detection glob over old `PN-*` strings. No shipped skill documents specific error codes (verified by grep). ## Follow-ups - Per-plane sweeps of the ~250 codeless user-facing throws (ORM, authoring, adapters) onto `structuredError`, ratcheting `lint:throws` down — trails RC per the ADR's freeze-scope; codes added later are non-breaking. - Centralize the hardcoded `prisma-next.dev` docs URLs in factories onto `docsUrlFor` (one-line domain flip at RC). ## Alternatives considered - **A single base class recognized by `instanceof`** — rejected; a shared prototype doesn't survive the control/execution split, JSON rehydration, or duplicate library copies. The old code already duck-typed around this; the ADR makes the workaround the mechanism. - **One physical union module listing every code** — rejected; it would invert `lint:deps` layering (foundation naming codes owned by targets/extensions). Per-namespace unions keep each code with its owner; the ADR crosswalk is the registry. - **Keeping numeric `PN-DOMAIN-NNNN`** — rejected in the scheme decision; dotted names are self-describing and already had 2:1 adoption. - **Converting all ~750 bare throws before RC** — rejected; only renames of *published* codes are breaking and must freeze. The ratchet lets the tail burn down safely after RC. ## 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. --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> | 2 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 2 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 2 个月前 |