Skip to content

Documentation

Schema Lifecycle Hooks

resolveInput, validate, beforeOperation, and afterOperation, plus beforeValidate / afterValidate, on collection create and update.

9/30/2026
2 min read Edit on GitHub

Optional transforms and validators on every document write path (Local API, HTTP, admin) for a collection schema. Field hooks live on field.hooks. List hooks live on the collection hooks object.

Order on create / update

  1. Field and list resolveInput
  2. beforeValidate — normalize (trim, slugify, defaults)
  3. Field and list validate, together with the numeric/exact gate. validate may return many errors; the write aborts once, before persist
  4. beforeOperation
  5. afterValidate — computed fields after the gate and beforeOperation
  6. Plugin / collection beforeSave lifecycle
  7. modifyRequest (widget validation & transforms)
  8. Persist (insert / update uses the final mutated payload)
  9. afterOperation (post-commit, not awaited — a failure is logged at debug and does not undo the write) alongside afterSave + transactional outbox emit

The same order is the contract in Schema model.

Defining hooks

import type { Schema } from "@src/content/types";

const posts: Schema = {
  _id: "posts",
  name: "Posts",
  fields: [/* ... */],
  hooks: {
    beforeValidate: (data) => ({
      ...data,
      slug:
        data.slug ||
        String(data.title || "")
          .toLowerCase()
          .replace(/\s+/g, "-"),
    }),
    afterValidate: (data) => ({
      ...data,
      searchKey: `${data.title}:${data.slug}`,
    }),
  },
};

Hooks may be async. resolveInput, beforeValidate, beforeOperation, and afterValidate return the data object. validate collects errors and aborts once before the write. Do not throw from a transform to reject a document. Field hooks use the same names on field.hooks.

Pure runners (unit-test friendly)

import {
  applyBeforeValidate,
  applyAfterValidate,
  applySchemaHookPipeline,
} from "@src/content/schema-hooks";

Implementation

  • Types + runners: src/content/schema-hooks.ts
  • Wired: src/services/sdk/namespaces/collections-namespace.ts (create / update)
  • Tests: tests/unit/content/schema-hooks.test.ts
Was this page helpful?