@terreno/agent-plugin 57.21.0 → 58.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +136 -0
- package/package.json +1 -1
- package/skills/building-admin-interfaces/SKILL.md +9 -6
- package/skills/building-admin-interfaces/references/nav-and-shell.md +1 -1
- package/skills/building-admin-interfaces/references/patterns-and-tools.md +4 -3
- package/skills/building-terreno-apps/SKILL.md +48 -34
- package/skills/building-terreno-apps/agents/openai.yaml +2 -2
- package/skills/building-terreno-apps/references/navigation.md +20 -14
- package/skills/building-terreno-apps/references/route-structure.md +26 -13
- package/skills/building-terreno-apps/references/screen-patterns.md +37 -54
- package/skills/generate-sdk/SKILL.md +87 -78
- package/skills/terreno-backend-api/references/model-router.md +0 -4
- package/skills/terreno-data-fetching/SKILL.md +83 -71
- package/skills/terreno-data-fetching/agents/openai.yaml +2 -2
- package/skills/terreno-data-fetching/references/auth-and-tokens.md +56 -60
- package/skills/terreno-data-fetching/references/realtime.md +26 -21
- package/skills/terreno-data-fetching/references/sdk-customization.md +31 -60
- package/skills/terreno-ui/SKILL.md +2 -2
- package/skills/terreno-ui/references/data-display.md +2 -0
- package/skills/upgrading-terreno/SKILL.md +13 -6
- package/skills/upgrading-terreno/references/ordering.md +3 -3
|
@@ -1,32 +1,23 @@
|
|
|
1
1
|
# Screen Patterns — Terreno Apps
|
|
2
2
|
|
|
3
|
-
## List screen
|
|
3
|
+
## List screen (synced collection)
|
|
4
|
+
|
|
5
|
+
Synced collections read from the local store: no loading spinner after bootstrap, and
|
|
6
|
+
writes apply immediately.
|
|
4
7
|
|
|
5
8
|
```tsx
|
|
6
|
-
import {
|
|
9
|
+
import {generateMutationId} from "@terreno/syncdb";
|
|
10
|
+
import {useMutate, useQuery} from "@terreno/syncdb/react";
|
|
11
|
+
import {Box, Button, Card, Heading, Page, Text} from "@terreno/ui";
|
|
7
12
|
import {useCallback} from "react";
|
|
8
|
-
import {useGetTodosQuery} from "@/store/sdk";
|
|
9
13
|
|
|
10
14
|
const TodoListScreen: React.FC = () => {
|
|
11
|
-
const
|
|
15
|
+
const todos = useQuery<Todo>("todos", {sort: "-created"});
|
|
16
|
+
const {create} = useMutate("todos");
|
|
12
17
|
|
|
13
18
|
const handleCreate = useCallback((): void => {
|
|
14
|
-
|
|
15
|
-
}, []);
|
|
16
|
-
|
|
17
|
-
if (isLoading) {
|
|
18
|
-
return <Page title="Todos"><Spinner /></Page>;
|
|
19
|
-
}
|
|
20
|
-
if (error) {
|
|
21
|
-
return (
|
|
22
|
-
<Page title="Todos">
|
|
23
|
-
<Text color="error">Failed to load</Text>
|
|
24
|
-
<Button text="Retry" onClick={refetch} />
|
|
25
|
-
</Page>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const items = data?.data ?? [];
|
|
19
|
+
create({data: {_id: generateMutationId(), title: "New todo", completed: false}});
|
|
20
|
+
}, [create]);
|
|
30
21
|
|
|
31
22
|
return (
|
|
32
23
|
<Page title="Todos" scroll>
|
|
@@ -35,11 +26,11 @@ const TodoListScreen: React.FC = () => {
|
|
|
35
26
|
<Heading size="lg">Todos</Heading>
|
|
36
27
|
<Button text="Add" onClick={handleCreate} iconName="plus" />
|
|
37
28
|
</Box>
|
|
38
|
-
{
|
|
29
|
+
{todos.length === 0 ? (
|
|
39
30
|
<Text color="secondaryLight">No todos yet</Text>
|
|
40
31
|
) : (
|
|
41
|
-
|
|
42
|
-
<Card key={todo.
|
|
32
|
+
todos.map((todo) => (
|
|
33
|
+
<Card key={todo._id} padding={3}>
|
|
43
34
|
<Text>{todo.title}</Text>
|
|
44
35
|
</Card>
|
|
45
36
|
))
|
|
@@ -50,18 +41,20 @@ const TodoListScreen: React.FC = () => {
|
|
|
50
41
|
};
|
|
51
42
|
```
|
|
52
43
|
|
|
44
|
+
Gate the empty state on the stream's bootstrap (see `docs/how-to/use-syncdb-correctly.md`).
|
|
45
|
+
|
|
53
46
|
## Profile screen
|
|
54
47
|
|
|
55
|
-
Use `TapToEdit` for per-field profile edits. Save each field with `
|
|
48
|
+
Use `TapToEdit` for per-field profile edits. Save each field with the generated `usePatchAuthMeMutation` — do not collect every field behind one Save button.
|
|
56
49
|
|
|
57
50
|
```tsx
|
|
58
51
|
import {Box, Card, Page, TapToEdit} from "@terreno/ui";
|
|
59
52
|
import {useCallback, useEffect, useState} from "react";
|
|
60
|
-
import {
|
|
53
|
+
import {useGetAuthMeQuery, usePatchAuthMeMutation} from "@/store/apiSdk";
|
|
61
54
|
|
|
62
55
|
const ProfileScreen: React.FC = () => {
|
|
63
|
-
const {data: profile} =
|
|
64
|
-
const [updateProfile] =
|
|
56
|
+
const {data: profile} = useGetAuthMeQuery();
|
|
57
|
+
const [updateProfile] = usePatchAuthMeMutation();
|
|
65
58
|
const [name, setName] = useState<string>("");
|
|
66
59
|
|
|
67
60
|
// Seed only this field from the server so saving another TapToEdit does not wipe the draft.
|
|
@@ -100,29 +93,26 @@ const ProfileScreen: React.FC = () => {
|
|
|
100
93
|
## Form screen
|
|
101
94
|
|
|
102
95
|
```tsx
|
|
96
|
+
import {generateMutationId} from "@terreno/syncdb";
|
|
97
|
+
import {useMutate} from "@terreno/syncdb/react";
|
|
103
98
|
import {Box, Button, Page, TextField} from "@terreno/ui";
|
|
104
99
|
import {useCallback, useState} from "react";
|
|
105
100
|
import {useRouter} from "expo-router";
|
|
106
|
-
import {usePostTodosMutation} from "@/store/sdk";
|
|
107
101
|
|
|
108
102
|
const CreateTodoScreen: React.FC = () => {
|
|
109
103
|
const router = useRouter();
|
|
110
104
|
const [title, setTitle] = useState<string>("");
|
|
111
105
|
const [titleError, setTitleError] = useState<string | undefined>();
|
|
112
|
-
const
|
|
106
|
+
const {create} = useMutate("todos");
|
|
113
107
|
|
|
114
|
-
const handleSubmit = useCallback(
|
|
108
|
+
const handleSubmit = useCallback((): void => {
|
|
115
109
|
if (!title.trim()) {
|
|
116
110
|
setTitleError("Title is required");
|
|
117
111
|
return;
|
|
118
112
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
} catch (err) {
|
|
123
|
-
console.error("Create failed", err);
|
|
124
|
-
}
|
|
125
|
-
}, [createTodo, router, title]);
|
|
113
|
+
create({data: {_id: generateMutationId(), title: title.trim(), completed: false}});
|
|
114
|
+
router.back();
|
|
115
|
+
}, [create, router, title]);
|
|
126
116
|
|
|
127
117
|
return (
|
|
128
118
|
<Page title="New Todo" scroll>
|
|
@@ -133,28 +123,28 @@ const CreateTodoScreen: React.FC = () => {
|
|
|
133
123
|
onChange={setTitle}
|
|
134
124
|
errorText={titleError}
|
|
135
125
|
/>
|
|
136
|
-
<Button text="Save" onClick={handleSubmit}
|
|
126
|
+
<Button text="Save" onClick={handleSubmit} fullWidth />
|
|
137
127
|
</Box>
|
|
138
128
|
</Page>
|
|
139
129
|
);
|
|
140
130
|
};
|
|
141
131
|
```
|
|
142
132
|
|
|
133
|
+
Server rejections arrive later in `useConflicts()` / `useSyncStatus().failedCount`, not
|
|
134
|
+
from `create`.
|
|
135
|
+
|
|
143
136
|
## Detail screen with params
|
|
144
137
|
|
|
145
138
|
```tsx
|
|
146
|
-
import {
|
|
139
|
+
import {useEntity} from "@terreno/syncdb/react";
|
|
140
|
+
import {Page, Text} from "@terreno/ui";
|
|
147
141
|
import {useLocalSearchParams} from "expo-router";
|
|
148
|
-
import {useGetTodosByIdQuery} from "@/store/sdk";
|
|
149
142
|
|
|
150
143
|
const TodoDetailScreen: React.FC = () => {
|
|
151
144
|
const {id} = useLocalSearchParams<{id: string}>();
|
|
152
|
-
const {data,
|
|
145
|
+
const {data, deleted} = useEntity<Todo>("todos", id ?? "");
|
|
153
146
|
|
|
154
|
-
if (
|
|
155
|
-
return <Page title="Todo"><Spinner /></Page>;
|
|
156
|
-
}
|
|
157
|
-
if (error || !data) {
|
|
147
|
+
if (!data || deleted) {
|
|
158
148
|
return <Page title="Todo"><Text color="error">Not found</Text></Page>;
|
|
159
149
|
}
|
|
160
150
|
|
|
@@ -175,17 +165,10 @@ skill `building-admin-interfaces`.
|
|
|
175
165
|
```tsx
|
|
176
166
|
import {AdminScreenRouter} from "@terreno/admin-frontend";
|
|
177
167
|
import {useLocalSearchParams} from "expo-router";
|
|
178
|
-
import {terrenoApi} from "@/store/sdk";
|
|
179
168
|
|
|
169
|
+
// Rendered inside the AdminProvider in app/admin/_layout.tsx.
|
|
180
170
|
const AdminModelScreen: React.FC = () => {
|
|
181
171
|
const {model} = useLocalSearchParams<{model: string}>();
|
|
182
|
-
return
|
|
183
|
-
<AdminScreenRouter
|
|
184
|
-
api={terrenoApi}
|
|
185
|
-
apiBase="/admin"
|
|
186
|
-
name={model ?? ""}
|
|
187
|
-
routeBase="/admin"
|
|
188
|
-
/>
|
|
189
|
-
);
|
|
172
|
+
return <AdminScreenRouter apiBase="/admin" name={model ?? ""} routeBase="/admin" />;
|
|
190
173
|
};
|
|
191
174
|
```
|
|
@@ -1,65 +1,64 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: generate-sdk
|
|
3
3
|
description: >-
|
|
4
|
-
Regenerate the example-frontend
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
Regenerate the example-frontend SDKs from the example-backend's OpenAPI spec
|
|
5
|
+
with terreno-syncdb-codegen: store/apiSdk.ts (typed request hooks for every
|
|
6
|
+
non-synced route, `bun run sdk`) and store/syncDbSdk.ts (synced collection
|
|
7
|
+
hooks, `bun run sync-sdk`). Handles dependency install, backend startup,
|
|
8
|
+
codegen, and cleanup from a fresh checkout. Use whenever the backend's API
|
|
9
|
+
surface changes — new modelRouter routes or actions, custom routes registered
|
|
10
|
+
via createOpenApiBuilder, new/modified Mongoose models or field descriptions
|
|
11
|
+
in example-backend, sync config changes, changes to
|
|
10
12
|
permissions/queryFields/populatePaths/responseHandler, edits to @terreno/api
|
|
11
13
|
routing or OpenAPI generation, or any time a route is added/removed/renamed.
|
|
12
|
-
Also use when the user asks to "regenerate the SDK", "update
|
|
13
|
-
"run bun run sdk"
|
|
14
|
-
composition: Pick after API-shape
|
|
15
|
-
compatibility.
|
|
14
|
+
Also use when the user asks to "regenerate the SDK", "update apiSdk.ts" or
|
|
15
|
+
"syncDbSdk.ts", "run bun run sdk" or "bun run sync-sdk", or reports
|
|
16
|
+
stale/missing generated hooks. Lifecycle composition: Pick after API-shape
|
|
17
|
+
changes; Roast to verify generated-client compatibility.
|
|
16
18
|
targets:
|
|
17
19
|
- '*'
|
|
18
20
|
---
|
|
19
21
|
# Generate Frontend SDK
|
|
20
22
|
|
|
21
|
-
Regenerates `example-frontend
|
|
23
|
+
Regenerates the two generated files in `example-frontend` from the live backend spec at
|
|
24
|
+
`http://localhost:4000/openapi.json` (or `OPENAPI_URL`). Both come from
|
|
25
|
+
`terreno-syncdb-codegen` in `@terreno/syncdb`.
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
`injectEndpoints`. See [syncdb reference](../../../../docs/reference/syncdb.md)
|
|
28
|
-
and [migrate-rtk-to-syncdb.md](../../../../docs/how-to/migrate-rtk-to-syncdb.md).
|
|
27
|
+
| Command | Output | Covers |
|
|
28
|
+
|---------|--------|--------|
|
|
29
|
+
| `bun run sdk` (runs `api-sdk`) | `store/apiSdk.ts` | Every operation without `x-terreno-sync`: `/auth/me`, modelRouter actions, AI, consents, announcements, version check |
|
|
30
|
+
| `bun run sync-sdk` | `store/syncDbSdk.ts` | `SYNC_COLLECTIONS` + collection hooks for the collections in the script's `--collections` list |
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
The `example-frontend` consumes the `example-backend` API via auto-generated RTK Query hooks in `store/openApiSdk.ts`. The codegen pulls from the live backend at `http://localhost:4000/openapi.json`, so the backend must be running while `bun run sdk` executes.
|
|
35
|
-
|
|
36
|
-
**Never edit `example-frontend/store/openApiSdk.ts` by hand — it is fully overwritten by this skill.**
|
|
32
|
+
**Never edit `store/apiSdk.ts` or `store/syncDbSdk.ts` by hand — codegen overwrites them.**
|
|
33
|
+
Codegen options live in `example-frontend/syncdb-codegen.json` (`excludePaths` drops
|
|
34
|
+
routes such as the SSE streams; `overrides` sets per-collection options). Built-in admin
|
|
35
|
+
uses admin-frontend's own fetch client and is not generated here.
|
|
37
36
|
|
|
38
37
|
## Documentation
|
|
39
38
|
|
|
40
|
-
Read `docs/reference/syncdb.md` and
|
|
39
|
+
Read `docs/reference/syncdb.md#codegen` and `docs/how-to/generate-the-client-sdk.md`
|
|
40
|
+
before regenerating. After a public API change, run `update-docs` in the same slice.
|
|
41
41
|
|
|
42
42
|
## When to run this skill
|
|
43
43
|
|
|
44
|
-
Run
|
|
44
|
+
Run `sdk` when the non-synced OpenAPI surface changes; run `sync-sdk` when a synced
|
|
45
|
+
collection's schema or `sync` config changes. Run both when unsure. Triggers:
|
|
45
46
|
|
|
46
|
-
- New or removed `modelRouter` registration
|
|
47
|
-
- Edits to `permissions`, `queryFields`, `populatePaths`, `defaultQueryParams`, `sort`, `responseHandler`, or `openApiOverwrite`
|
|
48
|
-
- New custom routes built with `createOpenApiBuilder`
|
|
49
|
-
- Mongoose schema changes that affect the public shape
|
|
50
|
-
-
|
|
51
|
-
- Edits to `@terreno/api`
|
|
52
|
-
-
|
|
47
|
+
- New or removed `modelRouter` registration, `collectionActions`, or `instanceActions`
|
|
48
|
+
- Edits to `permissions`, `queryFields`, `populatePaths`, `defaultQueryParams`, `sort`, `responseHandler`, `sync`, or `openApiOverwrite`
|
|
49
|
+
- New custom routes built with `createOpenApiBuilder`
|
|
50
|
+
- Mongoose schema changes that affect the public shape (fields, types, required/enum/default, `description`, refs)
|
|
51
|
+
- Auth route changes (`addAuthRoutes`, `addMeRoutes`, GitHub OAuth, Better Auth)
|
|
52
|
+
- Edits to `@terreno/api` OpenAPI generation (`openApi.ts`, `openApiBuilder.ts`, `api.ts`, `populate.ts`) or to `syncdb/src/codegen/`
|
|
53
|
+
- A new synced collection: also add it to the `--collections` list in the `sync-sdk` script
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
Skip it for backend-internal changes (logging, refactors that keep routes and models, tests).
|
|
55
56
|
|
|
56
57
|
## Prerequisites
|
|
57
58
|
|
|
58
|
-
- Bun
|
|
59
|
-
- MongoDB
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
If MongoDB is not running, tell the user and stop — do not try to install or start it automatically.
|
|
59
|
+
- Bun on PATH (run `bun` directly; do not modify PATH)
|
|
60
|
+
- A MongoDB **replica set** at `MONGO_URI` (the backend's change streams need one)
|
|
61
|
+
- Port 4000 free
|
|
63
62
|
|
|
64
63
|
## Procedure
|
|
65
64
|
|
|
@@ -67,90 +66,100 @@ Run the steps in order. Stop and report on the first failure.
|
|
|
67
66
|
|
|
68
67
|
### 1. Verify the worktree is bootstrapped
|
|
69
68
|
|
|
70
|
-
Detect whether dependencies are installed. The repo uses Bun workspaces, so a single root `node_modules` is sufficient.
|
|
71
|
-
|
|
72
69
|
```bash
|
|
73
70
|
test -d node_modules && test -d example-backend/node_modules && test -d example-frontend/node_modules && echo "installed" || echo "missing"
|
|
74
71
|
```
|
|
75
72
|
|
|
76
|
-
If `missing`, run
|
|
73
|
+
If `missing`, run `bun run bootstrap` from the repo root in the background and wait for it.
|
|
74
|
+
It installs deps and compiles every workspace package.
|
|
75
|
+
|
|
76
|
+
### 2. Start MongoDB if it is not running
|
|
77
|
+
|
|
78
|
+
`mongosh --quiet --eval 'rs.status().ok'` (or a `node` MongoClient ping) succeeds when a
|
|
79
|
+
replica set is up. Otherwise start one from the `mongodb-memory-server` binary cache and
|
|
80
|
+
initiate it once, as in `/workspace/CLAUDE.md` ("Example full stack"):
|
|
77
81
|
|
|
78
82
|
```bash
|
|
79
|
-
|
|
83
|
+
mkdir -p .devdata/mongo
|
|
84
|
+
"$(ls ~/.cache/mongodb-binaries/mongod-* | head -1)" \
|
|
85
|
+
--replSet rs0 --port 27017 --bind_ip 127.0.0.1 --dbpath .devdata/mongo
|
|
80
86
|
```
|
|
81
87
|
|
|
82
|
-
|
|
88
|
+
Run `mongod` in the background. Initiate the replica set with `node` (not `bun`) from
|
|
89
|
+
`example-backend/`. If no `mongod` binary exists, tell the user and stop.
|
|
83
90
|
|
|
84
|
-
###
|
|
85
|
-
|
|
86
|
-
The backend reads `example-backend/.env`. If that file is missing, copy the example:
|
|
91
|
+
### 3. Ensure backend env vars are set
|
|
87
92
|
|
|
88
93
|
```bash
|
|
89
94
|
test -f example-backend/.env || cp example-backend/.env.example example-backend/.env
|
|
90
95
|
```
|
|
91
96
|
|
|
92
|
-
The
|
|
93
|
-
|
|
94
|
-
### 3. Start the example backend on port 4000
|
|
97
|
+
The example values (`MONGO_URI=mongodb://127.0.0.1:27017/terreno-example?replicaSet=rs0`,
|
|
98
|
+
token and session secrets) are fine for codegen. Never overwrite an existing `.env`.
|
|
95
99
|
|
|
96
|
-
|
|
100
|
+
### 4. Start the example backend on port 4000
|
|
97
101
|
|
|
98
102
|
```bash
|
|
99
103
|
bun run backend:dev
|
|
100
104
|
```
|
|
101
105
|
|
|
102
|
-
Use
|
|
106
|
+
Use `run_in_background: true`.
|
|
103
107
|
|
|
104
|
-
###
|
|
108
|
+
### 5. Wait for the OpenAPI spec
|
|
105
109
|
|
|
106
|
-
Poll
|
|
110
|
+
Poll until the spec returns 200 (5–20 s on a cold start). Codegen against a backend that is
|
|
111
|
+
not ready fails or emits an empty SDK.
|
|
107
112
|
|
|
108
113
|
```bash
|
|
109
|
-
until curl -sf -o /dev/null
|
|
114
|
+
until curl -sf -o /dev/null http://localhost:4000/openapi.json; do sleep 2; done
|
|
110
115
|
```
|
|
111
116
|
|
|
112
|
-
If the backend logs an error (Mongo connection refused, port
|
|
113
|
-
|
|
114
|
-
### 5. Generate the SDK
|
|
117
|
+
If the backend logs an error (Mongo connection refused, port in use, compile error), stop
|
|
118
|
+
and report it.
|
|
115
119
|
|
|
116
|
-
|
|
120
|
+
### 6. Generate
|
|
117
121
|
|
|
118
122
|
```bash
|
|
119
|
-
cd example-frontend && bun run sdk
|
|
123
|
+
cd example-frontend && bun run sdk && bun run sync-sdk
|
|
120
124
|
```
|
|
121
125
|
|
|
122
|
-
|
|
126
|
+
Both scripts format their output with Biome. A non-zero exit names the problem: two
|
|
127
|
+
operations sharing a hook name (give one an `operationId`), a missing collection path, or a
|
|
128
|
+
list response without `data.items`.
|
|
123
129
|
|
|
124
|
-
###
|
|
130
|
+
### 7. Stop the backend
|
|
125
131
|
|
|
126
|
-
Kill the background backend
|
|
132
|
+
Kill the background backend you started (and `mongod`, if you started it):
|
|
127
133
|
|
|
128
134
|
```bash
|
|
129
135
|
pkill -f "example-backend.*src/index.ts" || true
|
|
130
136
|
```
|
|
131
137
|
|
|
132
|
-
###
|
|
138
|
+
### 8. Verify and report
|
|
133
139
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
|
|
138
|
-
- Any warnings or errors emitted by the backend or codegen
|
|
140
|
+
```bash
|
|
141
|
+
git diff --stat example-frontend/store/apiSdk.ts example-frontend/store/syncDbSdk.ts
|
|
142
|
+
cd example-frontend && bunx tsc --noEmit
|
|
143
|
+
```
|
|
139
144
|
|
|
140
|
-
|
|
145
|
+
Report which backend changes triggered the run, the diff stat, and any codegen or compile
|
|
146
|
+
errors. Do not commit the generated files automatically.
|
|
141
147
|
|
|
142
148
|
## Common failure modes
|
|
143
149
|
|
|
144
150
|
| Symptom | Cause | Fix |
|
|
145
151
|
|---|---|---|
|
|
146
|
-
| `ECONNREFUSED 127.0.0.1:27017` | MongoDB not running |
|
|
147
|
-
|
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
|
|
|
152
|
+
| `ECONNREFUSED 127.0.0.1:27017` | MongoDB not running | Step 2 |
|
|
153
|
+
| Backend boots but change streams fail | Mongo is not a replica set | Start `mongod --replSet rs0` and initiate it |
|
|
154
|
+
| `EADDRINUSE :::4000` | Stale backend process | `pkill -f "example-backend.*src/index.ts"`, then retry |
|
|
155
|
+
| `fetch failed` / empty output | Backend not ready when codegen ran | Redo step 5 |
|
|
156
|
+
| Duplicate hook name error | Two operations map to one name | Add an `operationId` to one route |
|
|
157
|
+
| Screen imports a hook that no longer exists | Route renamed or excluded | Update the import; check `excludePaths` in `syncdb-codegen.json` |
|
|
151
158
|
|
|
152
159
|
## Notes
|
|
153
160
|
|
|
154
|
-
-
|
|
155
|
-
|
|
156
|
-
-
|
|
161
|
+
- Script definitions: `example-frontend/package.json` (`api-sdk`, `sdk`, `sync-sdk`). They run
|
|
162
|
+
`syncdb/src/codegen/cli.ts` directly; consumer apps call the `terreno-syncdb-codegen` bin.
|
|
163
|
+
- Hook names match the old RTK codegen rule (`GET /auth/me` → `useGetAuthMeQuery`), so
|
|
164
|
+
migrated screens keep their names. Apps upgrading from `@terreno/rtk` follow
|
|
165
|
+
`docs/how-to/migrate-rtk-to-syncdb.md`.
|
|
@@ -41,10 +41,6 @@ modelRouter("/todos", Todo, {
|
|
|
41
41
|
excludeFromCreate: ["ownerId"],
|
|
42
42
|
excludeFromUpdate: ["ownerId"],
|
|
43
43
|
},
|
|
44
|
-
realtime: { // deprecated; removed in Terreno 58 — use `sync` instead
|
|
45
|
-
methods: ["create", "update", "delete"],
|
|
46
|
-
roomStrategy: "owner",
|
|
47
|
-
},
|
|
48
44
|
sync: {scope: {type: "owner"}},
|
|
49
45
|
collectionActions: {
|
|
50
46
|
bulkComplete: {
|