wellformed

Getting Started

Install wellformed and validate your first schema in under a minute.

Install

npm install wellformed-ts
pnpm add wellformed-ts
yarn add wellformed-ts
bun add wellformed-ts
cargo add wellformed wellformed-macros serde_json

Needs Node 18+ and TypeScript 5+ for the TypeScript package. The Rust crates support Rust 1.93.0+.

Build a schema

import { w } from "wellformed-ts";

const contact = w
  .object({
    firstName: w.string().trim().minLen(1),
    email: w.string().email(),
    phone: w.string().phone().optional(),
    age: w.integer().min(18).max(120),
  })
  .strict();
use wellformed_macros::wellformed;

const CONTACT: wellformed::EmbeddedSchema = wellformed!("schemas/contact.json");

In TypeScript, every method returns this, so you chain. Mark optionals with .optional(). .strict() rejects unknown keys. Rust embeds the serialized schema JSON as a value with wellformed!.

Validate

import { validate } from "wellformed-ts";

const result = validate(contact.toSchema("1.0"), {
  firstName: "  Alice  ",
  email: "alice@example.com",
  age: 30,
});

result.valid; // true
result.value.firstName; // "Alice", trimmed by the schema
use serde_json::json;
use wellformed_macros::wellformed;

const CONTACT: wellformed::EmbeddedSchema = wellformed!("schemas/contact.json");

fn validate_contact() -> wellformed::Result<()> {
    let (result, value) = CONTACT.validate_json(r#"{
      "firstName": "  Alice  ",
      "email": "alice@example.com",
      "age": 30
    }"#)?;

    assert!(result.is_valid());
    assert_eq!(value["firstName"], json!("Alice"));

    Ok(())
}

On failure, result.errors lists every field with a stable code and message in both runtimes.

Get the type for free

import type { Infer } from "wellformed-ts";

type Contact = Infer<typeof contact>;
use wellformed_macros::form_schema;

form_schema!(pub mod contact = "schemas/contact.json");

type Contact = contact::Values;

The schema is the source of truth. TypeScript infers from the builder. Rust can use wellformed! for value-style validation, or form_schema! when it needs generated Values, field metadata, and form state helpers.

Explore an example in the Playground

Next

On this page