@@ -45,9 +45,9 @@ mutation routes, and read-only finders. A `table` emits the full CRUD surface.
4545 "name" : " AuthorView" ,
4646 "children" : [
4747 { "source.rdb" : { "@kind" : " view" , "@table" : " v_author" } },
48- { "field.long" : { "name" : " id" ,
48+ { "field.long" : { "name" : " id" , "@required" : true ,
4949 "children" : [ { "origin.passthrough" : { "@from" : " Author.id" } } ] } },
50- { "field.string" : { "name" : " name" ,
50+ { "field.string" : { "name" : " name" , "@required" : true ,
5151 "children" : [ { "origin.passthrough" : { "@from" : " Author.name" } } ] } },
5252 { "field.long" : { "name" : " postCount" ,
5353 "children" : [ { "origin.aggregate" : {
@@ -124,13 +124,19 @@ export const authorView = pgView("v_author").as((qb) => qb.selectFrom("authors")
124124export const AuthorViewSchema = z .object ({
125125 id: z .number (),
126126 name: z .string (),
127- postCount: z .number (),
127+ postCount: z .number (). nullable () ,
128128});
129129
130130export type AuthorView = z .infer <typeof AuthorViewSchema >;
131131// no createAuthorView / updateAuthorView / deleteAuthorView — read-only.
132132```
133133
134+ Read-schema nullability mirrors the view column: a field that is not ` @required `
135+ (here ` postCount ` , a derived aggregate) is nullable in the view's SELECT type, so
136+ its Zod read field is emitted as ` .nullable() ` — matching what
137+ ` db.select().from(view) ` actually returns. A ` @required ` field (` id ` , ` name ` ) stays
138+ non-null.
139+
134140### Java
135141
136142OMDB resolves the physical name via ` @table ` ; ` @kind: "view" ` flips the entity to
0 commit comments