@afoures/http-client uses the Standard Schema spec for schema validation. Any compliant library works.
import { z } from 'zod'
const endpoint = new Endpoint({
method: 'POST',
pathname: '/users',
body: {
schema: z.object({
name: z.string().min(1),
email: z.string().email(),
}),
serialize: 'json',
},
data: {
schema: z.object({
id: z.string(),
name: z.string(),
createdAt: z.string().datetime(),
}),
parse: 'json',
},
})Zod transforms work for both input and output:
const endpoint = new Endpoint({
method: 'GET',
pathname: '/users',
query: {
schema: z.object({
page: z.number().transform(String), // number input, string output
}),
},
data: {
schema: z.object({
createdAt: z.string().transform(s => new Date(s)), // parse ISO to Date
}),
parse: 'json',
},
})
// Input: { page: 1 }
// Query string: ?page=1
// Response: { createdAt: "2024-01-15T10:30:00Z" }
// Output: { createdAt: Date }import { type } from 'arktype'
const endpoint = new Endpoint({
method: 'POST',
pathname: '/users',
body: {
schema: type({
name: 'string>0',
email: 'string',
age: 'number?',
}),
serialize: 'json',
},
data: {
schema: type({
id: 'string',
name: 'string',
'email?': 'string',
}),
parse: 'json',
},
})import { type } from 'arktype'
const endpoint = new Endpoint({
method: 'GET',
pathname: '/users',
data: {
schema: type({
id: 'string',
'createdAt': 'string.parse(v => new Date(v))',
}),
parse: 'json',
},
})import * as v from 'valibot'
const endpoint = new Endpoint({
method: 'POST',
pathname: '/users',
body: {
schema: v.object({
name: v.pipe(v.string(), v.minLength(1)),
email: v.pipe(v.string(), v.email()),
}),
serialize: 'json',
},
data: {
schema: v.object({
id: v.string(),
name: v.string(),
}),
parse: 'json',
},
})import * as v from 'valibot'
const endpoint = new Endpoint({
method: 'GET',
pathname: '/users',
data: {
schema: v.object({
id: v.string(),
createdAt: v.pipe(v.string(), v.transform(s => new Date(s))),
}),
parse: 'json',
},
})Schemas define both input validation and output parsing:
- Input (
Schema.infer_input): What you pass to the endpoint - Output (
Schema.infer_output): What you get back after validation/transforms
const schema = z.object({
id: z.string().transform(s => parseInt(s)),
})
// Input: string
// Output: number
const endpoint = new Endpoint({
method: 'GET',
pathname: '/items',
query: {
schema: z.object({
id: z.string().transform(parseInt),
}),
},
})
// You pass: { query: { id: '123' } } (string)
// URL becomes: /items?id=123
// After validation, id is: 123 (number)Share schemas across endpoints:
import { z } from 'zod'
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
})
const CreateUserSchema = UserSchema.omit({ id: true })
const api = http_client({
base_url: 'https://api.example.com',
endpoints: {
users: {
list: new Endpoint({
method: 'GET',
pathname: '/users',
data: { schema: z.array(UserSchema), parse: 'json' },
}),
get: new Endpoint({
method: 'GET',
pathname: '/users/(:id)',
data: { schema: UserSchema, parse: 'json' },
}),
create: new Endpoint({
method: 'POST',
pathname: '/users',
body: { schema: CreateUserSchema, serialize: 'json' },
data: { schema: UserSchema, parse: 'json' },
}),
},
},
})Any library implementing the Standard Schema spec works:
interface StandardSchemaV1<Input = unknown, Output = Input> {
readonly '~standard': {
readonly version: 1
readonly vendor: string
readonly validate: (value: Input) => StandardResult<Output>
}
}The HTTP client uses schema['~standard'].validate() for both input serialization and output parsing.