@aircall/exception-zod
v0.1.6
Published
This package provides a simple way to handle exceptions in your application. It is based on the [Zod](https://zod.dev/) library, which is a TypeScript-first schema declaration and validation library.
Downloads
1,874
Keywords
Readme
Introduction
This package provides a simple way to handle exceptions in your application. It is based on the Zod library, which is a TypeScript-first schema declaration and validation library.
Installation
yarn add @aircall/exception-zod
How to use
import { Exception } from '@aircall/exception';
import { zodMiddleware } from '@aircall/exception-zod';
// Let's say you have a function which creates a user
// First you define a schema to validate the body of the request
const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive()
});
// Let's say you have a lambda handler
export const handler = zodMiddleware(async (event: any) => {
// You can use the `parse` method to validate the body of the request
const body = schema.parse(event.body);
// You can then use the `body` object to create a user
const user = await createUser(body);
return {
statusCode: 200,
body: JSON.stringify(user)
};
});
// If the body of the request is invalid, the middleware will throw an exception
// You can catch the exception and return a proper response
try {
const response = await handler(event);
} catch (error) {
if (error instanceof Exception) {
// Manage the exception however you want here
}
return {
statusCode: 400,
body: JSON.stringify({
message: error.message
})
};
}
REST Integration
You can use the zodMiddleware
also side restMiddleware
which would automatically parse the body of the request and validate it against a schema. If the body is invalid, the middleware will throw an already formatted REST error using Aircall conventions.
import { restMiddleware } from '@aircall/exception-rest';
import { zodMiddleware } from '@aircall/exception-zod';
const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive()
});
export const handler = restMiddleware(
zodMiddleware(async (event: any) => {
// You can use the `parse` method to validate the body of the request
// If the body is invalid, the zod will throw an exception
// That will be caught by zodMiddleware to convert them to Aircall errors
// And then by the restMiddleware to convert them to REST responses
const body = schema.parse(event.body);
const user = await createUser(body);
return {
statusCode: 200,
body: JSON.stringify(user)
};
})
);
// Example of a request
const event = {
body: JSON.stringify({
name: 'J',
email: 'abc',
age: 1.2
})
};
const response = await handler(event);
// response
{
statusCode: 400,
body: JSON.stringify({
name: 'UserInputException',
message: 'Invalid user input',
code: '0100',
issues: [
{
code: '0103',
message: 'Input in "name" is too small, minimum is "1" "string"',
minimum: 1,
name: 'TooSmallException',
path: 'name',
type: 'string'
},
{
name: 'InvalidStringException',
message: 'Input in "email" has failed the "email" validation',
code: '0102',
path: 'email',
validation: 'email'
},
{
name: 'InvalidTypeException',
code: '0101',
expected: 'integer',
message: 'Input in "age" expected to be "integer" but received "float"',
path: 'age',
received: 'float'
}
]
})
}
GraphQL Integration
You can use the zodMiddleware
also side graphqlMiddleware
which would automatically parse the body of the request and validate it against a schema. If the body is invalid, the middleware will throw an already formatted GraphQL error using Aircall conventions.
import { graphqlMiddleware } from '@aircall/exception-graphql';
import { zodMiddleware } from '@aircall/exception-zod';
const schema = z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive()
});
export const handler = graphqlMiddleware(
zodMiddleware(async (event: any) => {
// You can use the `parse` method to validate the body of the request
// If the body is invalid, the zod will throw an exception
// That will be caught by zodMiddleware to convert them to Aircall errors
// And then by the graphqlMiddleware to convert them to GraphQL errors
const body = schema.parse(event.body);
const user = await createUser(body);
return {
user,
__typename: 'User'
};
})
);
// Example of a request
const event = {
body: JSON.stringify({
query: `
mutation {
createUser(input: { name: "J", email: "abc", age: 1.2 }) {
__typename
... on User {
id
name
email
age
}
... on UserInputException {
message
issues {
__typename
message
code
path
... on TooSmallException {
minimum
type
}
... on InvalidStringException {
validation
}
... on InvalidTypeException {
received
expected
}
}
}
}
}
`
})
};
const response = await handler(event);
// response
{
data: {
__typename: 'UserInputException',
message: 'Invalid user input',
extensions: {
code: '0100',
issues: [
{
__typename: 'TooSmallException',
code: '0103',
message: 'Input in "name" is too small, minimum is "1" "string"',
minimum: 1,
path: 'name',
type: 'string'
},
{
__typename: 'InvalidStringException',
code: '0102',
message: 'Input in "email" has failed the "email" validation',
path: 'email',
validation: 'email'
},
{
__typename: 'InvalidTypeException',
code: '0101',
message: 'Input in "age" expected to be "integer" but received "float"',
path: 'age',
expected: 'integer',
received: 'float'
}
]
}
}
}