v3: Custom JSON types ignore field validation attributes and type-level @@validate
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 65/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- node.js, postgresql, typescript
- Ambito
- backend
Direzione di ricerca
The payload points at ZodSchemaFactory.makeTypeDefSchema in the @zenstackhq/orm schema factory: it calls makeScalarSchema(def.type) without the field's def.attributes and does not apply type-level typeDef.attributes through the custom-validation helper. Start by running the provided schema.zmodel and repro.ts to confirm the six invalid mutations are accepted. Then trace how scalar fields pass attributes into validation and how the validateInput option gates the helpers. Done means all six invalid creates and updates are rejected while the wrong-scalar-type and unknown-key controls still reject.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Description and expected behavior
With validateInput: true, direct ORM creates and updates accept custom JSON values that violate @length, @gte, and type-level @@validate rules. The schema generates successfully and contains those validation attributes.
Expected: mutation input should be rejected when it violates those declared rules, including rules inside custom JSON types. Each update below replaces the entire JSON object, so this does not depend on validating omitted fields from a partial object.
@@strict and basic scalar-type checks still reject invalid input; this is specifically missing enforcement of the validation attributes.
Minimal reproduction
Create a fresh ESM project (package.json containing {"private":true,"type":"module"}), then install:
pnpm add @zenstackhq/[email protected] @zenstackhq/[email protected] @zenstackhq/[email protected] @zenstackhq/[email protected] [email protected] [email protected] [email protected]
Set DATABASE_URL to an empty disposable PostgreSQL database. The script creates an Example table there. Save the following files, then run:
pnpm exec zen generate --schema schema.zmodel
pnpm exec tsx repro.ts
schema.zmodel
datasource db {
provider = "postgresql"
}
type Bounds {
caption String @length(1, 3)
low Int @gte(0)
high Int
@@validate(low <= high)
@@strict
}
model Example {
id Int @id
bounds Bounds @json
}
repro.ts
import { ZenStackClient } from '@zenstackhq/orm';
import { PostgresDialect } from '@zenstackhq/orm/dialects/postgres';
import { Pool } from 'pg';
import { schema } from './schema';
const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 1 });
const db = new ZenStackClient(schema, {
dialect: new PostgresDialect({ pool }),
validateInput: true,
});
try {
await pool.query('CREATE TABLE "Example" (id integer PRIMARY KEY, bounds jsonb NOT NULL)');
const invalid = [
{ caption: 'too long', low: 0, high: 1 },
{ caption: 'ok', low: -1, high: 1 },
{ caption: 'ok', low: 5, high: 1 },
];
for (const [index, bounds] of invalid.entries()) {
console.log('create', JSON.stringify(await db.example.create({ data: { id: index + 1, bounds } })));
}
for (const bounds of invalid) {
console.log('update', JSON.stringify(await db.example.update({ where: { id: 1 }, data: { bounds } })));
}
for (const [label, bounds] of [
['wrong scalar type', { caption: 'ok', low: 'zero', high: 1 }],
['unknown key', { caption: 'ok', low: 0, high: 1, extra: true }],
] as const) {
try {
// These control cases intentionally bypass static structural checks.
await db.example.create({ data: { id: 99, bounds: bounds as any } });
console.log(label, 'accepted');
} catch {
console.log(label, 'rejected');
}
}
} finally {
await pool.end();
}
Actual output
create {"id":1,"bounds":{"low":0,"high":1,"caption":"too long"}}
create {"id":2,"bounds":{"low":-1,"high":1,"caption":"ok"}}
create {"id":3,"bounds":{"low":5,"high":1,"caption":"ok"}}
update {"id":1,"bounds":{"low":0,"high":1,"caption":"too long"}}
update {"id":1,"bounds":{"low":-1,"high":1,"caption":"ok"}}
update {"id":1,"bounds":{"low":5,"high":1,"caption":"ok"}}
wrong scalar type rejected
unknown key rejected
All six printed creates/updates should reject:
caption: "too long"violates@length(1, 3).low: -1violates@gte(0).low: 5, high: 1violates@@validate(low <= high).
The last two lines are controls showing that basic structural validation and @@strict remain active. The as any applies only to those deliberately malformed control cases; the six incorrectly accepted mutations need no cast.
Environment
- ZenStack: 3.9.4, stock npm packages, no patches
- PostgreSQL: 16.15
- Node.js: 22.14.0
- Package manager: pnpm 11.25.0
pg: 8.21.0; Zod: 4.5.4;tsx: 4.19.0- Direct
ZenStackClientwithvalidateInput: true; no plugins
Additional context
In 3.9.4, ZodSchemaFactory.makeTypeDefSchema calls makeScalarSchema(def.type) without the field's def.attributes, and does not apply typeDef.attributes through the custom-validation helper. This appears to explain the behavior. Passing the field annotations and applying type-level validation through the existing helpers, while respecting the validation option, seems like a targeted fix.
- Lingua principale
- TypeScript
- Stelle
- 2.9k
- Fork
- 157
- Merge medio
- 11h 42m
- PR unite (30g)
- 20
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di zenstackhq/zenstack
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
zenstackhq/zenstack#2873 ·
I maintainer di solito rispondono entro 1 giorno
-
runtime
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
zenstackhq/zenstack#2868 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
zenstackhq/zenstack#2694 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 68/100
zenstackhq/zenstack#2659 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
zenstackhq/zenstack#2542 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di zenstackhq/zenstack
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
MystenLabs/MemWal#1163 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Mondriaan
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
knaw-huc/textannoviz#709 ·
I maintainer di solito rispondono entro 1 giorno
-
billion-context-pi
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
ranxianglei/billion-context#2521 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Add: YRF Music NepalApertastreams:add
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100