Custom Handlers & Hook Types
Hooks and Handlers - Custom Handlers & Hook Types Custom handlers replace the default CRUD operation with your own business logic. Custom Handlers When to Use Custom Handlers Complex business logic that doesn't fit CRUD Multi-step operations External API integrations Custom valid
Hooks and Handlers - Custom Handlers & Hook Types
Custom handlers replace the default CRUD operation with your own business logic.
Custom Handlers
When to Use Custom Handlers
- Complex business logic that doesn't fit CRUD
- Multi-step operations
- External API integrations
- Custom validation beyond preHooks
- Special response formats
Basic Custom Handler
// Create with additional logic
const result = await $ctx.$repos.products.create({
data: {
name: $ctx.$body.name,
price: $ctx.$body.price,
createdBy: $ctx.$user.id
}
});
// Perform additional operations
const product = result.data[0];
// Create related records
await $ctx.$repos.product_images.create({
data: {
productId: product.id,
imageUrl: $ctx.$body.imageUrl
}
});
// Return custom response
return {
success: true,
product: product,
message: 'Product created successfully'
};
Multi-Step Operations
// Create order with items
const orderResult = await $ctx.$repos.orders.create({
data: {
customerId: $ctx.$body.customerId,
total: 0,
status: 'pending'
}
});
const order = orderResult.data[0];
let total = 0;
// Create order items
for (const item of $ctx.$body.items) {
const productResult = await $ctx.$repos.products.find({
where: { id: { _eq: item.productId } }
});
if (productResult.data.length === 0) {
$ctx.$throw['404'](`Product ${item.productId} not found`);
return;
}
const product = productResult.data[0];
const itemTotal = product.price * item.quantity;
total += itemTotal;
await $ctx.$repos.order_items.create({
data: {
orderId: order.id,
productId: item.productId,
quantity: item.quantity,
price: product.price,
total: itemTotal
}
});
}
// Update order total
await $ctx.$repos.orders.update({
id: order.id,
data: { total: total }
});
// Return complete order
const finalOrder = await $ctx.$repos.orders.find({
where: { id: { _eq: order.id } }
});
return finalOrder;
Default CRUD Behavior
If you don't provide a custom handler, the system automatically performs CRUD operations based on HTTP method:
- GET: Query records using repository
find() - POST: Create record using repository
create() - PATCH: Update record using repository
update() - DELETE: Delete record using repository
delete()
The default CRUD uses data from:
- $ctx.$query for GET requests (filter, fields, limit, sort)
- $ctx.$body for POST/PATCH requests (data to create/update)
- $ctx.$params.id for PATCH/DELETE requests (record ID)
Hook Types
Global Hooks
Global hooks run on all routes.
Configuration:
- Route: null (no specific route)
- Methods: [] (all methods) or specific methods like ['POST', 'PATCH']
Example:
// Global preHook - runs on all routes, all methods
// Configuration: route = null, methods = []
// Global preHook - runs on all routes, POST only
// Configuration: route = null, methods = ['POST']
Route-Specific Hooks
Route-specific hooks run only on a specific route.
Configuration:
- Route: Specific route (e.g., route with path /users)
- Methods: [] (all methods) or specific methods
Example:
// Route preHook - runs on /users route, all methods
// Configuration: route = /users route, methods = []
// Route preHook - runs on /users route, POST only
// Configuration: route = /users route, methods = ['POST']
Execution Order
Hooks execute in this order:
- Global hooks (all methods)
- Global hooks (specific method)
- Route hooks (all methods)
- Route hooks (specific method)
Example for POST /users:
Global preHook (all) Global preHook (POST) Route preHook (all) Route preHook (POST) Handler Global postHook (all) Global postHook (POST) Route postHook (all) Route postHook (POST)
Post-hooks run in the same global-then-route grouping as pre-hooks (not reverse order). See API Lifecycle – postHooks.
Next Steps
- See preHooks for pre-handler operations
- Learn about postHooks for post-handler operations
- Check Common Patterns for best practices