Problem
zen generate --lite (and liteOnly) drops all attributes from the emitted TypeScript schema — both model-level and field-level — via TsSchemaGenerator:
- model:
const allAttributes = lite ? [] : getAllAttributes(dm)...
- field:
if (!lite && field.attributes.length > 0) ...
Additionally, createTypeDefObject always emits every typedef attribute (including policy @@allow / @@deny), even in lite mode — the opposite inconsistency.
This silently breaks the documented client-side createSchemaFactory / @zenstackhq/zod path: addStringValidation / addNumberValidation read fieldDef.attributes, so with a lite schema they emit bare z.string() / z.number() with no .min() / .max() / .regex() / .date() / .time() / etc.
Verified still present in 3.8.3 and 3.9.0. There is no CLI flag to keep validation attributes in lite mode.
Symptom (before / after)
User.dateOfBirth String? @date (formerly @regex ISO date):
- Full
schema.ts: field has attributes: [{ name: "@date" }] → factory emits z.string().date() → editor renders a DatePicker and validates inline.
- Lite
schema-lite.ts: no attributes → factory emits bare z.string() → editor renders a plain text field; invalid values surface as server ORMError INVALID_INPUT toasts instead of inline zod errors. Char counters from @length also disappear (stringLengthLimitsOfZodSchema finds no checks).
Proposed fix
In lite mode, keep attributes whose resolved declaration carries the stdlib @@@validation marker (@length, @regex, @email, @url, @datetime, @date, @time, @phone, @startsWith, @endsWith, @contains, @trim, @lower, @upper, @gt, @gte, @lt, @lte, and model-level @@validate). Whitelist by the marker, not by name — so policy attributes can never leak into the client bundle.
Apply the same filter in createTypeDefObject (today it emits all typedef attributes unconditionally, which can leak policy into lite).
Optional: gate behind --lite-validation if a hard break of current lite output is a concern; defaulting it on would match the documented factory usage.
Workaround
We currently re-emit schema-lite.ts after zen generate with a local script that patches TsSchemaGenerator prototype methods and filters by @@@validation. Happy to turn that into a PR against ts-schema-generator.ts if maintainers are open to it.
Environment
@zenstackhq/sdk / cli / zod 3.9.0
- Client schemas via
createSchemaFactory(schemaLite)
Problem
zen generate --lite(andliteOnly) drops all attributes from the emitted TypeScript schema — both model-level and field-level — viaTsSchemaGenerator:const allAttributes = lite ? [] : getAllAttributes(dm)...if (!lite && field.attributes.length > 0) ...Additionally,
createTypeDefObjectalways emits every typedef attribute (including policy@@allow/@@deny), even in lite mode — the opposite inconsistency.This silently breaks the documented client-side
createSchemaFactory/@zenstackhq/zodpath:addStringValidation/addNumberValidationreadfieldDef.attributes, so with a lite schema they emit barez.string()/z.number()with no.min()/.max()/.regex()/.date()/.time()/ etc.Verified still present in 3.8.3 and 3.9.0. There is no CLI flag to keep validation attributes in lite mode.
Symptom (before / after)
User.dateOfBirth String? @date(formerly@regexISO date):schema.ts: field hasattributes: [{ name: "@date" }]→ factory emitsz.string().date()→ editor renders a DatePicker and validates inline.schema-lite.ts: noattributes→ factory emits barez.string()→ editor renders a plain text field; invalid values surface as serverORMError INVALID_INPUTtoasts instead of inline zod errors. Char counters from@lengthalso disappear (stringLengthLimitsOfZodSchemafinds no checks).Proposed fix
In lite mode, keep attributes whose resolved declaration carries the stdlib
@@@validationmarker (@length,@regex,@email,@url,@datetime,@date,@time,@phone,@startsWith,@endsWith,@contains,@trim,@lower,@upper,@gt,@gte,@lt,@lte, and model-level@@validate). Whitelist by the marker, not by name — so policy attributes can never leak into the client bundle.Apply the same filter in
createTypeDefObject(today it emits all typedef attributes unconditionally, which can leak policy into lite).Optional: gate behind
--lite-validationif a hard break of current lite output is a concern; defaulting it on would match the documented factory usage.Workaround
We currently re-emit
schema-lite.tsafterzen generatewith a local script that patchesTsSchemaGeneratorprototype methods and filters by@@@validation. Happy to turn that into a PR againstts-schema-generator.tsif maintainers are open to it.Environment
@zenstackhq/sdk/cli/zod3.9.0createSchemaFactory(schemaLite)