Skip to content

feat(codegen-ts): generate Prisma schema from the model - #502

Merged
dmealing merged 8 commits into
mainfrom
fm/mo-prisma
Oct 28, 2026
Merged

dmealing merged 8 commits into
mainfrom
fm/mo-prisma

Conversation

@dmealing

@dmealing dmealing commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Closes #479.

Gate: one no-mistakes run (run 01M61G2D993T3D3PBVFNHM3QA9, three review fix rounds inside it). CI step skipped by triage (--skip ci).

What Changed

  • Adds the prisma-schema reference generator (prismaSchemaFile(), ejectable via meta eject prisma-schema). With orm: "prisma" in metaobjects.config.ts, meta gen writes schema.prisma for the postgresql, mysql or sqlite provider. Types, ids, defaults, nullability, enums, relations, unique keys, indexes, @map/@@map and Postgres @schema are mapped. CHECK constraints the model implies go to schema.checks.sql, applied with prisma db execute --file.
  • Unsupported shapes are refused with ERR_PRISMA_* codes instead of being dropped. orm: "prisma" defaults every target to runtime: false and rejects runtime: true and the Drizzle-writing generators (queries, routes, routes-hono, callable). The default orm: "drizzle" is unchanged.
  • meta verify --codegen fails on a stale or hand-edited schema.prisma. meta verify --db checks a Prisma-pushed Postgres database against the model, and fixes SQLite type-spelling drift (BOOLEAN/INTEGER, DECIMAL/NUMERIC, TRUE/1). Adds the @metaobjectsdev/migrate-ts/expected subpath, which codegen-ts now imports.
Validation

Risk Assessment

⚠️ Medium: The fix rounds' refusals (views, sqlite/mysql @Schema, flattened objects, handEdits removal, ERR_PRISMA_UNSUPPORTED_SCHEMA export) trace correctly, but the change is large and also edits shared migrate-ts diff and default logic, and I did not read the docs, mirror and fixture files.

Testing

The pushed-then-verified SQLite scenario passed live through the real Prisma CLI. I also drove the refusals and mappings live through meta gen. Flattened objects map to addressStreet with @Map("address_street"). A non-default @Schema is refused with ERR_PRISMA_UNSUPPORTED_SCHEMA on sqlite and mysql, and emitted as @@Schema on postgres. A flattened-object model passes meta verify --db after prisma db push. ci-local.sh --quick flagged reference templates lint (biome useTemplate on a string concatenation in the Prisma reference template). I fixed it in both byte-identical copies (src/reference/prisma-schema.ts and src/generators/prisma-schema-file.ts); the byte-identical test, prisma tests and the full gates lane are green afterwards. The stryker mutation completeness gate (1765 mutants) hit my timeout and did not finish. The Postgres db push integration case was skipped because MIGRATE_TS_PG_URL is unset. There is no UI surface, so no screenshots apply.

  • Live validation: ✅ go - 5 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Prisma shop: meta gen writes schema.prisma, prisma validate accepts it, hand edit fails verify --codegen ✅ pass live cli test/integration/prisma-schema.test.ts (real prisma CLI)
prisma db push on SQLite, then meta verify --db differs only by CHECKs; added stray column fails ✅ pass live cli test/integration/prisma-schema.test.ts (sqlite)
Flattened object field maps to prefixed columns and verifies against a pushed DB ✅ pass live Temporary driver run: gen output and verify --db exit 0
Non-default @Schema refused with ERR_PRISMA_UNSUPPORTED_SCHEMA on sqlite and mysql, emitted on postgres ✅ pass live Temporary driver run: gen output
Postgres prisma db push then meta verify --db ⏸️ untested no MIGRATE_TS_PG_URL not set and no Postgres server was started; docker is installed but I did not start a container. Set MIGRATE_TS_PG_URL to a Postgres server to run it.
Reference template lint gate clean ✅ pass live scripts/ci-local.sh --only gates after fix
Evidence: Live gen outputs (summary)
flattened-pg: exit 0, model Person has addressStreet @map("address_street") @db.VarChar(50), addressCity @map("address_city")
schema-sqlite: exit 1, ERR_PRISMA_UNSUPPORTED_SCHEMA: 'a::b::Person' declares @schema 'hr' ... only on postgresql
schema-mysql: exit 1, ERR_PRISMA_UNSUPPORTED_SCHEMA (same refusal)
schema-pg-ok: exit 0, @@schema("hr"), schemas = ["hr", "public"]
flattened sqlite: prisma db push in sync; meta verify --db exit 0

Pipeline

Updates from git push no-mistakes

✅ **Intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 3 infos
  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:181 - The generator drops a write-through entity's replica view without an error. This breaks the module's own rule ('refused, never dropped') and the documented claim that a pushed database passes meta verify --db. isManagedReadOnly refuses an object only when it has no writable source (!hasWritableRdbSource). A write-through entity (FR-024 §7: @role: primary table plus a @role: replica @kind: view source) has a writable table, so it passes. Its view is then lost, because buildPrismaSchema reads only snapshot.tables and never asks for views. The CLI's verify --db adds that view through buildProjectionViews (its second loop, root.objects().filter(isWriteThrough)), so the failure path is: prisma db push from the generated schema, then meta verify --db reports the view as missing, and the generator never said anything. Sibling sites with the same problem: (1) on MySQL the generator ignores @schema (multiSchema is Postgres-only, build-prisma-schema.ts:714-715), so tables that declare different schemas collapse into one namespace and the schema is lost without an error. (2) The other direction: a projection on @kind: storedProc/tableFunction/materializedView is refused, and the message says meta verify --db 'would report it missing'. That is false, because classifyReadOnlySource skips those kinds and verify does not expect them. Earliest shared fix: build the refusal set from what verify --db actually expects. Call buildProjectionViews(root, { dialect }) (it lives in codegen-ts) and refuse each view whose fqn object passes matches. On MySQL, refuse a non-default @schema, or emit @@schema there too.
  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:676 - An entity with a field.object @storage: "flattened" field makes the generator throw a plain Error ('no field of ... maps to column ...'). It never returns a PrismaSchemaError and never produces a model. flattenObjectField in migrate-ts expected-schema.ts expands the field into one column per nested value-object field, named <parent_col>_<nested_col> (for example address_street). fieldsByColumn (line 198) maps only the entity's own fields by resolveColumnName, so no entry matches those columns. Flattened storage is documented vocabulary, so a Prisma adopter who uses it gets an internal-looking crash, not a mapping or a named refusal. The column-type mappers (sqliteColumnType, mysqlColumnType) also need the nested field's subtype. Fix: map each flattened column to its nested field, with a synthesized Prisma name such as addressStreet and @map("address_street"). Or refuse it with a PrismaSchemaError code that names the field and the fix.
  • ⚠️ server/typescript/packages/codegen-ts/src/generators/prisma-schema-file.ts:53 - Simplification: the handEdits option of prismaSchemaFile() (also in reference/prisma-schema.ts:73, the registry options string and the recipe) is not needed for the stated intent, which is one place to declare a field and a build that fails on drift. It also contradicts the generator's own reasoning. The header says a merged hand edit 'would change the database without the model knowing', yet the option lets an adopter set "merge"/"keep" and do exactly that. An adopter who wants different behaviour can eject the generator. Recommended remedy: remove the option and hard-code handEdits: "overwrite".
  • ℹ️ docs/recipes/prisma.md:149 - Fixed the refusal table's ERR_PRISMA_UNSUPPORTED_INDEX row. It said every @using is refused, but the code maps Postgres hash/gin/gist/brin/spgist to @@index(type: ...) and refuses only other methods. Made the same edit in the three mirrors so recipe-mirrors and agent-context-conformance stay byte-equal: agent-context/skills/metaobjects-codegen/references/typescript-prisma.md:128, and fixtures/agent-context-conformance/{ts-react-tanstack,ts-requirements}/expected/.claude/skills/metaobjects-codegen/references/typescript-prisma.md:128.
  • ℹ️ CHANGELOG.md:26 - Corrected the CHANGELOG claim that a database pushed by prisma db push 'passes meta verify --db ... on Postgres and SQLite'. On SQLite, checks: "omit" is required, and the gate reports each missing CHECK, as the recipe and the integration test both state. The entry now says that Postgres passes once the checks file is applied, and that SQLite reports only the missing CHECKs.
  • ⚠️ docs/recipes/prisma.md:149 - The new ERR_PRISMA_UNSUPPORTED_INDEX row says a @using method other than Postgres hash/gin/gist/brin/spgist is refused. That wording is still wrong for one case: build-prisma-schema.ts indexAttributes also accepts @using: btree on every provider (ix.using.toLowerCase() !== "btree"), so a btree index is never refused. Change the cell to read: "... or a @using method other than btree or, on Postgres, hash, gin, gist, brin or spgist". Make the same edit in the three byte-equal mirrors: agent-context/skills/metaobjects-codegen/references/typescript-prisma.md:128 and fixtures/agent-context-conformance/{ts-react-tanstack,ts-requirements}/expected/.claude/skills/metaobjects-codegen/references/typescript-prisma.md:128.

🔧 Fix applied.
7 issues (5 warnings, 2 infos) still open:

  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:181 - The generator drops a write-through entity's replica view without an error. This breaks the module's own rule ('refused, never dropped') and the documented claim that a pushed database passes meta verify --db. isManagedReadOnly refuses an object only when it has no writable source (!hasWritableRdbSource). A write-through entity (FR-024 §7: @role: primary table plus a @role: replica @kind: view source) has a writable table, so it passes. Its view is then lost, because buildPrismaSchema reads only snapshot.tables and never asks for views. The CLI's verify --db adds that view through buildProjectionViews (its second loop, root.objects().filter(isWriteThrough)), so the failure path is: prisma db push from the generated schema, then meta verify --db reports the view as missing, and the generator never said anything. Sibling sites with the same problem: (1) on MySQL the generator ignores @schema (multiSchema is Postgres-only, build-prisma-schema.ts:714-715), so tables that declare different schemas collapse into one namespace and the schema is lost without an error. (2) The other direction: a projection on @kind: storedProc/tableFunction/materializedView is refused, and the message says meta verify --db 'would report it missing'. That is false, because classifyReadOnlySource skips those kinds and verify does not expect them. Earliest shared fix: build the refusal set from what verify --db actually expects. Call buildProjectionViews(root, { dialect }) (it lives in codegen-ts) and refuse each view whose fqn object passes matches. On MySQL, refuse a non-default @schema, or emit @@schema there too.
  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:676 - An entity with a field.object @storage: "flattened" field makes the generator throw a plain Error ('no field of ... maps to column ...'). It never returns a PrismaSchemaError and never produces a model. flattenObjectField in migrate-ts expected-schema.ts expands the field into one column per nested value-object field, named <parent_col>_<nested_col> (for example address_street). fieldsByColumn (line 198) maps only the entity's own fields by resolveColumnName, so no entry matches those columns. Flattened storage is documented vocabulary, so a Prisma adopter who uses it gets an internal-looking crash, not a mapping or a named refusal. The column-type mappers (sqliteColumnType, mysqlColumnType) also need the nested field's subtype. Fix: map each flattened column to its nested field, with a synthesized Prisma name such as addressStreet and @map("address_street"). Or refuse it with a PrismaSchemaError code that names the field and the fix.
  • ⚠️ server/typescript/packages/codegen-ts/src/generators/prisma-schema-file.ts:53 - Simplification: the handEdits option of prismaSchemaFile() (also in reference/prisma-schema.ts:73, the registry options string and the recipe) is not needed for the stated intent, which is one place to declare a field and a build that fails on drift. It also contradicts the generator's own reasoning. The header says a merged hand edit 'would change the database without the model knowing', yet the option lets an adopter set "merge"/"keep" and do exactly that. An adopter who wants different behaviour can eject the generator. Recommended remedy: remove the option and hard-code handEdits: "overwrite".
  • ℹ️ docs/recipes/prisma.md:149 - Fixed the refusal table's ERR_PRISMA_UNSUPPORTED_INDEX row. It said every @using is refused, but the code maps Postgres hash/gin/gist/brin/spgist to @@index(type: ...) and refuses only other methods. Made the same edit in the three mirrors so recipe-mirrors and agent-context-conformance stay byte-equal: agent-context/skills/metaobjects-codegen/references/typescript-prisma.md:128, and fixtures/agent-context-conformance/{ts-react-tanstack,ts-requirements}/expected/.claude/skills/metaobjects-codegen/references/typescript-prisma.md:128.
  • ℹ️ CHANGELOG.md:26 - Corrected the CHANGELOG claim that a database pushed by prisma db push 'passes meta verify --db ... on Postgres and SQLite'. On SQLite, checks: "omit" is required, and the gate reports each missing CHECK, as the recipe and the integration test both state. The entry now says that Postgres passes once the checks file is applied, and that SQLite reports only the missing CHECKs.
  • ⚠️ docs/recipes/prisma.md:149 - The new ERR_PRISMA_UNSUPPORTED_INDEX row says a @using method other than Postgres hash/gin/gist/brin/spgist is refused. That wording is still wrong for one case: build-prisma-schema.ts indexAttributes also accepts @using: btree on every provider (ix.using.toLowerCase() !== "btree"), so a btree index is never refused. Change the cell to read: "... or a @using method other than btree or, on Postgres, hash, gin, gist, brin or spgist". Make the same edit in the three byte-equal mirrors: agent-context/skills/metaobjects-codegen/references/typescript-prisma.md:128 and fixtures/agent-context-conformance/{ts-react-tanstack,ts-requirements}/expected/.claude/skills/metaobjects-codegen/references/typescript-prisma.md:128.
  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:683 - Fix round 2 (the @Schema sibling of prisma-write-through-view-dropped) added refuseSchema for non-Postgres providers, and the CHANGELOG and recipe say a @schema outside Postgres gets an ERR_PRISMA_* code. That holds for MySQL only. On provider: "sqlite", buildExpectedSchemaWithProvenance(root, { dialect: "sqlite" }) (line 672) throws first. migrate-ts expected-schema.ts:329-336 throws a plain Error('sqlite does not support DB schemas; ...') for any table with a @schema, including objects matches would exclude. So refuseSchema is unreachable for sqlite, and the sqlite case is neither a PrismaSchemaError nor filterable. The new test covers mysql only. Fix: check @schema for sqlite before building the expected schema (or build the schema with the postgres dialect for the check) so sqlite also raises ERR_PRISMA_UNSUPPORTED_SCHEMA and respects matches; add a sqlite case to the test.

🔧 Fix applied.
9 issues (6 warnings, 3 infos) still open:

  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:181 - The generator drops a write-through entity's replica view without an error. This breaks the module's own rule ('refused, never dropped') and the documented claim that a pushed database passes meta verify --db. isManagedReadOnly refuses an object only when it has no writable source (!hasWritableRdbSource). A write-through entity (FR-024 §7: @role: primary table plus a @role: replica @kind: view source) has a writable table, so it passes. Its view is then lost, because buildPrismaSchema reads only snapshot.tables and never asks for views. The CLI's verify --db adds that view through buildProjectionViews (its second loop, root.objects().filter(isWriteThrough)), so the failure path is: prisma db push from the generated schema, then meta verify --db reports the view as missing, and the generator never said anything. Sibling sites with the same problem: (1) on MySQL the generator ignores @schema (multiSchema is Postgres-only, build-prisma-schema.ts:714-715), so tables that declare different schemas collapse into one namespace and the schema is lost without an error. (2) The other direction: a projection on @kind: storedProc/tableFunction/materializedView is refused, and the message says meta verify --db 'would report it missing'. That is false, because classifyReadOnlySource skips those kinds and verify does not expect them. Earliest shared fix: build the refusal set from what verify --db actually expects. Call buildProjectionViews(root, { dialect }) (it lives in codegen-ts) and refuse each view whose fqn object passes matches. On MySQL, refuse a non-default @schema, or emit @@schema there too.
  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:676 - An entity with a field.object @storage: "flattened" field makes the generator throw a plain Error ('no field of ... maps to column ...'). It never returns a PrismaSchemaError and never produces a model. flattenObjectField in migrate-ts expected-schema.ts expands the field into one column per nested value-object field, named <parent_col>_<nested_col> (for example address_street). fieldsByColumn (line 198) maps only the entity's own fields by resolveColumnName, so no entry matches those columns. Flattened storage is documented vocabulary, so a Prisma adopter who uses it gets an internal-looking crash, not a mapping or a named refusal. The column-type mappers (sqliteColumnType, mysqlColumnType) also need the nested field's subtype. Fix: map each flattened column to its nested field, with a synthesized Prisma name such as addressStreet and @map("address_street"). Or refuse it with a PrismaSchemaError code that names the field and the fix.
  • ⚠️ server/typescript/packages/codegen-ts/src/generators/prisma-schema-file.ts:53 - Simplification: the handEdits option of prismaSchemaFile() (also in reference/prisma-schema.ts:73, the registry options string and the recipe) is not needed for the stated intent, which is one place to declare a field and a build that fails on drift. It also contradicts the generator's own reasoning. The header says a merged hand edit 'would change the database without the model knowing', yet the option lets an adopter set "merge"/"keep" and do exactly that. An adopter who wants different behaviour can eject the generator. Recommended remedy: remove the option and hard-code handEdits: "overwrite".
  • ℹ️ docs/recipes/prisma.md:149 - Fixed the refusal table's ERR_PRISMA_UNSUPPORTED_INDEX row. It said every @using is refused, but the code maps Postgres hash/gin/gist/brin/spgist to @@index(type: ...) and refuses only other methods. Made the same edit in the three mirrors so recipe-mirrors and agent-context-conformance stay byte-equal: agent-context/skills/metaobjects-codegen/references/typescript-prisma.md:128, and fixtures/agent-context-conformance/{ts-react-tanstack,ts-requirements}/expected/.claude/skills/metaobjects-codegen/references/typescript-prisma.md:128.
  • ℹ️ CHANGELOG.md:26 - Corrected the CHANGELOG claim that a database pushed by prisma db push 'passes meta verify --db ... on Postgres and SQLite'. On SQLite, checks: "omit" is required, and the gate reports each missing CHECK, as the recipe and the integration test both state. The entry now says that Postgres passes once the checks file is applied, and that SQLite reports only the missing CHECKs.
  • ⚠️ docs/recipes/prisma.md:149 - The new ERR_PRISMA_UNSUPPORTED_INDEX row says a @using method other than Postgres hash/gin/gist/brin/spgist is refused. That wording is still wrong for one case: build-prisma-schema.ts indexAttributes also accepts @using: btree on every provider (ix.using.toLowerCase() !== "btree"), so a btree index is never refused. Change the cell to read: "... or a @using method other than btree or, on Postgres, hash, gin, gist, brin or spgist". Make the same edit in the three byte-equal mirrors: agent-context/skills/metaobjects-codegen/references/typescript-prisma.md:128 and fixtures/agent-context-conformance/{ts-react-tanstack,ts-requirements}/expected/.claude/skills/metaobjects-codegen/references/typescript-prisma.md:128.
  • ⚠️ server/typescript/packages/codegen-ts/src/prisma/build-prisma-schema.ts:683 - Fix round 2 (the @Schema sibling of prisma-write-through-view-dropped) added refuseSchema for non-Postgres providers, and the CHANGELOG and recipe say a @schema outside Postgres gets an ERR_PRISMA_* code. That holds for MySQL only. On provider: "sqlite", buildExpectedSchemaWithProvenance(root, { dialect: "sqlite" }) (line 672) throws first. migrate-ts expected-schema.ts:329-336 throws a plain Error('sqlite does not support DB schemas; ...') for any table with a @schema, including objects matches would exclude. So refuseSchema is unreachable for sqlite, and the sqlite case is neither a PrismaSchemaError nor filterable. The new test covers mysql only. Fix: check @schema for sqlite before building the expected schema (or build the schema with the postgres dialect for the check) so sqlite also raises ERR_PRISMA_UNSUPPORTED_SCHEMA and respects matches; add a sqlite case to the test.
  • ⚠️ server/typescript/packages/codegen-ts/src/index.ts:492 - The package-root export list for the Prisma error codes omits ERR_PRISMA_UNSUPPORTED_SCHEMA. The constant is defined in prisma/prisma-errors.ts:11, listed in PRISMA_ERROR_CODES, raised by refuseSchema in build-prisma-schema.ts, and documented in the recipe and the skill mirrors. The other seven codes are exported. The index comment says the pure stages are public so an owned (ejected) copy 'imports only this package'. A consumer that catches PrismaSchemaError and compares e.code to this one constant cannot import it from @metaobjectsdev/codegen-ts. The in-repo test imports it from src/prisma/prisma-errors.js, so nothing fails today. Fix: add ERR_PRISMA_UNSUPPORTED_SCHEMA to the export block at index.ts:486-492.
  • ℹ️ CHANGELOG.md:29 - The entry says what a Prisma schema cannot express 'is refused with an ERR_PRISMA_* code, never dropped'. On MySQL, checksOf (build-prisma-schema.ts:623-638) silently leaves out every CHECK that is not enum membership (the validator.length and validator.numeric checks). It does this without an error and meta verify --db does not support MySQL, so nothing reports them. The recipe table and 'SQLite and MySQL' section state this, but the CHANGELOG sentence reads as absolute. Reword it to say MySQL gets the enum checks only, as the recipe does.

🔧 Fix applied.
3 infos still open:

  • ℹ️ docs/recipes/prisma.md:149 - Fixed the refusal table's ERR_PRISMA_UNSUPPORTED_INDEX row. It said every @using is refused, but the code maps Postgres hash/gin/gist/brin/spgist to @@index(type: ...) and refuses only other methods. Made the same edit in the three mirrors so recipe-mirrors and agent-context-conformance stay byte-equal: agent-context/skills/metaobjects-codegen/references/typescript-prisma.md:128, and fixtures/agent-context-conformance/{ts-react-tanstack,ts-requirements}/expected/.claude/skills/metaobjects-codegen/references/typescript-prisma.md:128.
  • ℹ️ CHANGELOG.md:26 - Corrected the CHANGELOG claim that a database pushed by prisma db push 'passes meta verify --db ... on Postgres and SQLite'. On SQLite, checks: "omit" is required, and the gate reports each missing CHECK, as the recipe and the integration test both state. The entry now says that Postgres passes once the checks file is applied, and that SQLite reports only the missing CHECKs.
  • ℹ️ server/typescript/packages/codegen-ts/src/reference/prisma-schema.ts:20 - The header of the ejected template lists prismaChecksFileName next to fileName as an option that decides where the files land. There is no such option: PrismaSchemaFileOptions has no field of that name, and prismaChecksFileName is a private function (line 91) that derives <name>.checks.sql from fileName. An adopter who reads the header and passes prismaChecksFileName gets a type error. Fix: delete the name from the parenthesis, and say the checks file name follows fileName.
✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 5 of 6 scenarios driven live against the product
Scenario Result Live Evidence
Prisma shop: meta gen writes schema.prisma, prisma validate accepts it, hand edit fails verify --codegen ✅ pass live cli test/integration/prisma-schema.test.ts (real prisma CLI)
prisma db push on SQLite, then meta verify --db differs only by CHECKs; added stray column fails ✅ pass live cli test/integration/prisma-schema.test.ts (sqlite)
Flattened object field maps to prefixed columns and verifies against a pushed DB ✅ pass live Temporary driver run: gen output and verify --db exit 0
Non-default @Schema refused with ERR_PRISMA_UNSUPPORTED_SCHEMA on sqlite and mysql, emitted on postgres ✅ pass live Temporary driver run: gen output
Postgres prisma db push then meta verify --db ⏸️ untested no MIGRATE_TS_PG_URL not set and no Postgres server was started; docker is installed but I did not start a container. Set MIGRATE_TS_PG_URL to a Postgres server to run it.
Reference template lint gate clean ✅ pass live scripts/ci-local.sh --only gates after fix
  • scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains
  • bun test test/prisma test/reference-byte-identical.test.ts test/generator-registry.test.ts test/metaobjects-config.test.ts in codegen-ts (192 pass)
  • bun test test/integration/prisma-schema.test.ts in cli: real gen, prisma validate/format, prisma db push, meta verify --codegen and --db on SQLite (4 pass, Postgres case skipped)
  • Temporary driver (deleted afterwards): real meta gen for flattened-object fields on postgres and sqlite, and @schema on sqlite, mysql and postgres
  • Temporary driver: flattened-object model on sqlite, prisma db push, then meta verify --db (exit 0)
  • scripts/ci-local.sh --quick: conformance typescript and ts unit suites passed; run killed at my 590s cap during the stryker mutation gate
  • scripts/ci-local.sh --only gates after the lint fix: all gates green
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

…risma" (#479)

A project that keeps Prisma as its ORM now declares each field once, in the
MetaObjects model, and the build fails when Prisma and the model drift.

- New `prisma-schema` reference generator (`prismaSchemaFile()`), for the
  postgresql, mysql and sqlite providers. It builds on the expected schema that
  `meta migrate` writes and `meta verify --db` compares against. It maps types,
  ids, defaults, nullability, enums, relations, unique keys, indexes, @map/@@Map
  and Postgres @@Schema. CHECK constraints go in a companion schema.checks.sql.
  What Prisma cannot express is refused with an ERR_PRISMA_* code, not dropped.
  Hand edits are overwritten, so `verify --codegen` fails on one. The generator
  is ejectable and byte-identical to its reference copy.
- New `orm` config switch. `orm: "prisma"` defaults every target to
  runtime: false and refuses runtime: true and the Drizzle-bound generators
  (queries, routes, routes-hono, callable). `orm: "drizzle"` is the default.
- migrate-ts: a new `@metaobjectsdev/migrate-ts/expected` subpath (no kysely).
  `@default: "now"` is now the expression now(), so Postgres no longer stamps
  every row with the table's creation time. SQLite verify accepts BOOLEAN,
  DECIMAL(p,s) and TRUE/FALSE defaults as the INTEGER, NUMERIC and 1/0 they
  store as.
- Tests: goldens for all three providers and every refusal; an integration test
  running `prisma validate` and `prisma format`, `verify --codegen`, and
  `prisma db push` then `meta verify --db` on SQLite and real Postgres, passing
  and then failing on drift. The Postgres half runs in the ts-slow lane.
- Docs: docs/recipes/prisma.md plus its codegen-skill mirror, the TS port doc,
  the README matrix, llms.txt, and the fit-assessment notes that said no
  generator targets Prisma.
@dmealing
dmealing merged commit 170a5fe into main Oct 28, 2026
1 check passed
@dmealing
dmealing deleted the fm/mo-prisma branch October 28, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prisma support: generate or cross-check schema.prisma from the model

1 participant