You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 32e9f36
Browse filesBrowse the repository at this point in the historyBrowse files
Invoke domain hooks from the operation lifecycle after authorization. Hooks can enforce domain invariants, publish side effects, and observe errors; they are not the authorization policy.
186
120
187
-
## Plugin stack() wiring (in stack.ts)
121
+
## Plugin `createBackendStack()` wiring (in stack.ts)
Copy file name to clipboardExpand all lines: .agents/skills/btst-backend-plugin-dev/SKILL.md
+30-21Lines changed: 30 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
name: btst-backend-plugin-dev
3
-
description: Patterns for writing BTST backend plugins inside the monorepo, including defineBackendPlugin structure, getters.ts/mutations.ts separation, the api factory, lifecycle hook naming conventions, and accessing the adapter in AI tool execute functions. Use when creating or modifying a backend plugin, adding DB getters or mutations, wiring the api factory, or implementing lifecycle hooks in src/plugins/{name}/api/.
3
+
description: Patterns for writing BTST backend plugins inside the monorepo, including operation-first authorization, getters.ts/mutations.ts separation, lifecycle hooks, and narrow SSG raw factories. Use when creating or modifying a backend plugin, adding DB getters or mutations, operations, permission descriptors, or lifecycle hooks in src/plugins/{name}/api/.
4
4
---
5
5
6
6
# BTST Backend Plugin Development
@@ -12,19 +12,21 @@ src/plugins/{name}/
12
12
api/
13
13
plugin.ts ← defineBackendPlugin entry
14
14
getters.ts ← read-only DB functions (no HTTP context)
-**`getters.ts`** — pure async DB functions only. No HTTP context, no lifecycle hooks. Always takes `adapter` as first arg.
23
-
-**`mutations.ts`** — write operations (create/update/delete). No auth hooks, no HTTP context. Add JSDoc: "Authorization hooks are NOT called."
24
+
-**`mutations.ts`** — lower-level write primitives. No HTTP context or lifecycle composition. Document that callers own validation and lifecycle.
24
25
-**`api/index.ts`** — re-export everything from getters + mutations for direct server-side import.
25
-
- The `api` factory and `routes` factory share the same adapter instance — bind getters inside the factory, don't pass adapter at call site.
26
-
- If the plugin has a one-time init step (e.g. `syncContentTypes`), call it inside each getter/mutation wrapper — not only inside `routes`.
27
-
-**Never** use `myStack.api.*` as a substitute for authenticated HTTP endpoints — auth hooks are not called.
26
+
-**`operations.ts`** — define the one maintained business inventory with input validation, exact permission descriptors, authoritative facts, domain execution, and lifecycle hooks.
27
+
- Bind HTTP routes to same-key operations. Use `operationRouteMap` only for real route-name mismatches.
28
+
- The optional `raw` factory is narrow: first-party plugins expose only `prefetchForRoute` for SSG. Do not duplicate business getters or mutations on `createBackendStack().raw`.
29
+
- Use `myStack.forRequest(request).operations.*` for request work and `myStack.trusted.*` for explicitly trusted jobs.
-**Wrong adapter type** — use `import type { DBAdapter as Adapter } from "@btst/db"` in getters/mutations/plugin files.
74
83
-**`"GET /path"` string keys** — routes use `createEndpoint()`, not string-keyed method/path objects.
75
84
-**`ctx.json()`** — does not exist; return data directly from route handlers.
76
-
-**`stack().api` bypasses auth hooks** — never use for authenticated data access; enforce auth at the call site.
77
-
-**Plugin init not called via `api`** — if `routes` factory runs a setup (e.g. `syncContentTypes`), also await it inside each `api` getter wrapper.
85
+
-**Business methods on `createBackendStack().raw`** — do not add them. Keep the composed lifecycle explicit through `forRequest(request).operations` or `trusted`, and reserve `raw` for narrow lower-level/SSG helpers.
86
+
-**Authorization in lifecycle hooks** — routine access control belongs in operation descriptors and the one shared rule. Hooks receive already-authorized context.
78
87
-**Write ops in `getters.ts`** — write functions belong in `mutations.ts`, not `getters.ts`.
0 commit comments