vault backup: 2026-05-15 15:53:42

This commit is contained in:
Vadym Samoilenko 2026-05-15 15:53:42 +01:00
parent 990d292032
commit 9e8d783088
4 changed files with 65 additions and 1 deletions

View file

@ -78,3 +78,4 @@ tags: [daily]
- 15:38 — session ended | `ai_leed`
- 15:42 — session ended | `ai_leed`
- 15:44 — session ended | `ai_leed`
- 15:53 (6min) — session ended | `Shumiland`

View file

@ -60,7 +60,7 @@
| [[wiki/payloadcms/fields-basic\|PayloadCMS — Fields: Basic]] | Scalar (basic) fields store a single value per document. They map directly to database columns and d | https://payloadcms.com/docs/fields/overview | 2026-05-15 |
| [[wiki/payloadcms/fields-complex\|PayloadCMS — Fields: Complex]] | Complex fields define structure, layout, or relations between documents. Some are data-bearing (Arra | https://payloadcms.com/docs/fields/array | 2026-05-15 |
| [[wiki/payloadcms/getting-started\|PayloadCMS — Getting Started]] | Payload is a code-first, open-source Next.js fullstack framework that acts as a CMS, enterprise tool | getting-started__what-is-payload.md | 2026-05-15 |
| [[wiki/payloadcms/hooks\|PayloadCMS — Hooks]] | - Hooks execute side effects at precise moments in the Document lifecycle | https://payloadcms.com/docs/hooks/overview | 2026-05-15 |
| [[wiki/payloadcms/hooks\|PayloadCMS — Hooks]] | All hook types (Root/Collection/Global/Field), awaited vs fire-and-forget, APIError, performance (avoid read hooks), context caching, jobs offload | raw/hooks__overview.md | 2026-05-15 |
| [[wiki/payloadcms/live-preview\|PayloadCMS — Live Preview]] | - Renders your frontend inside an iframe directly in the Admin Panel | https://payloadcms.com/docs/live-preview/overview | 2026-05-15 |
| [[wiki/payloadcms/rich-text\|PayloadCMS — Rich Text (Lexical)]] | - Rich text is powered by **Lexical** (Meta's framework), exposed via `@payloadcms/richtext-lexical` | https://payloadcms.com/docs/rich-text/overview | 2026-05-15 |
| [[wiki/payloadcms/examples-overview\|Examples Overview]] | 9 official starter examples (auth, draft-preview, multi-tenant, tailwind-shadcn, whitelabel…) — `npx create-payload-app --example <name>` | raw/examples__overview.md | 2026-05-15 |

View file

@ -2,6 +2,7 @@
tags: [payloadcms, tech-patterns]
topic: payloadcms
sources:
- raw/hooks__overview.md
- https://payloadcms.com/docs/hooks/overview
- https://payloadcms.com/docs/hooks/collections
- https://payloadcms.com/docs/hooks/globals
@ -231,6 +232,68 @@ declare module 'payload' {
}
```
## Custom Error Messages
Throw `APIError` from any hook to return structured errors to REST or GraphQL callers:
```ts
import { APIError, type CollectionBeforeChangeHook } from 'payload'
const beforeChangeHook: CollectionBeforeChangeHook = async ({ data }) => {
if (rateLimitExceeded) {
throw new APIError('You have sent too many requests', 429)
}
return data
}
```
## Performance
### Avoid expensive logic in read hooks
`beforeRead` / `afterRead` run on **every** read request — query-time operations here multiply with list view page sizes.
```ts
// BAD — runs on every find/findByID
hooks: { beforeRead: [async () => { await doSomethingExpensive() }] }
// BETTER — only on create/update
hooks: { beforeChange: [async () => { await doSomethingExpensive() }] }
```
### Use Hook Context to cache across hooks
```ts
hooks: {
beforeChange: [
async ({ context, data }) => {
context.enriched = await fetchExpensiveData(data.userId)
return { ...data, profile: context.enriched }
},
],
afterChange: [
async ({ context, doc }) => {
// reuse what beforeChange already fetched — no second DB call
await syncToCRM(doc.id, context.enriched)
},
],
}
```
Full context API → [[wiki/payloadcms/hooks-context|Hooks — Context]]
### Offload long-running tasks
```ts
afterChange: [
async ({ doc, req }) => {
await req.payload.jobs.queue({ task: 'processReport', input: { id: doc.id } })
},
]
```
→ [[wiki/payloadcms/jobs-queue|Jobs Queue]]
## Gotchas
- **`data` on `beforeChange`/`beforeValidate`** — contains only changed fields (delta), not the full document. Use `originalDoc` for unchanged fields. `id` is NOT in `data` on create — use `afterChange` if you need it.