-
-
Notifications
You must be signed in to change notification settings - Fork 138
fix(orm): enable TypeScript excess-property checking on where for all CRUD methods #2565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
258b8a7
93cfa6b
5d18867
34add8c
1df1c06
ef5c70e
90655bb
a4cc3b5
8256c24
580efa3
0c4bbc1
5e6a8e1
ff982b9
4edc2b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -484,6 +484,23 @@ export class ZodSchemaFactory< | |
| // expression builder | ||
| fields['$expr'] = z.custom((v) => typeof v === 'function', { error: '"$expr" must be a function' }).optional(); | ||
|
|
||
| // $is sub-model filter for delegate (polymorphic) base models | ||
| const modelDef = requireModel(this.schema, model); | ||
| if (modelDef.isDelegate && modelDef.subModels && modelDef.subModels.length > 0) { | ||
| const subModelSchema = z.object( | ||
| Object.fromEntries( | ||
| modelDef.subModels.map((subModel) => [ | ||
| subModel, | ||
| z | ||
| .lazy(() => this.makeWhereSchema(subModel, false, false, false, options)) | ||
| .nullish() | ||
| .optional(), | ||
| ]), | ||
| ), | ||
| ); | ||
| fields['$is'] = subModelSchema.optional(); | ||
|
Comment on lines
+490
to
+501
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n packages/orm/src/client/zod/factory.ts | sed -n '485,505p'Repository: zenstackhq/zenstack Length of output: 1123 🏁 Script executed: rg -n "subModelSchema\|strictObject" packages/orm/src/client/zod/factory.ts -A 2 -B 2Repository: zenstackhq/zenstack Length of output: 45 🏁 Script executed: rg -n "\$is" packages/orm/src/client/crud/dialects/base-dialect.ts -A 5 -B 2Repository: zenstackhq/zenstack Length of output: 45 🏁 Script executed: rg -n "z\.object|z\.strictObject" packages/orm/src/client/zod/factory.ts -B 1 -A 1 | head -100Repository: zenstackhq/zenstack Length of output: 3776 🏁 Script executed: fd -type f -name "*.ts" -path "*dialects*" | head -10Repository: zenstackhq/zenstack Length of output: 233 🏁 Script executed: rg -n "\\\$is" packages/orm/src/client/crud/ -A 3 -B 1 | head -80Repository: zenstackhq/zenstack Length of output: 1984 🏁 Script executed: rg -n "z\.object\(" packages/orm/src/client/zod/factory.tsRepository: zenstackhq/zenstack Length of output: 111 🏁 Script executed: rg -n "buildIsFilter" packages/orm/src/client/crud/dialects/base-dialect.ts -A 30 | head -80Repository: zenstackhq/zenstack Length of output: 3365 🏁 Script executed: rg -n "createInvalidInputError" packages/orm/src/client/crud/dialects/base-dialect.ts -B 2Repository: zenstackhq/zenstack Length of output: 1781 🏁 Script executed: rg -n "buildIsFilter" packages/orm/src/client/crud/dialects/base-dialect.ts -A 50 | tail -40Repository: zenstackhq/zenstack Length of output: 2244 🏁 Script executed: cat -n packages/orm/src/client/crud/dialects/base-dialect.ts | sed -n '312,360p'Repository: zenstackhq/zenstack Length of output: 2975 Use
🔒 Proposed fix- const subModelSchema = z.object(
+ const subModelSchema = z.strictObject(
Object.fromEntries(
modelDef.subModels.map((subModel) => [
subModel,
z
.lazy(() => this.makeWhereSchema(subModel, false, false, false, options))
.nullish()
.optional(),
]),
),
);🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| // logical operators | ||
| fields['AND'] = this.orArray( | ||
| z.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields, false, options)), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Build the
$isEXISTS subquery frombuildSelectModel()andbuildExistsExpression().subWhereis the fullWhereInputof the sub-model, so it can reference inherited base fields and relations. WithselectFrom(\${subModelName} as ${subAlias}`), aliases likeAsset/Videoare never joined, so a valid filter such as$is: { Video: { viewCount: { gt: 0 } } }will generate broken refs. Also,this.eb.exists(...)` bypasses the dialect hook that handles same-table EXISTS rewrites.🛠 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents