diff --git a/.drive/projects/prisma-cli-v8/deferred.md b/.drive/projects/prisma-cli-v8/deferred.md index bbc23c33..038bad6b 100644 --- a/.drive/projects/prisma-cli-v8/deferred.md +++ b/.drive/projects/prisma-cli-v8/deferred.md @@ -97,6 +97,8 @@ composer can use it. ## The ORM family does not work through the assembled binary (found 2026-08-13, writing the e2e happy paths) +**Resolved 2026-08-17 (the presentations half):** `@prisma/orm-toolchain@8.0.0-rc.2` declares all four presentations, prisma-cli pins it, and the engine's two defensive `?.()` calls are gone. The `orm init` config mismatch below is untouched and still live. + Running the shipped `prisma` binary against a scratch directory, rather than the ORM family through the test harness, turns up three things. The first is a defect a user hits on their first command. - **`prisma orm init` scaffolds a project the `prisma` binary cannot read.** It writes `prisma-next.config.ts` — the standalone `prisma-next` bin's config file — and then fails its own last step, `Emit the contract`, with exit 5 and `Config is not a defineConfig result`. Nine files are already on disk at that point. Running any ORM command afterwards fails again, differently: the mounted family reads its configuration from an `orm` section of `prisma.config.ts` (`ormConfigSection`, `packages/1-framework/3-tooling/cli/src/orm/config-section.ts` in prisma/prisma), so it reports `CLI.CONFIG_SECTION_INVALID` and `CONFIG.FILE_NOT_FOUND` — "The orm config section is absent, so prisma-next.config.ts was never evaluated." So `prisma orm init && prisma contract emit` cannot work, and the two config surfaces have different shapes: the section nests the whole config under `orm`, while the scaffolded file exports a `defineConfig` result. Which side moves is the ORM's call; that it is broken today is not in question. diff --git a/packages/cli-engine/src/execution/command-context.ts b/packages/cli-engine/src/execution/command-context.ts index 1062b8d9..591bd20b 100644 --- a/packages/cli-engine/src/execution/command-context.ts +++ b/packages/cli-engine/src/execution/command-context.ts @@ -55,24 +55,18 @@ export function makeUi(colorEnabled: boolean, stderr: OutputStream): Ui { /** Materializes ONLY the active format's presentation functions, at the * return site: human → human + stdout + next; json → json + next. * - * `stdout` and `next` may be absent at runtime, so both are called with - * `?.()`. `Presentations` requires all four, so no command compiled - * against this engine can omit one — but `@prisma/orm-toolchain` is - * built against engine `0.0.9`, where three of the four were optional, - * and its published commands took that up: `migration list` declares - * `human` and `json` and neither of the others. Calling them - * unconditionally makes it exit 2 — `stdout` in human mode, `next` in - * both. + * Every one is called unconditionally, because `Presentations` requires + * all four and nothing reaches here that did not satisfy that type. * - * `json` is called unconditionally, and stays that way: a missing json - * presentation is the defect this change removes, and every ORM command - * already declares one. - * - * This is version skew in our own code, not a foreign contract. The fix - * is in prisma/prisma: declare the missing presentations in the ORM - * commands and build orm-toolchain against this engine, where the type - * refuses to compile without them. Delete both `?.()` when that - * version is pinned here. */ + * Two of these calls were briefly written `?.()`, to tolerate + * `@prisma/orm-toolchain` built against engine `0.0.9`, where three of + * the four were optional and its commands took that up. That was a + * consumer working around a producer it shares an owner with. The + * producer was fixed instead (prisma/prisma#30004), and this repo pins + * a version that declares all four, so the defensive calls are gone. + * Anything that omits one now fails loudly rather than silently + * publishing an empty surface — which is the whole point of requiring + * them. */ function materializePresentation( state: RunState, ui: Ui, @@ -83,14 +77,14 @@ function materializePresentation( human: [], stdout: [], json: presentations.json(), - next: presentations.next?.() ?? [], + next: presentations.next(), }; } return { human: presentations.human(ui), - stdout: presentations.stdout?.() ?? [], + stdout: presentations.stdout(), json: undefined, - next: presentations.next?.() ?? [], + next: presentations.next(), }; }