Middleware

Hook Middleware

Hook Middleware is a powerful middleware that allows you to hook into the URPC lifecycle and execute custom logic before and after CRUD operations. This enables you to implement cross-cutting concerns like validation, logging, caching, notifications, and more.

Installation

npm install @unilab/urpc-core

Basic Usage

Creating Hook Middleware

Use the createHookMiddleware factory function to create a hook middleware:

import { createHookMiddleware } from '@unilab/urpc-core/middleware';

const HookMiddleware = createHookMiddleware((hookManager) => {
  hookManager
    .beforeCreate(async (context) => {
      console.log('Before creating:', context);
      // Validation, data transformation, etc.
    })
    .afterCreate(async (context) => {
      console.log('After creating:', context);
      // Notifications, logging, etc.
    });
});

Registering with URPC

import { URPC } from '@unilab/urpc-hono';

const app = URPC.init({
  plugins: [MyPlugin],
  middlewares: [HookMiddleware],
});

Hook Types

Operation-Specific Hooks

Create Hooks

  • beforeCreate: Executed before entity creation
  • afterCreate: Executed after successful entity creation

Update Hooks

  • beforeUpdate: Executed before entity update
  • afterUpdate: Executed after successful entity update

Delete Hooks

  • beforeDelete: Executed before entity deletion
  • afterDelete: Executed after successful entity deletion

Universal Hooks

  • beforeAny: Executed before any operation
  • afterAny: Executed after any operation

Hook Function Signature

Each hook function receives three parameters:

type HookFunction<T extends Record<string, any>> = (
  context: MiddlewareContext<T>
) => Promise<void> | void;

Audit Logging

const AuditHooks = createHookMiddleware((hookManager) => {
  hookManager
    .afterCreate(async (context) => {
      console.log(`AUDIT: Created ${context.operation} with ID: ${context.result?.id}`);
    })
    .afterUpdate(async (context) => {
      console.log(`AUDIT: Updated ${context.operation} with ID: ${context.result?.id}`);
    })
    .afterDelete(async (context) => {
      console.log(`AUDIT: Deleted ${context.operation}`);
    });
});

Notifications

const NotificationHooks = createHookMiddleware((hookManager) => {
  hookManager
    .afterCreate(async (context) => {
      if (context?.adapter.constructor.name === 'UserAdapter') {
        await sendWelcomeEmail(context.result?.email);
      }
    })
    .afterUpdate(async (context) => {
      await sendUpdateNotification(context.result?.id, context.args.data);
    });
});