Endpoints serialize path params, query strings, and request bodies using schemas. All serialization validates input and can transform data.
Path parameters are serialized from the params input into the URL pathname.
If no schema is provided, params are inferred from the pathname pattern:
const endpoint = new Endpoint({
method: 'GET',
pathname: '/users/(:id)',
})
const url = await endpoint.generate_url({
base_url: 'https://api.example.com',
params: { id: '123' },
})
// https://api.example.com/users/123Use a schema to validate and transform params:
const endpoint = new Endpoint({
method: 'GET',
pathname: '/users/(:id)',
params: {
schema: z.object({
id: z.string().uuid(),
}),
},
})Provide a serialize function to transform validated params:
const endpoint = new Endpoint({
method: 'GET',
pathname: '/users/(:id)',
params: {
schema: z.object({ id: z.number() }),
serialize: (data) => ({ id: `user-${data.id}` }),
},
})
const url = await endpoint.generate_url({
base_url: 'https://api.example.com',
params: { id: 123 },
})
// https://api.example.com/users/user-123Query parameters are serialized into the URL search string.
const endpoint = new Endpoint({
method: 'GET',
pathname: '/users',
query: {
schema: z.object({
page: z.number().transform(String),
search: z.string().optional(),
}),
},
})
const url = await endpoint.generate_url({
base_url: 'https://api.example.com',
query: { page: 1, search: 'john' },
})
// https://api.example.com/users?page=1&search=johnconst endpoint = new Endpoint({
method: 'GET',
pathname: '/users',
query: {
schema: z.object({
tags: z.array(z.string()),
}),
serialize: (data) => {
const params = new URLSearchParams()
params.set('tags', data.tags.join(','))
return params
},
},
})
const url = await endpoint.generate_url({
base_url: 'https://api.example.com',
query: { tags: ['admin', 'active'] },
})
// https://api.example.com/users?tags=admin,activeRequest bodies are serialized for POST, PUT, PATCH, and DELETE methods.
Use serialize: 'json' to serialize the body as JSON:
const endpoint = new Endpoint({
method: 'POST',
pathname: '/users',
body: {
schema: z.object({
name: z.string(),
email: z.string().email(),
}),
serialize: 'json',
},
})
const { body, content_type } = await endpoint.serialize_body({
body: { name: 'John', email: 'john@example.com' },
})
// body: '{"name":"John","email":"john@example.com"}'
// content_type: 'application/json'For non-JSON bodies (FormData, text, etc.):
const endpoint = new Endpoint({
method: 'POST',
pathname: '/upload',
body: {
schema: z.object({
file: z.instanceof(File),
name: z.string(),
}),
serialize: (data) => {
const formData = new FormData()
formData.append('file', data.file)
formData.append('name', data.name)
return { body: formData, content_type: 'multipart/form-data' }
},
},
})const endpoint = new Endpoint({
method: 'POST',
pathname: '/login',
body: {
schema: z.object({
username: z.string(),
password: z.string(),
}),
serialize: (data) => {
const params = new URLSearchParams()
params.set('username', data.username)
params.set('password', data.password)
return { body: params, content_type: 'application/x-www-form-urlencoded' }
},
},
})const endpoint = new Endpoint({
method: 'POST',
pathname: '/echo',
body: {
schema: z.string(),
serialize: (text) => ({
body: text,
content_type: 'text/plain',
}),
},
})If input fails schema validation, a SerializationError is returned:
const result = await endpoint.serialize_body({ body: { name: '' } })
if (result instanceof SerializationError) {
console.log(result.message) // "Body serialization failed"
console.log(result.cause) // Schema validation issues
}