Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Input Validation - Zagora
Skip to content

Input Validation

Validate arguments with schemas

Input validation ensures your procedures receive correctly typed and validated data at runtime.

Basic Input

Define an input schema using any StandardSchema-compliant validator:

import { z } from 'zod';
import { zagora } from 'zagora';
 
const greet = zagora()
  .input(z.string())
  .handler((_, name) => `Hello, ${name}!`)
  .callable();
 
greet('Alice');  // { ok: true, data: 'Hello, Alice!' }
greet(123);      // { ok: false, error: { kind: 'VALIDATION_ERROR', ... } }

Object Inputs

For structured data, use object schemas:

const createUser = zagora()
  .input(z.object({
    name: z.string().min(1),
    email: z.string().email(),
    age: z.number().optional()
  }))
  .handler((_, input) => {
    // input: { name: string, email: string, age?: number }
    return { id: '123', ...input };
  })
  .callable();
 
createUser({ name: 'Alice', email: 'alice@example.com' });

Tuple Inputs (Multiple Arguments)

Use tuple schemas to define multiple arguments with per-argument validation:

const add = zagora()
  .input(z.tuple([z.number(), z.number()]))
  .handler((_, a, b) => a + b)  // Arguments are spread
  .callable();
 
add(5, 10);  // { ok: true, data: 15 }

With defaults and optionals:

const greet = zagora()
  .input(z.tuple([
    z.string(),                    // Required
    z.number().default(18),        // Optional with default
    z.string().optional()          // Optional (undefined allowed)
  ]))
  .handler((_, name, age, title) => {
    // name: string
    // age: number (never undefined due to default!)
    // title: string | undefined
    return `${title || 'User'} ${name}, age ${age}`;
  })
  .callable();
 
greet('Alice');              // "User Alice, age 18"
greet('Bob', 25);            // "User Bob, age 25"
greet('Carol', 30, 'Dr.');   // "Dr. Carol, age 30"

Array Inputs

For variable-length inputs of the same type:

const sum = zagora()
  .input(z.array(z.number()))
  .handler((_, numbers) => {
    return numbers.reduce((a, b) => a + b, 0);
  })
  .callable();
 
sum([1, 2, 3, 4, 5]);  // { ok: true, data: 15 }

Validation Errors

When input validation fails, you get a structured error:

const result = createUser({ name: '', email: 'invalid' });
 
if (!result.ok && result.error.kind === 'VALIDATION_ERROR') {
  console.log(result.error.issues);
  // [
  //   { path: ['name'], message: 'String must contain at least 1 character(s)' },
  //   { path: ['email'], message: 'Invalid email' }
  // ]
}

Using Different Validators

Zagora works with any StandardSchema validator:

Valibot

import * as v from 'valibot';
import { zagora } from 'zagora';
 
const greet = zagora()
  .input(v.string())
  .handler((_, name) => `Hello, ${name}!`)
  .callable();

ArkType

import { type } from 'arktype';
import { zagora } from 'zagora';
 
const greet = zagora()
  .input(type('string'))
  .handler((_, name) => `Hello, ${name}!`)
  .callable();

No Input

Procedures can omit input entirely:

const getTime = zagora()
  .handler(() => new Date().toISOString())
  .callable();
 
getTime();  // { ok: true, data: '2024-01-15T10:30:00.000Z' }

Next Steps