@polyprism/ts-domain-class
v0.3.1
Published
Prisma 6 & 7 generator that emits opinionated TypeScript domain classes — private fields, getters/setters with active @coerce + @normalise, builder, from(), toJSON(). Pure ESM. Part of PolyPrism.
Maintainers
Readme
@polyprism/ts-domain-class
A Prisma 6 & 7 generator that emits opinionated TypeScript domain classes from your schema.prisma. Private fields, getters/setters with setter-driven data laundering, from() static factory, toJSON(), and a fluent builder. Part of PolyPrism.
const order = new Order({
customerId: "cus_123",
total: "10.99", // stringified money from an HTTP API → coerced to Decimal
placedAt: "2026-06-02", // ISO string → coerced to Date
});
await prisma.order.create({ data: order }); // pass directly — no destructurePure ESM, Prisma 7-native, one runtime dep (@polyprism/runtime). CI tests against both Prisma 6 and Prisma 7. The runtime dep is the price of admission for setter-driven data casting; the other PolyPrism patterns (ts-interface, ts-type, ts-class) stay zero-runtime-dep.
Install
pnpm add -D prisma @polyprism/ts-domain-class
pnpm add @polyprism/runtimeNote the split: the generator is a devDependency, the runtime is a real dependency.
Configure
generator polyprismCodegen {
provider = "polyprism-ts-domain-class"
output = "../generated"
}⚠️ The provider string is the bin name (no
@scope/prefix).
Run
pnpm prisma generateWhat you get
- Setter-driven type laundering —
Int/Float/Decimal/BigInt/DateTimefields coerce by default. Strings, booleans, enums, relations, and JSON columns stay strict. @noCoerceto opt a default-coerce field out (e.g. an internal counter you want strictly typed).@coerce(target)to opt a strict-by-default field in (e.g.String @coerce(int)for legacy stringified columns).@normalise(trim, lowercase, uppercase, nullEmptyToNull)to pipe string-typed fields through ordered transforms on assignment.- Constructor:
new User({ ... })— object-arg with defaults applied for fields that have them. - Prisma-friendly:
prisma.user.create({ data: userInstance })works directly because the instance exposes enumerable accessors. NotoData()plumbing. - JSON-safe:
JSON.stringify(userInstance)produces wire-safe output natively. Models withBigIntcolumns also get a customtoJSON()soJSON.stringifydoesn't throw on bigints. User.from(plainObject)static factory — hydrate a class instance from an untrusted shape (HTTP body, Prisma row, queue message). Assigns via setters so@coerce/@normalisefire on the way in; unknown keys are silently dropped.User.builder()...build()fluent builder with one chainable method per init-writable field.- Everything
ts-classgives you (standalone enum files, three-axis naming, JSDoc preservation,@db.Xprecision metadata, etc.).
Sibling patterns
@polyprism/ts-interface—export interface User { ... }@polyprism/ts-type—export type User = { ... };@polyprism/ts-class—export class User { ... }with public fields (no setter pipeline)
License
MIT © Travis Fitzgerald
