|
| 1 | +--- |
| 2 | +"prisma-effect-kysely": minor |
| 3 | +--- |
| 4 | + |
| 5 | +feat: emit `XTable` (Kysely table) + bare `X` (Selectable SELECT row) per table |
| 6 | + |
| 7 | +Each model now generates **two** schemas instead of one, following Kysely's own |
| 8 | +`PersonTable` → `Person` naming convention: |
| 9 | + |
| 10 | +- **`{Name}Table`** — the wrapper-laden struct (`columnType()`/`generated()` |
| 11 | + intact). It drives the Kysely `DB` interface, where its `ColumnType<>`/ |
| 12 | + `Generated<>` brands give `.insertInto`/`.updateTable` their insert/update |
| 13 | + variance. Per Kysely's rule, this table type is never a query-result type. |
| 14 | +- **`{Name}`** (bare) — the SELECT row, `Selectable({Name}Table)` with the |
| 15 | + wrappers stripped. This is the composable, value+type-merged schema that |
| 16 | + contracts, RPC outputs, and decode boundaries bind to. It is derived once by |
| 17 | + the generator, so consumers never re-wrap `Selectable(...)` themselves. |
| 18 | + |
| 19 | +`export type {Name} = typeof {Name}.Type` (the SELECT row type). The `DB` |
| 20 | +interface entry is `Schema.Schema.Type<typeof {Name}Table>` — referencing the |
| 21 | +wrapper-laden table so Kysely query typing keeps working (gated by the |
| 22 | +`kysely-values-type-inference` regression test). |
| 23 | + |
| 24 | +**Why not `@effect/sql` `Model.Class`?** A type spike showed `Model.Class` |
| 25 | +(which encodes insert/update variance in separate `.insert`/`.update` Effect |
| 26 | +schemas) is incompatible with the Kysely `DB` interface: Kysely needs the |
| 27 | +TS-level `ColumnType`/`Generated` wrappers on the table type, which `Model.Class` |
| 28 | +abandons — `db.insertInto(...).values(...)` then demands generated columns. The |
| 29 | +`Table` + bare-row split keeps both the Effect-schema and Kysely-query halves |
| 30 | +working. |
| 31 | + |
| 32 | +This resolves the table-vs-row name clash (bare `X` = row, `XTable` = table) |
| 33 | +and eliminates per-consumer `Selectable(...)` repetition, with no `Model.Class`, |
| 34 | +import aliases, namespace imports, or `*Schema` suffixes. |
| 35 | + |
| 36 | +**Migration for consumers:** the bare `X` export flips from the wrapper-laden |
| 37 | +table to the SELECT row. Replace `Selectable<X>` → `X`, `Selectable(X)` → `X`, |
| 38 | +and `Insertable<X>`/`Updateable<X>` → `Insertable<typeof XTable>`/ |
| 39 | +`Updateable<typeof XTable>`. Join tables (no `XTable` emitted) keep |
| 40 | +`Selectable<JoinTable>`. |
| 41 | + |
| 42 | +Also: `domain-detector` replaces a `@ts-expect-error` with a |
| 43 | +`'schemaLocation' in model` type guard; `JoinTableInfo[]` parameters are now |
| 44 | +`readonly`. |
0 commit comments