Skip to content

Run validators in generated code: TypeScript and cross-schema validators (phase 4d) #96

Open

Description

@Kinflou

Validators are checked at comline build but never run: no generator reads @validators. The design is already written up in docs/design/validators.md ("Phase 4 — runtime enforcement"). This issue tracks building it.

Steps (from the design note)

  • 4a. Freeze the validate { assert(...) } condition as a tree Done in feat!: structured types and literals in the frozen IR #108. FrozenUnit::Assert now carries expr: Condition: a flat first comparison plus rest: Vec<(LogicalOp, Comparison)>, grouped left to right because the grammar has no precedence. The operands are Path / Integer / String. The text and references are kept alongside.
  • 4b. Done for Rust (comline-rust#52, runtime#12, generation#57). Generated types implement comline_runtime::validation::Validate (validate() collects, validate_first() stops at one). field is the path to the value (friends[1], author.handle), and checks recurse into nested structs and array elements. Resolution, including alias chains and property binding, lives in comline_codegen::validation.
  • 4c. Done for Rust (cli#71). validate_on_decode = "off" | "collect" | "first", default off. Structs and errors decode through an unchecked shadow via #[serde(try_from)]; the dispatcher refuses a call whose params fail their checks.
  • 4d. comline-typescript; validators declared in another schema or package (needs that schema's IR at generate time).

Points the design note doesn't settle yet

  • value.length must mean the same thing in every target. Settled in core#109: Unicode scalar values for a string, elements for an array. 4d's TypeScript must count by code point. Rust's .chars().count() counts Unicode scalar values, but TypeScript's .length counts UTF-16 code units ("😀".length == 2), so the same schema would accept different strings. Core defines it (see Validators declare the types they apply to #97) and each generator emits code that matches (in TS, iterate by code point).
  • Generated checks must be panic-safe: a failing condition is a validation failure, never a crash.
  • Function arguments: comline-rust already bundles them into a <Protocol><Method>Params struct, so validate() can run there once arguments can carry validators (only via aliases, Validators on type aliases #99).

The design note should be updated as these land.

Activity

  1. added
    P3Eventually
    and removed
    P1Next
    on Oct 31, 2026
  2. moved this from Todo to In Progress in Comline Development Roadmapon Nov 9, 2026
  3. changed the title [-]Run validators in generated code (validators phase 4)[/-] [+]Run validators in generated code: TypeScript and cross-schema validators (phase 4d)[/+] on Nov 9, 2026
  4. Kinflou commented on Nov 9, 2026

    @Kinflou
    MemberAuthor

    Retitled to what's left. Steps 4a–4c are done for Rust. Step 4d remains: the TypeScript generator (generation's FEATURES.md lists validators and validate_on_decode as ignored there), and validators declared in another schema or package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3EventuallycodegenCode generationenhancementNew feature or request

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions