Skip to content

Commit 1811798

Browse files
committed
no-mistakes(document): docs: projection read-type nullability mirrors view column
1 parent 84cde02 commit 1811798

2 files changed

Lines changed: 17 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
77

88
## [Unreleased]
99

10+
### Fixed
11+
- **codegen-ts — projection read-type nullability** now mirrors the view column:
12+
a non-`@required` projection field generates a nullable Drizzle view column but
13+
previously kept a non-null Zod read type, so the generated projection query
14+
returned `T | null` into a non-null `<Name>` field and failed to compile under
15+
strict TS. The read field is now emitted as `.nullable()` whenever its view
16+
column is not `.notNull()`, so the read type matches the view's SELECT type.
17+
1018
## [0.12.4] — 2026-06-27
1119

1220
_npm `0.12.4` (full lockstep across all 13 `@metaobjectsdev/*` publish candidates)._

docs/features/source-kinds.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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")
124124
export const AuthorViewSchema = z.object({
125125
id: z.number(),
126126
name: z.string(),
127-
postCount: z.number(),
127+
postCount: z.number().nullable(),
128128
});
129129

130130
export 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

136142
OMDB resolves the physical name via `@table`; `@kind: "view"` flips the entity to

0 commit comments

Comments
 (0)