Hooks
Hooks allow you to execute custom logic at various points in the request lifecycle.
Global Hooks
Define hooks in your configuration:
typescript
export default defineConfig({
hooks: {
// Server lifecycle
onStart: async ({ lucent }) => {
console.log("Server starting...");
},
onStop: async ({ lucent }) => {
console.log("Server stopping...");
},
// Request lifecycle
beforeRequest: async ({ request, lucent }) => {
// Modify request or return early
return request;
},
afterResponse: async ({ request, response, lucent }) => {
// Modify response
return response;
},
},
});Collection Hooks
typescript
export const posts = defineCollection({
name: "posts",
hooks: {
// Before CRUD operations
beforeCreate: async (data, { db, user }) => {
data.createdAt = new Date();
data.authorId = user?.id;
return data;
},
beforeUpdate: async (data, { db, user, record }) => {
data.updatedAt = new Date();
return data;
},
beforeDelete: async ({ db, user, record }) => {
// Return false to prevent deletion
if (record.published) {
throw new Error("Cannot delete published posts");
}
},
// After CRUD operations
afterCreate: async (record, { db, user }) => {
await notifyAdmins(`New post: ${record.title}`);
},
afterUpdate: async (record, { db, user }) => {
await updateSearchIndex(record);
},
afterDelete: async (record, { db, user }) => {
await cleanupRelated(record);
},
},
});Hook Context
Hooks receive a context object:
typescript
beforeCreate: async (data, context) => {
const { db, user, collection, lucent } = context;
// db - Database instance
// user - Authenticated user (or null)
// collection - Collection definition
// lucent - Full Lucent instance
return data;
};Async Hooks
All hooks can be async:
typescript
beforeCreate: async (data, { db }) => {
const validated = await validateData(data);
return validated;
};Error Handling
Throw errors to stop the pipeline:
typescript
beforeCreate: async (data, { user }) => {
if (!user) {
throw new Error("Authentication required");
}
return data;
};