✨ feat: add SKILL documentation for Gitea issue attachments, tibi hook authoring, and SSR caching
This commit is contained in:
71
.agents/skills/tibi-hook-authoring/SKILL.md
Normal file
71
.agents/skills/tibi-hook-authoring/SKILL.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
name: tibi-hook-authoring
|
||||
description: Write and debug server-side hooks for tibi-server (goja Go JS runtime). Covers IIFE structure, HookResponse/HookException types, context.filter Go-object quirk, single-item vs list retrieval, and MongoDB filter patterns. Use when creating or modifying files in api/hooks/.
|
||||
---
|
||||
|
||||
# tibi-hook-authoring
|
||||
|
||||
## Hook file structure
|
||||
|
||||
Wrap every hook in an IIFE:
|
||||
|
||||
```js
|
||||
;(function () {
|
||||
/** @type {HookResponse} */
|
||||
const response = { status: 200 }
|
||||
|
||||
// ... hook logic ...
|
||||
|
||||
return response
|
||||
})()
|
||||
```
|
||||
|
||||
Always return a `HookResponse` or throw a `HookException`.
|
||||
|
||||
## Type safety
|
||||
|
||||
- Use inline JSDoc type casting: `/** @type {TypeName} */ (value)`.
|
||||
- Reference typed collection entries from `types/global.d.ts`.
|
||||
- Avoid `@ts-ignore`; use proper casting instead.
|
||||
- Use `const` and `let` instead of `var` — the goja runtime supports them.
|
||||
|
||||
## context.filter — Go object quirk
|
||||
|
||||
`context.filter` is a Go object, not a regular JS 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 produces an empty filter inside `$and`, which crashes the Go server.
|
||||
|
||||
## Single-item vs. list retrieval
|
||||
|
||||
For `GET /:collection/:id`, the Go server sets `_id` automatically from the URL parameter.
|
||||
|
||||
GET read hooks should **not** set their own `_id` filter for `req.param("id")`. Only add authorization filters (e.g. `{ userId: userId }`).
|
||||
|
||||
## HookResponse fields (GET hooks)
|
||||
|
||||
| Field | Purpose |
|
||||
| ------------- | ------------------------------------------------------------------- |
|
||||
| `filter` | MongoDB filter (list retrieval, or restrict single-item) |
|
||||
| `selector` | MongoDB projection (`{ field: 0 }` exclude, `{ field: 1 }` include) |
|
||||
| `offset` | Pagination offset |
|
||||
| `limit` | Pagination limit |
|
||||
| `sort` | Sort specification |
|
||||
| `pipelineMod` | Function to manipulate the aggregation pipeline |
|
||||
|
||||
## context.data for write hooks
|
||||
|
||||
- `context.data` can be an array for bulk operations — always guard with `!Array.isArray(context.data)`.
|
||||
- For POST hooks, `context.data.id` may contain the new entry ID.
|
||||
- For PUT/PATCH, `req.param("id")` gives the entry ID.
|
||||
Reference in New Issue
Block a user