# API Hooks (tibi-server) Hook files run inside the tibi-server Go runtime (goja). For the full workflow, prefer the `tibi-hook-authoring` skill. ## Related skills - `security-hardening-and-token-strategy` when hooks touch secrets, external requests, auth, or risky capabilities. - `tibi-actions-and-forms` when the behavior is endpoint-like and should be modeled as an action instead of collection CRUD. - `troubleshooting-and-debugging` when goja/runtime failures span config, auth, hook execution, or reverse-proxy behavior. ## Conventions - Wrap hook files in an IIFE: `;(function () { ... })()`. - Always return a HookResponse type or throw a HookException type. - Use inline type casting with `/** @type {TypeName} */ (value)` and typed collection entries from `types/global.d.ts`. - Avoid `@ts-ignore`; use proper casting instead. - Use `const` and `let` instead of `var`. The tibi-server runtime supports modern JS declarations. - Public-read or mutation hooks that affect rendered content must be reviewed together with `filter_public.js`, `config.js`, and cache invalidation behavior. ## context.filter — Go object quirk `context.filter` is not a regular JS object but a Go object. Even when empty, it is **truthy**. Always check with `Object.keys()`: ```js const requestedFilter = context.filter && typeof context.filter === "object" && !Array.isArray(context.filter) && Object.keys(context.filter).length > 0 ? context.filter : null ``` **Never** use `context.filter || null` — it is always truthy and results in an empty filter object inside `$and`, which crashes the Go server. ## Single-item vs. list retrieval For single-item retrieval (`GET /:collection/:id`), the Go server sets `_id` automatically from the URL parameter. GET read hooks should therefore **not set their own `_id` filter** for `req.param("id")`; instead, only add authorization filters (e.g. `{ userId: userId }`). ## HookResponse fields for GET hooks - `filter` — MongoDB filter (list retrieval only, or to restrict single-item retrieval) - `selector` — MongoDB projection (`{ fieldName: 0 }` to exclude, `{ fieldName: 1 }` to include) - `offset`, `limit`, `sort` — pagination/sorting - `pipelineMod` — function to manipulate the aggregation pipeline ## Related tests - When creating or modifying collections/hooks: extend or create corresponding API tests in `tests/api/`. - After hook changes, run only affected API tests: `npx playwright test tests/api/filename.spec.ts`. - When tests fail, clarify whether the hook or the test needs adjustment — coordinate with the user. - If hook changes affect public rendering, add or rerun the narrowest SSR/public-read validation instead of relying only on CRUD-oriented API tests.