Skip to content

Lite schema strips @@@validation attributes, breaking createSchemaFactory client validation #2793

Description

@ErikDakoda

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions