@agentuity/schema
A lightweight, type-safe schema validation library for the Agentuity platform. Supports the StandardSchema specification.
Features
- 🎯 Type-safe schema validation
- 📦 Lightweight with zero runtime dependencies
- 🔗 StandardSchema v1 compliant
- 🌐 Works in browser and server environments (Node.js, Bun)
- ⚡ Simple, fluent API
Installation
bun add @agentuity/schema
Usage
import { s, ValidationError } from '@agentuity/schema';
const userSchema = s.object({
name: s.string(),
age: s.number(),
email: s.string(),
isActive: s.boolean(),
});
type User = s.infer<typeof userSchema>;
try {
const user: User = userSchema.parse({
name: 'John',
age: 30,
email: 'john@example.com',
isActive: true,
});
console.log('Valid user:', user);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
console.error('Issues:', error.issues);
}
}
const result = userSchema.safeParse(data);
if (result.success) {
console.log('Valid data:', result.data);
} else {
console.error('Validation failed:', result.error.message);
}
const optionalSchema = s.object({
name: s.string(),
nickname: s.optional(s.string()),
age: s.nullable(s.number()),
});
const stringArraySchema = s.array(s.string());
const userArraySchema = s.array(userSchema);
const statusSchema = s.union(s.literal('active'), s.literal('inactive'), s.literal('pending'));
const roleSchema = s.enum(['admin', 'user', 'guest']);
const prioritySchema = s.enum([1, 2, 3, 4, 5]);
const roleSchema = s.literal('admin');
API
Basic Types
s.string() - String validation
s.number() - Number validation
s.boolean() - Boolean validation
s.null() - Null validation
s.undefined() - Undefined validation
Complex Types
s.object(shape) - Object validation with typed properties
s.array(schema) - Array validation with typed elements
Utility Types
s.optional(schema) - Makes a schema optional
s.nullable(schema) - Makes a schema nullable
s.union(...schemas) - Union of multiple schemas
s.literal(value) - Exact value matching
s.enum([...values]) - Enum type (union of literals)
const roleSchema = s.enum(['admin', 'user', 'guest']);
const role = roleSchema.parse('admin');
const roleSchema2 = s.union(s.literal('admin'), s.literal('user'), s.literal('guest'));
Coercion
Automatically convert values to the correct type (like zod.coerce):
s.coerce.string() - Coerce to string using String(value)
s.coerce.number() - Coerce to number using Number(value)
s.coerce.boolean() - Coerce to boolean using Boolean(value)
s.coerce.date() - Coerce to Date using new Date(value)
const formSchema = s.object({
name: s.string(),
age: s.coerce.number(),
newsletter: s.coerce.boolean(),
createdAt: s.coerce.date(),
});
const formData = formSchema.parse({
name: 'John',
age: '30',
newsletter: 'on',
createdAt: '2025-01-01',
});
const querySchema = s.object({
page: s.coerce.number(),
limit: s.coerce.number(),
});
const params = querySchema.parse({
page: '1',
limit: '20',
});
Documentation
All schemas support a .describe(description: string) method for adding documentation:
const userSchema = s
.object({
id: s.string().describe('The unique identifier'),
name: s.string().describe('The user full name'),
age: s.number().describe('Age in years'),
})
.describe('User profile');
JSON Schema Conversion
Convert schemas to JSON Schema format:
const schema = s.object({
name: s.string().describe('User name'),
age: s.number().describe('User age'),
});
const jsonSchema = s.toJSONSchema(schema);
Convert JSON Schema to schemas:
const jsonSchema = {
type: 'object',
properties: {
firstName: {
type: 'string',
description: 'First name',
},
lastName: {
type: 'string',
description: 'Last name',
},
age: {
type: 'number',
description: 'Age',
},
hobbies: {
type: 'array',
items: { type: 'string' },
},
},
required: ['firstName', 'lastName', 'age', 'hobbies'],
};
const schema = s.fromJSONSchema(jsonSchema);
const result = schema['~standard'].validate(data);
Round-trip conversion is supported:
const original = s.object({ name: s.string() });
const json = s.toJSONSchema(original);
const reconstructed = s.fromJSONSchema(json);
Parsing & Validation
.parse(value) - Throws on validation error
try {
const user = userSchema.parse(data);
} catch (error) {
if (error instanceof ValidationError) {
console.error(error.message);
console.error(error.issues);
}
}
.safeParse(value) - Returns result object
const result = userSchema.safeParse(data);
if (result.success) {
console.log(result.data);
} else {
console.error(result.error);
}
Type Inference
Use s.infer to extract TypeScript types from schemas (like zod's z.infer):
import { s } from '@agentuity/schema';
const Player = s.object({
username: s.string(),
xp: s.number(),
inventory: s.array(s.string()),
});
type Player = s.infer<typeof Player>;
const player: Player = Player.parse(data);
You can also import the Infer type directly if preferred:
import { s, type Infer } from '@agentuity/schema';
type Player = Infer<typeof Player>;
Error Handling
Validation errors are structured and include paths to the failed fields:
const profileSchema = s.object({
user: s.object({
name: s.string(),
age: s.number(),
}),
});
try {
profileSchema.parse({ user: { name: 'John', age: 'thirty' } });
} catch (error) {
if (error instanceof ValidationError) {
console.log(error.message);
console.log(error.issues);
}
}
StandardSchema Support
All schemas implement the StandardSchema v1 interface:
interface StandardSchemaV1<Input, Output> {
readonly '~standard': {
readonly version: 1;
readonly vendor: string;
readonly validate: (value: unknown) => Result<Output>;
readonly types?: { input: Input; output: Output };
};
}
License
Apache-2.0