Ir al contenido

Global Backend Hooks

Esta página aún no está disponible en tu idioma.

While Entity Callbacks run on the database adapter layer scoped to individual collections, Global Backend Hooks run at the HTTP API boundary. They allow you to define cross-cutting logic that applies globally across all collections or admin endpoints.

Use global backend hooks for:

  • Global PII masking: Filtering out or redacting sensitive user information for specific roles.
  • Unified audit logging: Writing log entries for all creations, updates, or deletions across all collections.
  • Global validation rules: Restricting certain HTTP methods or operations under custom context rules.
  • User lifecycle side-effects: Sending custom welcome emails or syncing external identity providers when users are saved or deleted.

Configure hooks in initializeRebaseBackend by providing the hooks property of type BackendHooks:

import { initializeRebaseBackend } from "@rebasepro/server-core";
const instance = await initializeRebaseBackend({
app,
server,
// ... basic config
hooks: {
users: {
afterRead: (user, context) => {
// Return user or null to filter it out
return user;
}
},
data: {
afterRead: (slug, entity, context) => {
// Apply global data transformations
return entity;
}
}
}
});

Every boundary hook receives a BackendHookContext detailing the request environment:

interface BackendHookContext {
/** The authenticated user payload, or undefined if public */
requestUser?: {
userId: string;
roles: string[];
};
/** The HTTP method triggering the hook */
method: "GET" | "POST" | "PUT" | "DELETE";
}

Intercept user account operations at the /api/admin boundary.

HookSignatureDescription
afterRead(user, context) => user | nullTransform user record before returning. Returning null hides it.
beforeSave(data, context) => dataModify user fields (email, roles, name) before database insert/update. Throw to reject.
afterSave(user, context) => voidPost-save hook for side effects.
beforeDelete(userId, context) => voidIntercept delete operations. Throw to prevent.
afterDelete(userId, context) => voidPost-delete side effects hook.
const hooks: BackendHooks = {
users: {
afterSave: async (user, context) => {
if (context.method === "POST") {
// New user signed up - sync to HubSpot/Salesforce
await syncToCRM(user.email, user.displayName);
}
},
beforeDelete: async (userId, context) => {
// Prevent deleting protected system accounts
if (userId === "system-admin-uuid") {
throw new Error("Cannot delete system admin account!");
}
}
}
};

Intercept role definitions fetched by the admin panel.

HookSignatureDescription
afterRead(role, context) => role | nullModify or hide role properties dynamically.

Intersects ALL collection entities flowing through the REST API routes. These run after the per-collection EntityCallbacks.

HookSignatureDescription
afterRead(slug, entity, context) => entity | nullModify or redact fields before sending to client. Return null to exclude the record.
beforeSave(slug, values, entityId, context) => valuesPerform global checks or inject values before saving. Throw to abort.
afterSave(slug, entity, context) => voidRun post-save tasks (e.g. syncing search indexes).
beforeDelete(slug, entityId, context) => voidRun validation before deletion. Throw to block.
afterDelete(slug, entityId, context) => voidPost-deletion cleanup.

Example: Global PII Masking and Global Audit Logging

Section titled “Example: Global PII Masking and Global Audit Logging”
import { BackendHooks } from "@rebasepro/types";
const hooks: BackendHooks = {
data: {
// Redact email addresses for non-admin requests
afterRead: (slug, entity, context) => {
const isAdmin = context.requestUser?.roles.includes("admin");
if (!isAdmin && entity.email) {
return {
...entity,
email: "********" // Mask email
};
}
return entity;
},
// Log all deletion actions globally
afterDelete: async (slug, entityId, context) => {
console.log(`[AUDIT] User ${context.requestUser?.userId} deleted ${slug}/${entityId}`);
await writeToAuditLogs({
action: "delete",
collection: slug,
entityId,
userId: context.requestUser?.userId
});
}
}
};