Schema Lifecycle Hooks
beforeValidate / afterValidate transforms on collection create and update.
On this page
Optional transforms on every document write path (Local API, HTTP, admin) for a collection schema.
Order on create / update
- Sanitize field inputs
beforeValidate— normalize (trim, slugify, defaults)- Numeric range gate (
validateNumericFields) afterValidate— computed fields after the gate- Plugin / collection
beforeSavelifecycle modifyRequest(widget validation & transforms)- Persist (
insert/updateuses the final mutated payload) afterSave+ transactional outbox emit
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. They must return the data object (not throw for rejection — use validation rules).
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?