Validation

Learn about Kito's powerful Rust-powered validation system

Kito provides high-performance request validation powered by Rust, ensuring data integrity with minimal overhead.

Basic Schema

Create validation schemas using the t builder and schema helper:

import { server, schema, t } from "kitojs";
 
const userSchema = schema({
  body: t.object({
    name: t.str(),
    email: t.str().email(),
    age: t.num()
  })
});
 
app.post("/users", ({ req, res }) => {
  // Body is validated
  const { name, email, age } = req.body;
  res.json({ name, email, age });
}, userSchema);

JSON Schema

You can also use standard JSON Schema definitions:

import { server, schema } from "kitojs";
 
const userSchema = schema.json({
  body: {
    type: "object",
    properties: {
      name: { type: "string", minLength: 1 },
      age: { type: "number", minimum: 0 }
    },
    required: ["name"]
  }
});
 
app.post("/users", ({ req }) => {
  const { name, age } = req.body;
  res.json({ name, age });
}, userSchema);

Schema Types

Kito supports multiple data types with built-in validation:

Strings

t.str()                    // Basic string
t.str().min(3)             // Minimum length
t.str().max(50)            // Maximum length
t.str().length(10)         // Exact length
t.str().email()            // Email format
t.str().url()              // URL format
t.str().uuid()             // UUID format
t.str().regex(/^[a-z]+$/)  // Custom pattern

Numbers

t.num()                    // Basic number
t.num().min(0)             // Minimum value
t.num().max(100)           // Maximum value
t.num().int()              // Integer only
t.num().positive()         // Positive numbers
t.num().negative()         // Negative numbers

Booleans

t.bool()                   // Basic boolean

Arrays

t.array(t.str())           // String array
t.array(t.num())           // Number array
t.array(t.str()).min(1)    // Minimum length
t.array(t.str()).max(10)   // Maximum length

Objects

t.object({
  name: t.str(),
  age: t.num(),
  active: t.bool()
})

Literals

t.literal("admin")         // Exact string match
t.literal(42)              // Exact number match
t.literal(true)            // Exact boolean match

Unions

// String or number
t.union(t.str(), t.num())
 
// Enum-like
t.union(
  t.literal("admin"),
  t.literal("user"),
  t.literal("guest")
)

Optional Fields

Make fields optional with default values:

const schema = t.object({
  name: t.str(),                    // Required
  email: t.str().email().optional(), // Optional
  age: t.num().default(18)          // Optional with default
});

Validating Different Parts

Validate different parts of the request:

const completeSchema = schema({
  // URL parameters
  params: t.object({
    id: t.str().uuid()
  }),
  
  // Query string
  query: t.object({
    page: t.num().min(1).default(1),
    limit: t.num().min(1).max(100).default(10)
  }),
  
  // Request body
  body: t.object({
    title: t.str().min(1).max(200),
    content: t.str()
  }),
  
  // Request headers
  headers: t.object({
    authorization: t.str()
  })
});
 
app.post("/posts/:id", ({ req }) => {
  // All parts are validated
  const { id } = req.params;
  const { page, limit } = req.query;
  const { title, content } = req.body;
}, completeSchema);

Type Safety

Schemas provide full TypeScript type inference:

// ...
 
const userSchema = schema({
  body: t.object({
    name: t.str(),
    email: t.str().email(),
    age: t.num().optional()
  })
});
 
app.post("/users", ({ req }) => {
  // TypeScript knows the exact types
  req.body.name;   // string
  req.body.email;  // string
  req.body.age;    // number | undefined
}, userSchema);

Nested Objects

Validate complex nested structures:

const profileSchema = schema({
  body: t.object({
    user: t.object({
      name: t.str(),
      profile: t.object({
        bio: t.str(),
        avatar: t.str().url().optional(),
        social: t.object({
          twitter: t.str().optional(),
          github: t.str().optional()
        })
      })
    })
  })
});

Array Validation

Validate arrays of complex objects:

const batchSchema = schema({
  body: t.object({
    users: t.array(
      t.object({
        name: t.str(),
        email: t.str().email()
      })
    ).min(1).max(100)
  })
});
 
app.post("/users/batch", ({ req }) => {
  const { users } = req.body;
  // users is User[] with min 1, max 100 items
}, batchSchema);

Error Handling

When validation fails, Kito automatically returns a 400 error with details:

{
  "error": "Validation Error",
  "message": "Validation error in body.email: Invalid email format"
}
⚠️ Caution

Validation errors are automatically handled. No need to write error handling code.

Performance

Kito’s validation is powered by Rust, making it significantly faster than JavaScript-based validators.