Skip to content

Hooks

Hooks

Hooks give a collection server-side behavior — validation and side effects — as one file beside the model, discovered automatically with a generated registry-aware type.

Before and after

Create Before hooks validate and return the accepted input (or patch it); they run before the write, outside the commit transaction — a refusal writes nothing. After hooks run once the write has committed — an approval hold defers them until approval.

import { refuse } from '@norbital-ai/bolt/authoring';
import { Effect } from 'effect';
import type { Hooks } from './$types.js';

export default {
  create: {
    perRecord: {
      before: {
        description: 'Rejects a duplicate site name.',
        handler: ({ input, api }) =>
          Effect.gen(function* () {
            const count = yield* api.db.query.sites.count({ where: { name: { eq: input.name } } });
            if (count) refuse('Site already exists.');
            return input;
          })
      }
    }
  }
} satisfies Hooks;

Hook points

Hooks are declared per operation. On `create` each operation can also carry `prepare` (one batch-wide read) and `input`; per-record hooks sit under perRecord :

OperationBeforeAfter
createvalidate the candidate, apply defaults, reject duplicatestouch derived data, write related records
updateguard forbidden transitions, re-validate changed fieldsrecompute totals, update search or derived state
deleterefuse to delete referenced or protected recordsclean up dependent artifacts, notify downstream
Durable work belongs in automations, not hooks
A hook is part of somebody else’s write: before hooks run before its transaction, after hooks after it has committed. Work that must survive the write belongs in automations — scheduled, event-driven, or started from code with `api.automations.run`, each a durable background run of its own.

Choose the narrowest role

Companion roles overlap on purpose — pick the narrowest one that fits:

  • Hooks — mutation invariants and same-transaction effects
  • Pipelines — reusable bulk ingest and artifact contracts ( pipelines)
  • Integrations — reliable external delivery that reuses pipelines ( integrations)