Skip to content

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;
};

Released under the MIT License.