@terreno/mcp 57.21.0 → 58.0.0-beta.1
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/CHANGELOG.md +43 -0
- package/README.md +57 -3
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +17 -16
- package/dist/bootstrap.js.map +1 -1
- package/dist/docs/guidelines/admin-frontend/guidelines/core.md +6 -5
- package/dist/docs/guidelines/ui/guidelines/core.md +1 -1
- package/dist/docs/prompts/debug.md +6 -4
- package/dist/docs/prompts/screen.md +11 -17
- package/dist/docs/resources/overview.md +5 -3
- package/dist/docs/resources/patterns.md +157 -238
- package/dist/docs/resources/syncdb.md +44 -16
- package/dist/docs/templates/bootstrap/CLAUDE.template.md +2 -2
- package/dist/docs/templates/bootstrap/cursorrules.template.md +7 -5
- package/dist/docs/templates/bootstrap/frontend/app/(tabs)/profile.template.tsx +8 -12
- package/dist/docs/templates/bootstrap/frontend/app/_layout.template.tsx +75 -52
- package/dist/docs/templates/bootstrap/frontend/app/login.template.tsx +46 -108
- package/dist/docs/templates/bootstrap/frontend/app/signup.template.tsx +53 -0
- package/dist/docs/templates/bootstrap/frontend/lib/betterAuth.template.md +18 -0
- package/dist/docs/templates/bootstrap/frontend/store/apiClient.template.md +33 -0
- package/dist/docs/templates/bootstrap/frontend/store/apiSdk.template.md +76 -0
- package/dist/docs/templates/bootstrap/frontend/store/syncdb.template.md +56 -0
- package/dist/docs/templates/bootstrap/frontend/utils/index.template.md +0 -4
- package/dist/docs/upgrades/58.0.0-beta.1.md +504 -0
- package/dist/docs/upgrades/58.0.0.md +495 -4
- package/dist/docs/versioned/next/README.md +2 -2
- package/dist/docs/versioned/next/approval-rubric.md +2 -2
- package/dist/docs/versioned/next/explanation/admin-interface.md +6 -5
- package/dist/docs/versioned/next/explanation/admin-plugin-frontend.md +1 -1
- package/dist/docs/versioned/next/explanation/ai-workflows.md +5 -3
- package/dist/docs/versioned/next/explanation/announcements/rtk-deprecation.md +16 -11
- package/dist/docs/versioned/next/explanation/authentication.md +62 -43
- package/dist/docs/versioned/next/explanation/dependency-management.md +1 -1
- package/dist/docs/versioned/next/explanation/deployment-baseline.md +1 -1
- package/dist/docs/versioned/next/explanation/example-coverage.md +2 -2
- package/dist/docs/versioned/next/explanation/explicit-any-policy.md +5 -6
- package/dist/docs/versioned/next/explanation/gcp-hosting-architecture.md +1 -1
- package/dist/docs/versioned/next/explanation/local-first-data.md +11 -9
- package/dist/docs/versioned/next/explanation/model-router-actions.md +1 -1
- package/dist/docs/versioned/next/explanation/modular-api-design.md +2 -2
- package/dist/docs/versioned/next/explanation/no-barrel-imports.md +5 -5
- package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +4 -3
- package/dist/docs/versioned/next/explanation/source-rules.md +2 -2
- package/dist/docs/versioned/next/explanation/typescript-configuration.md +2 -4
- package/dist/docs/versioned/next/explanation/versioning-policy.md +3 -3
- package/dist/docs/versioned/next/how-to/README.md +3 -2
- package/dist/docs/versioned/next/how-to/add-feature-flags.md +50 -25
- package/dist/docs/versioned/next/how-to/add-organizations.md +2 -1
- package/dist/docs/versioned/next/how-to/admin-custom-home.md +8 -2
- package/dist/docs/versioned/next/how-to/admin-custom-widget.md +0 -1
- package/dist/docs/versioned/next/how-to/agent-ui-asks.md +6 -6
- package/dist/docs/versioned/next/how-to/build-admin-screens.md +10 -8
- package/dist/docs/versioned/next/how-to/build-for-web.md +1 -1
- package/dist/docs/versioned/next/how-to/call-external-apis.md +2 -2
- package/dist/docs/versioned/next/how-to/circleci.md +12 -6
- package/dist/docs/versioned/next/how-to/configure-better-auth.md +114 -60
- package/dist/docs/versioned/next/how-to/connect-mcp-service-token.md +10 -4
- package/dist/docs/versioned/next/how-to/create-a-terreno-app.md +14 -2
- package/dist/docs/versioned/next/how-to/debug-with-mcp.md +8 -13
- package/dist/docs/versioned/next/how-to/expose-mcp-tools.md +15 -4
- package/dist/docs/versioned/next/how-to/generate-the-client-sdk.md +33 -0
- package/dist/docs/versioned/next/how-to/github-actions-ci.md +2 -2
- package/dist/docs/versioned/next/how-to/in-app-notifications.md +1 -1
- package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +318 -447
- package/dist/docs/versioned/next/how-to/password-reset.md +1 -1
- package/dist/docs/versioned/next/how-to/product-announcements.md +6 -3
- package/dist/docs/versioned/next/how-to/rate-limiting.md +38 -16
- package/dist/docs/versioned/next/how-to/run-mongodb-migrations.md +19 -0
- package/dist/docs/versioned/next/how-to/run-tests-locally.md +2 -3
- package/dist/docs/versioned/next/how-to/set-up-social-login.md +1 -1
- package/dist/docs/versioned/next/how-to/set-up-terreno-mcp.md +2 -2
- package/dist/docs/versioned/next/how-to/track-upstream-expo.md +1 -1
- package/dist/docs/versioned/next/how-to/upgrade-banner.md +5 -3
- package/dist/docs/versioned/next/how-to/upgrade-terreno.md +5 -5
- package/dist/docs/versioned/next/how-to/use-syncdb-correctly.md +1 -1
- package/dist/docs/versioned/next/how-to/websocket-integration.md +113 -402
- package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +5 -0
- package/dist/docs/versioned/next/implementationPlans/native-module-baseline.md +29 -5
- package/dist/docs/versioned/next/implementationPlans/remove-legacy-realtime.md +1 -1
- package/dist/docs/versioned/next/implementationPlans/remove-rtk.md +185 -0
- package/dist/docs/versioned/next/reference/README.md +1 -1
- package/dist/docs/versioned/next/reference/admin-frontend.md +85 -70
- package/dist/docs/versioned/next/reference/admin-spa.md +10 -4
- package/dist/docs/versioned/next/reference/ai.md +36 -4
- package/dist/docs/versioned/next/reference/announcements.md +3 -3
- package/dist/docs/versioned/next/reference/api.md +39 -24
- package/dist/docs/versioned/next/reference/cli.md +3 -4
- package/dist/docs/versioned/next/reference/environment-variables.md +16 -16
- package/dist/docs/versioned/next/reference/feature-flags.md +48 -7
- package/dist/docs/versioned/next/reference/jobs.md +2 -2
- package/dist/docs/versioned/next/reference/legacy/rtk.md +25 -600
- package/dist/docs/versioned/next/reference/mcp-server.md +441 -1158
- package/dist/docs/versioned/next/reference/syncdb.md +426 -16
- package/dist/docs/versioned/next/reference/test.md +28 -3
- package/dist/docs/versioned/next/reference/ui.md +132 -19
- package/dist/docs/versioned/next/tasks/native-module-baseline.md +8 -4
- package/dist/docs/versioned/next/tasks/rate-limiting.md +9 -2
- package/dist/docs/versioned/next/tasks/remove-legacy-realtime.md +5 -5
- package/dist/docs/versioned/next/tasks/remove-rtk.md +155 -0
- package/dist/local/localTools.d.ts.map +1 -1
- package/dist/local/localTools.js +3 -54
- package/dist/local/localTools.js.map +1 -1
- package/dist/local/tools/runtime.d.ts +0 -21
- package/dist/local/tools/runtime.d.ts.map +1 -1
- package/dist/local/tools/runtime.js +0 -176
- package/dist/local/tools/runtime.js.map +1 -1
- package/dist/local/tools/syncDb.d.ts +0 -11
- package/dist/local/tools/syncDb.d.ts.map +1 -1
- package/dist/local/tools/syncDb.js +1 -5
- package/dist/local/tools/syncDb.js.map +1 -1
- package/dist/packageGuidelines.d.ts +3 -2
- package/dist/packageGuidelines.d.ts.map +1 -1
- package/dist/packageGuidelines.js +4 -11
- package/dist/packageGuidelines.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +17 -18
- package/dist/prompts.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +1 -8
- package/dist/resources.js.map +1 -1
- package/dist/search/chunker.d.ts +1 -1
- package/dist/search/chunker.d.ts.map +1 -1
- package/dist/search/inferPackages.d.ts +1 -1
- package/dist/search/inferPackages.js +5 -5
- package/dist/search/inferPackages.js.map +1 -1
- package/dist/tools.d.ts +6 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +126 -119
- package/dist/tools.js.map +1 -1
- package/package.json +6 -6
- package/src/docs/guidelines/admin-frontend/guidelines/core.md +6 -5
- package/src/docs/guidelines/ui/guidelines/core.md +1 -1
- package/src/docs/prompts/debug.md +6 -4
- package/src/docs/prompts/screen.md +11 -17
- package/src/docs/resources/overview.md +5 -3
- package/src/docs/resources/patterns.md +157 -238
- package/src/docs/resources/syncdb.md +44 -16
- package/src/docs/templates/bootstrap/CLAUDE.template.md +2 -2
- package/src/docs/templates/bootstrap/cursorrules.template.md +7 -5
- package/src/docs/templates/bootstrap/frontend/app/(tabs)/profile.template.tsx +8 -12
- package/src/docs/templates/bootstrap/frontend/app/_layout.template.tsx +75 -52
- package/src/docs/templates/bootstrap/frontend/app/login.template.tsx +46 -108
- package/src/docs/templates/bootstrap/frontend/app/signup.template.tsx +53 -0
- package/src/docs/templates/bootstrap/frontend/lib/betterAuth.template.md +18 -0
- package/src/docs/templates/bootstrap/frontend/store/apiClient.template.md +33 -0
- package/src/docs/templates/bootstrap/frontend/store/apiSdk.template.md +76 -0
- package/src/docs/templates/bootstrap/frontend/store/syncdb.template.md +56 -0
- package/src/docs/templates/bootstrap/frontend/utils/index.template.md +0 -4
- package/src/docs/upgrades/58.0.0-beta.1.md +504 -0
- package/src/docs/upgrades/58.0.0.md +495 -4
- package/src/docs/versioned/next/README.md +2 -2
- package/src/docs/versioned/next/approval-rubric.md +2 -2
- package/src/docs/versioned/next/explanation/admin-interface.md +6 -5
- package/src/docs/versioned/next/explanation/admin-plugin-frontend.md +1 -1
- package/src/docs/versioned/next/explanation/ai-workflows.md +5 -3
- package/src/docs/versioned/next/explanation/announcements/rtk-deprecation.md +16 -11
- package/src/docs/versioned/next/explanation/authentication.md +62 -43
- package/src/docs/versioned/next/explanation/dependency-management.md +1 -1
- package/src/docs/versioned/next/explanation/deployment-baseline.md +1 -1
- package/src/docs/versioned/next/explanation/example-coverage.md +2 -2
- package/src/docs/versioned/next/explanation/explicit-any-policy.md +5 -6
- package/src/docs/versioned/next/explanation/gcp-hosting-architecture.md +1 -1
- package/src/docs/versioned/next/explanation/local-first-data.md +11 -9
- package/src/docs/versioned/next/explanation/model-router-actions.md +1 -1
- package/src/docs/versioned/next/explanation/modular-api-design.md +2 -2
- package/src/docs/versioned/next/explanation/no-barrel-imports.md +5 -5
- package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +4 -3
- package/src/docs/versioned/next/explanation/source-rules.md +2 -2
- package/src/docs/versioned/next/explanation/typescript-configuration.md +2 -4
- package/src/docs/versioned/next/explanation/versioning-policy.md +3 -3
- package/src/docs/versioned/next/how-to/README.md +3 -2
- package/src/docs/versioned/next/how-to/add-feature-flags.md +50 -25
- package/src/docs/versioned/next/how-to/add-organizations.md +2 -1
- package/src/docs/versioned/next/how-to/admin-custom-home.md +8 -2
- package/src/docs/versioned/next/how-to/admin-custom-widget.md +0 -1
- package/src/docs/versioned/next/how-to/agent-ui-asks.md +6 -6
- package/src/docs/versioned/next/how-to/build-admin-screens.md +10 -8
- package/src/docs/versioned/next/how-to/build-for-web.md +1 -1
- package/src/docs/versioned/next/how-to/call-external-apis.md +2 -2
- package/src/docs/versioned/next/how-to/circleci.md +12 -6
- package/src/docs/versioned/next/how-to/configure-better-auth.md +114 -60
- package/src/docs/versioned/next/how-to/connect-mcp-service-token.md +10 -4
- package/src/docs/versioned/next/how-to/create-a-terreno-app.md +14 -2
- package/src/docs/versioned/next/how-to/debug-with-mcp.md +8 -13
- package/src/docs/versioned/next/how-to/expose-mcp-tools.md +15 -4
- package/src/docs/versioned/next/how-to/generate-the-client-sdk.md +33 -0
- package/src/docs/versioned/next/how-to/github-actions-ci.md +2 -2
- package/src/docs/versioned/next/how-to/in-app-notifications.md +1 -1
- package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +318 -447
- package/src/docs/versioned/next/how-to/password-reset.md +1 -1
- package/src/docs/versioned/next/how-to/product-announcements.md +6 -3
- package/src/docs/versioned/next/how-to/rate-limiting.md +38 -16
- package/src/docs/versioned/next/how-to/run-mongodb-migrations.md +19 -0
- package/src/docs/versioned/next/how-to/run-tests-locally.md +2 -3
- package/src/docs/versioned/next/how-to/set-up-social-login.md +1 -1
- package/src/docs/versioned/next/how-to/set-up-terreno-mcp.md +2 -2
- package/src/docs/versioned/next/how-to/track-upstream-expo.md +1 -1
- package/src/docs/versioned/next/how-to/upgrade-banner.md +5 -3
- package/src/docs/versioned/next/how-to/upgrade-terreno.md +5 -5
- package/src/docs/versioned/next/how-to/use-syncdb-correctly.md +1 -1
- package/src/docs/versioned/next/how-to/websocket-integration.md +113 -402
- package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +1 -1
- package/src/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +5 -0
- package/src/docs/versioned/next/implementationPlans/native-module-baseline.md +29 -5
- package/src/docs/versioned/next/implementationPlans/remove-legacy-realtime.md +1 -1
- package/src/docs/versioned/next/implementationPlans/remove-rtk.md +185 -0
- package/src/docs/versioned/next/reference/README.md +1 -1
- package/src/docs/versioned/next/reference/admin-frontend.md +85 -70
- package/src/docs/versioned/next/reference/admin-spa.md +10 -4
- package/src/docs/versioned/next/reference/ai.md +36 -4
- package/src/docs/versioned/next/reference/announcements.md +3 -3
- package/src/docs/versioned/next/reference/api.md +39 -24
- package/src/docs/versioned/next/reference/cli.md +3 -4
- package/src/docs/versioned/next/reference/environment-variables.md +16 -16
- package/src/docs/versioned/next/reference/feature-flags.md +48 -7
- package/src/docs/versioned/next/reference/jobs.md +2 -2
- package/src/docs/versioned/next/reference/legacy/rtk.md +25 -600
- package/src/docs/versioned/next/reference/mcp-server.md +441 -1158
- package/src/docs/versioned/next/reference/syncdb.md +426 -16
- package/src/docs/versioned/next/reference/test.md +28 -3
- package/src/docs/versioned/next/reference/ui.md +132 -19
- package/src/docs/versioned/next/tasks/native-module-baseline.md +8 -4
- package/src/docs/versioned/next/tasks/rate-limiting.md +9 -2
- package/src/docs/versioned/next/tasks/remove-legacy-realtime.md +5 -5
- package/src/docs/versioned/next/tasks/remove-rtk.md +155 -0
- package/dist/docs/guidelines/rtk/guidelines/core.md +0 -26
- package/dist/docs/resources/rtk.md +0 -181
- package/dist/docs/templates/bootstrap/frontend/openapi-config.template.md +0 -16
- package/dist/docs/templates/bootstrap/frontend/scripts/generate-sdk.template.md +0 -49
- package/dist/docs/templates/bootstrap/frontend/store/appState.template.md +0 -45
- package/dist/docs/templates/bootstrap/frontend/store/errors.template.md +0 -51
- package/dist/docs/templates/bootstrap/frontend/store/index.template.md +0 -86
- package/dist/docs/templates/bootstrap/frontend/store/openApiSdk.template.md +0 -49
- package/dist/docs/templates/bootstrap/frontend/store/sdk.template.md +0 -80
- package/src/docs/guidelines/rtk/guidelines/core.md +0 -26
- package/src/docs/resources/rtk.md +0 -181
- package/src/docs/templates/bootstrap/frontend/openapi-config.template.md +0 -16
- package/src/docs/templates/bootstrap/frontend/scripts/generate-sdk.template.md +0 -49
- package/src/docs/templates/bootstrap/frontend/store/appState.template.md +0 -45
- package/src/docs/templates/bootstrap/frontend/store/errors.template.md +0 -51
- package/src/docs/templates/bootstrap/frontend/store/index.template.md +0 -86
- package/src/docs/templates/bootstrap/frontend/store/openApiSdk.template.md +0 -49
- package/src/docs/templates/bootstrap/frontend/store/sdk.template.md +0 -80
|
@@ -597,9 +597,9 @@ pickers, sort menus).
|
|
|
597
597
|
</DropdownPanel>
|
|
598
598
|
``````
|
|
599
599
|
|
|
600
|
-
> `Filter`
|
|
601
|
-
>
|
|
602
|
-
>
|
|
600
|
+
> `Filter` and `FilterProps`, the former names, were removed in Terreno 58. The
|
|
601
|
+
> `FilterSelectMenu` / `FilterBoolean` / `FilterAccordion` / `FilterChangesBadge` controls
|
|
602
|
+
> keep their names.
|
|
603
603
|
|
|
604
604
|
#### Positioning
|
|
605
605
|
|
|
@@ -1251,18 +1251,87 @@ On web, that container is portaled to `document.body` (`position: fixed`, `z-ind
|
|
|
1251
1251
|
|
|
1252
1252
|
Only the visible toast takes clicks. Every full-width layer around it (the container, its safe area, and the `Toast` layout wrapper) uses `pointerEvents: "box-none"`, so a button at the same height as an open toast stays clickable. Declare that style through `StyleSheet.create`; react-native-web drops `pointerEvents` from inline styles.
|
|
1253
1253
|
|
|
1254
|
-
## Consent
|
|
1254
|
+
## Consent and announcement navigators
|
|
1255
1255
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1256
|
+
`ConsentNavigator` and `AnnouncementNavigator` gate authenticated app content on the
|
|
1257
|
+
consent (`@terreno/api` consents) and announcement (`@terreno/announcements`) routes.
|
|
1258
|
+
Both take a request `client` instead of an RTK Query api (the `api` prop was removed in
|
|
1259
|
+
Terreno 58). Pass the app's `@terreno/syncdb/api` client:
|
|
1258
1260
|
|
|
1259
|
-
|
|
1261
|
+
```tsx
|
|
1262
|
+
import {AnnouncementNavigator, ConsentNavigator} from "@terreno/ui";
|
|
1263
|
+
import {apiClient} from "@/store/apiClient"; // createApiClient({authProvider, baseUrl, ...})
|
|
1264
|
+
|
|
1265
|
+
<ConsentNavigator client={apiClient}>
|
|
1266
|
+
<AnnouncementNavigator client={apiClient} frequency={{userId}}>
|
|
1267
|
+
<AppTabs />
|
|
1268
|
+
</AnnouncementNavigator>
|
|
1269
|
+
</ConsentNavigator>
|
|
1270
|
+
```
|
|
1271
|
+
|
|
1272
|
+
### `TerrenoRequestClient`
|
|
1273
|
+
|
|
1274
|
+
`client` is any object with a `request` method of this shape. A syncdb `ApiClient` satisfies
|
|
1275
|
+
it structurally; `@terreno/ui` does not depend on `@terreno/syncdb`.
|
|
1276
|
+
|
|
1277
|
+
```typescript
|
|
1278
|
+
interface TerrenoRequestArgs {
|
|
1279
|
+
url: string; // relative paths resolve against the client's base URL
|
|
1280
|
+
method?: string; // default "GET"
|
|
1281
|
+
params?: Record<string, unknown>; // query string; undefined values are omitted
|
|
1282
|
+
body?: Record<string, unknown> | null;
|
|
1283
|
+
headers?: Record<string, string>;
|
|
1284
|
+
unwrap?: boolean; // unwrap {data} envelopes (default true)
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
interface TerrenoRequestClient {
|
|
1288
|
+
request: <T = unknown>(args: TerrenoRequestArgs) => Promise<T>;
|
|
1289
|
+
}
|
|
1290
|
+
```
|
|
1291
|
+
|
|
1292
|
+
A failed request must reject with an error carrying the HTTP `status` (syncdb's `ApiError`
|
|
1293
|
+
does). On `401` / `403` both navigators render `children` so the app's auth handling runs;
|
|
1294
|
+
any other error shows a **Retry** screen and calls `onError`.
|
|
1295
|
+
|
|
1296
|
+
### `ConsentNavigator` props
|
|
1297
|
+
|
|
1298
|
+
| Prop | Type | Description |
|
|
1299
|
+
|------|------|-------------|
|
|
1300
|
+
| `client` | `TerrenoRequestClient` | Required. Sends `GET /consents/pending` and `POST /consents/respond`. |
|
|
1301
|
+
| `baseUrl` | `string` | Optional path prefix for the consent routes. |
|
|
1302
|
+
| `children` | `ReactNode` | Rendered once no consent forms are pending. |
|
|
1303
|
+
| `extraScreens` | `ReactNode[]` | Shown in order after the forms; each element receives an `onNext` prop. |
|
|
1304
|
+
| `onError` | `(error: unknown) => void` | Called for non-auth load errors and failed submissions. |
|
|
1305
|
+
| `variables` | `Record<string, string>` | Substituted into consent form markdown. |
|
|
1306
|
+
|
|
1307
|
+
### `AnnouncementNavigator` props
|
|
1308
|
+
|
|
1309
|
+
| Prop | Type | Description |
|
|
1310
|
+
|------|------|-------------|
|
|
1311
|
+
| `client` | `TerrenoRequestClient` | Required. Sends `GET /announcements/pending`, `GET /announcements/feed`, and the acknowledge / impression / click events. |
|
|
1312
|
+
| `baseUrl` | `string` | Optional path prefix for the announcement routes. |
|
|
1313
|
+
| `children` | `ReactNode` | App content; hidden behind a modal announcement, kept mounted under a banner. |
|
|
1314
|
+
| `frequency` | `AnnouncementFrequencyConfig` | Client-side interrupt caps (`maxInterruptionsPerSession`, `cooldownHours`, `skipFirstLaunch`, `userId`). |
|
|
1315
|
+
| `onError` | `(error: unknown) => void` | Called for non-auth load errors and failed acknowledgements. |
|
|
1316
|
+
|
|
1317
|
+
### Hooks
|
|
1260
1318
|
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1319
|
+
The navigators are built on hooks you can call directly. Each takes `(client, baseUrl?)` and
|
|
1320
|
+
keeps loading, error, and data in React state.
|
|
1321
|
+
|
|
1322
|
+
| Hook | Returns |
|
|
1323
|
+
|------|---------|
|
|
1324
|
+
| `useConsentForms(client, baseUrl?)` | `{forms, isLoading, error, refetch}` |
|
|
1325
|
+
| `useSubmitConsent(client, baseUrl?)` | `{submit, isSubmitting, error}` |
|
|
1326
|
+
| `useAnnouncements(client, baseUrl?, {page, limit}?)` | `{pending, feed, isLoading, error, refetch, isFeedLoading, feedError, refetchFeed}` |
|
|
1327
|
+
| `useAcknowledgeAnnouncement(client, baseUrl?)` | `{acknowledge, recordImpression, recordClick, isSubmitting, error, ...}` |
|
|
1328
|
+
|
|
1329
|
+
Queries fetch on mount and when `client`, `baseUrl`, or feed paging change. `refetch()` joins
|
|
1330
|
+
a request already in flight. A successful `submit` refetches every mounted `useConsentForms`
|
|
1331
|
+
on the same client, and a successful `acknowledge` refetches every mounted pending
|
|
1332
|
+
announcement on the same client.
|
|
1333
|
+
|
|
1334
|
+
### Provisional signatures on consent forms
|
|
1266
1335
|
|
|
1267
1336
|
When staff signed the form provisionally, the pending form carries
|
|
1268
1337
|
`provisionalSignature: {signedAt, signedByName}` (`ConsentFormPublic`), and the screen shows
|
|
@@ -1284,12 +1353,12 @@ For staff who record consent on a user's behalf. The server must grant the viewe
|
|
|
1284
1353
|
```tsx
|
|
1285
1354
|
import {ProvisionalConsentSigner} from "@terreno/ui";
|
|
1286
1355
|
|
|
1287
|
-
<ProvisionalConsentSigner
|
|
1356
|
+
<ProvisionalConsentSigner client={apiClient} userId={memberId} />
|
|
1288
1357
|
```
|
|
1289
1358
|
|
|
1290
1359
|
| Prop | Type | Description |
|
|
1291
1360
|
| --- | --- | --- |
|
|
1292
|
-
| `
|
|
1361
|
+
| `client` | `TerrenoRequestClient` | The app's request client, as passed to `ConsentNavigator` |
|
|
1293
1362
|
| `baseUrl` | `string` | Optional prefix for consent routes |
|
|
1294
1363
|
| `userId` | `string` | The user being signed for |
|
|
1295
1364
|
| `onSigned` | `(response) => void` | Called with the stored `ConsentResponse` after a provisional signature |
|
|
@@ -1318,14 +1387,14 @@ the signer, date, and note. Provisional rows also have "Void". It opens a dialog
|
|
|
1318
1387
|
a required reason, sends it to `POST /consent-responses/:id/void`, and refetches, so the row
|
|
1319
1388
|
returns to "Pending". A void error shows in the dialog and calls `onError`.
|
|
1320
1389
|
|
|
1321
|
-
`useProvisionalConsent({
|
|
1390
|
+
`useProvisionalConsent({client, baseUrl?, userId})` returns `{statuses, isLoading, error,
|
|
1322
1391
|
refetch, sign, isSigning, voidSignature, isVoiding}`. `statuses` are `ProvisionalConsentStatusRow`s
|
|
1323
1392
|
(`{form, status, isConsented, respondedAt?, provisional?}`). `sign({consentFormId, note,
|
|
1324
1393
|
locale?})` signs for the hook's `userId` and resolves to the `ConsentResponse`, or rejects
|
|
1325
|
-
with the
|
|
1326
|
-
same way. The hook
|
|
1327
|
-
`
|
|
1328
|
-
`
|
|
1394
|
+
with the request error. `voidSignature({responseId, reason})` voids a provisional signature the
|
|
1395
|
+
same way. The hook requests `GET /consent-responses/status`, `POST /consent-responses/provisional`,
|
|
1396
|
+
and `POST /consent-responses/:id/void` on the client. Signing and voiding refetch every mounted
|
|
1397
|
+
`useProvisionalConsent` and `useConsentForms` on the same client.
|
|
1329
1398
|
|
|
1330
1399
|
testIDs: `provisional-consent-signer`, `provisional-consent-loading`,
|
|
1331
1400
|
`provisional-consent-error`, `provisional-consent-retry-button`, `provisional-consent-empty`,
|
|
@@ -2391,6 +2460,21 @@ describe("MyComponent", () => {
|
|
|
2391
2460
|
|
|
2392
2461
|
**Why:** Most @terreno/ui components require ThemeProvider context to access theme values.
|
|
2393
2462
|
|
|
2463
|
+
### createFakeRequestClient
|
|
2464
|
+
|
|
2465
|
+
In-repo test helper (`ui/src/test-utils.tsx`) for components that take a
|
|
2466
|
+
`TerrenoRequestClient`. Routes are `"METHOD /path/:param"` keys; unmatched requests reject
|
|
2467
|
+
with a 404-shaped error. `fakeHttpError(status)` builds an error carrying `status`.
|
|
2468
|
+
|
|
2469
|
+
``````typescript
|
|
2470
|
+
const {client, callsTo} = createFakeRequestClient({
|
|
2471
|
+
"GET /consents/pending": () => ({data: [form]}),
|
|
2472
|
+
"POST /consents/respond": () => ({agreed: true}),
|
|
2473
|
+
});
|
|
2474
|
+
renderWithTheme(<ConsentNavigator client={client}>{children}</ConsentNavigator>);
|
|
2475
|
+
expect(callsTo("POST /consents/respond")).toHaveLength(1);
|
|
2476
|
+
``````
|
|
2477
|
+
|
|
2394
2478
|
### TapToEdit testIDs
|
|
2395
2479
|
|
|
2396
2480
|
Pass `testID` on `TapToEdit`. The Field input uses that id. Action controls suffix it:
|
|
@@ -2823,6 +2907,35 @@ for that type:
|
|
|
2823
2907
|
A value that is already formatted, such as "Oct 8, 2026, 3:00 PM", is not ISO, so a `date`
|
|
2824
2908
|
column shows it unchanged.
|
|
2825
2909
|
|
|
2910
|
+
## DataTable column widths
|
|
2911
|
+
|
|
2912
|
+
`width` on a `DataTableColumn` is optional. A column with a `width` is always that many
|
|
2913
|
+
pixels. A column without one is sized automatically:
|
|
2914
|
+
|
|
2915
|
+
1. Its natural width is the wider of its header (title plus the sort, info, and filter icons)
|
|
2916
|
+
and its content, plus cell padding, clamped to 80–360px. Content is read from at most 50
|
|
2917
|
+
rows, spread evenly across `data`. Dates are measured as formatted; boolean cells are a
|
|
2918
|
+
fixed icon width; custom cells whose value is not a string or number count as 120px.
|
|
2919
|
+
2. When the table body is wider than the sum of all columns, auto-sized columns grow to fill
|
|
2920
|
+
it, in proportion to their natural widths. When the columns are wider than the body, they
|
|
2921
|
+
keep their natural widths and the table scrolls horizontally.
|
|
2922
|
+
|
|
2923
|
+
Text is measured with one shared canvas on web and estimated from font size on native, so
|
|
2924
|
+
sizing never renders or lays out extra cells. Measurement reruns only when `columns`, `data`,
|
|
2925
|
+
`defaultTextSize`, or `customColumnComponentMap` change; a container resize only reruns the
|
|
2926
|
+
fill step. Keep `columns` and `data` referentially stable between renders.
|
|
2927
|
+
|
|
2928
|
+
```typescript
|
|
2929
|
+
const columns: DataTableColumn[] = [
|
|
2930
|
+
{columnType: "text", title: "Name"}, // auto
|
|
2931
|
+
{columnType: "text", title: "Email"}, // auto
|
|
2932
|
+
{columnType: "number", title: "Visits"}, // auto
|
|
2933
|
+
{columnType: "custom", title: "", width: 60}, // fixed
|
|
2934
|
+
];
|
|
2935
|
+
```
|
|
2936
|
+
|
|
2937
|
+
Custom cell components receive the column with its resolved `width`.
|
|
2938
|
+
|
|
2826
2939
|
## DataTable server-side filtering
|
|
2827
2940
|
|
|
2828
2941
|
`DataTable` is data-layer agnostic. Optional filter and search props emit a
|
|
@@ -4,16 +4,18 @@ IP: [native-module-baseline](../implementationPlans/native-module-baseline.md)
|
|
|
4
4
|
|
|
5
5
|
## Phase 1 — Dependencies + config
|
|
6
6
|
|
|
7
|
-
- [
|
|
7
|
+
- [x] **Task 1.1**: Catalog + app package manifests
|
|
8
8
|
- Description: add the seven packages to root catalog (sorted) and to example-frontend + demo deps via `catalog:`
|
|
9
9
|
- Files: root `package.json`, `example-frontend/package.json`, `demo/package.json`
|
|
10
10
|
- Depends on: none
|
|
11
11
|
- Acceptance: `bun install` + full compile green
|
|
12
|
-
-
|
|
12
|
+
- Done: six of seven manifest entries landed; `react-native-otp-verify` dropped (no New Architecture support). See IP Implementation notes.
|
|
13
|
+
- [x] **Task 1.2**: Config plugins + build properties
|
|
13
14
|
- Description: stripe + purchases plugins; `expo-build-properties` Kotlin 2.x / compileSdk 36 pins
|
|
14
15
|
- Files: `example-frontend/app.json`, `demo/app.json`
|
|
15
16
|
- Depends on: 1.1
|
|
16
17
|
- Acceptance: `expo config` resolves without errors; web export unaffected
|
|
18
|
+
- Done: stripe + local-authentication + build-properties plugins. `react-native-purchases` ships no config plugin. compileSdk pinned to 37 (RN 0.88 default), not 36.
|
|
17
19
|
|
|
18
20
|
## Phase 2 — Builds + verification
|
|
19
21
|
|
|
@@ -22,16 +24,18 @@ IP: [native-module-baseline](../implementationPlans/native-module-baseline.md)
|
|
|
22
24
|
- Files: `eas.json` profiles if needed
|
|
23
25
|
- Depends on: Phase 1
|
|
24
26
|
- Acceptance: both builds compile
|
|
25
|
-
- [
|
|
27
|
+
- [x] **Task 2.2**: Diagnostics story
|
|
26
28
|
- Description: hidden demo story listing resolved native module versions
|
|
27
29
|
- Files: `demo/stories/NativeModules.stories.tsx`, `demo/demoConfig.tsx`
|
|
28
30
|
- Depends on: 2.1
|
|
29
31
|
- Acceptance: story shows all seven modules on a dev build; screenshot evidence
|
|
30
|
-
-
|
|
32
|
+
- Done: hidden `Native Modules` page (`hidden: true` config, routable at `/demo/Native%20Modules`). Web screenshot only; on-device check waits on Task 2.1.
|
|
33
|
+
- [x] **Task 2.3**: Expo Go degradation doc
|
|
31
34
|
- Description: document which flows need a dev build (stripe, local-auth) vs preview modes (purchases)
|
|
32
35
|
- Files: `docs/` upgrade note draft
|
|
33
36
|
- Depends on: 2.1
|
|
34
37
|
- Acceptance: reviewed checklist in the note
|
|
38
|
+
- Done: Expo Go table in `mcp-server/src/docs/upgrades/58.0.0.md`.
|
|
35
39
|
|
|
36
40
|
## Phase 3 — Release
|
|
37
41
|
|
|
@@ -8,12 +8,12 @@ IP: [rate-limiting.md](../implementationPlans/rate-limiting.md)
|
|
|
8
8
|
## Phase 1 — Tracer (memory, TerrenoApp)
|
|
9
9
|
|
|
10
10
|
- [x] **Task 1.1**: Rate-limit module + TerrenoApp mount
|
|
11
|
-
- Delivers: `rateLimit: {}` on `TerrenoApp` limits HTTP; omitted option
|
|
11
|
+
- Delivers: `rateLimit: {}` on `TerrenoApp` limits HTTP; omitted option used to be a no-op (Terreno 58 default-on — see Task 5.1); `POST /auth/login` uses the auth bucket (20 / 15 min); modelRouter list uses `api` (600 / 15 min); skip `/health` and `/openapi.json`; 429 `APIError` `code: "rate-limit-exceeded"` with `Retry-After` and IETF `RateLimit` / `RateLimit-Policy`; memory store; `trust proxy` default `1` when enabled
|
|
12
12
|
- Files: `api/src/rateLimit/types.ts`, `api/src/rateLimit/store.ts`, `api/src/rateLimit/memoryStore.ts`, `api/src/rateLimit/policies.ts`, `api/src/rateLimit/middleware.ts`, `api/src/rateLimit/rateLimit.test.ts`, `api/src/terrenoApp.ts`, `api/src/index.ts`, `api/src/api.ts` (remove `TODO add rate limit`)
|
|
13
13
|
- Blocked by: none
|
|
14
14
|
- Skills: `terreno-backend-api`, `backend-test-env`, `update-docs`
|
|
15
15
|
- Docs: stub section in `docs/reference/api.md` (`rateLimit` option) so the tracer is documented when it lands
|
|
16
|
-
- Acceptance: bun tests —
|
|
16
|
+
- Acceptance: bun tests — with limiter off (`rateLimit: false`), burst login no 429; auth 20 then 429; 21st list GET still 200; 601st list 429; `/health` never 429; 429 body/headers; login classified auth
|
|
17
17
|
|
|
18
18
|
## Phase 2 — Shared stores
|
|
19
19
|
|
|
@@ -68,3 +68,10 @@ IP: [rate-limiting.md](../implementationPlans/rate-limiting.md)
|
|
|
68
68
|
- Blocked by: 4.1
|
|
69
69
|
- Skills: `update-docs`
|
|
70
70
|
- Acceptance: seed `Implementation plan` / `Tasks` links are not `*(not yet written)*`
|
|
71
|
+
|
|
72
|
+
## Phase 5 — Terreno 58
|
|
73
|
+
|
|
74
|
+
- [x] **Task 5.1**: Default the limiter on
|
|
75
|
+
- Delivers: omitted `rateLimit` mounts the memory limiter with default limits; `rateLimit: false` turns it off; `{}` / options unchanged; example-backend passes `{trustProxy: 1}` when deployed and `false` locally; 58 upgrade note
|
|
76
|
+
- Files: `api/src/terrenoApp.ts`, `api/src/rateLimit/rateLimit.test.ts`, `example-backend/src/server.ts`, `docs/how-to/rate-limiting.md`, `docs/reference/api.md`, `mcp-server/src/docs/upgrades/58.0.0.md`, `.rulesync/rules/api/00-api.md`
|
|
77
|
+
- Acceptance: omitted → 429 on the 21st login; `false` → 25 logins succeed; `{}` → 429 on the 21st login; backend suites stay green
|
|
@@ -28,31 +28,31 @@ See: [`docs/implementationPlans/remove-legacy-realtime.md`](../implementationPla
|
|
|
28
28
|
|
|
29
29
|
## Phase 2: Delete in Terreno 58
|
|
30
30
|
|
|
31
|
-
- [
|
|
31
|
+
- [x] **Task 2.1**: Remove `modelRouter` `realtime` registration
|
|
32
32
|
- Delivers: passing `realtime` is a type error; no `registerRealtime` from `modelRouter`
|
|
33
33
|
- Files: `api/src/api.ts`, `api/src/realtime/types.ts`, `api/src/realtime/deprecation.ts`, `api/src/index.ts`, `api/src/api.test.ts`
|
|
34
34
|
- Blocked by: Terreno 58 major
|
|
35
35
|
- Acceptance: TypeScript and tests fail if a router still passes `realtime`; `sync` registration is unchanged
|
|
36
36
|
|
|
37
|
-
- [
|
|
37
|
+
- [x] **Task 2.2**: Stop emitting legacy `sync` (RTK) websocket events
|
|
38
38
|
- Delivers: change streams emit `sync:delta` only for synced models; no RTK `sync` payload
|
|
39
39
|
- Files: `api/src/realtime/changeStreamWatcher.ts`, `api/src/realtime/realtimeApp.ts`, `api/src/realtime/registry.ts`, related tests
|
|
40
40
|
- Blocked by: Task 2.1
|
|
41
41
|
- Acceptance: a model with only `sync` still emits `sync:delta`; no `sync` events for collection CRUD; `admin:model.changed` still works when `admin.realtime` is true
|
|
42
42
|
|
|
43
|
-
- [
|
|
43
|
+
- [x] **Task 2.3**: Remove `@terreno/rtk` cache-patching helpers
|
|
44
44
|
- Delivers: `realtimeList`, `realtimeDocument`, `setRealtimeSocket`, `getRealtimeSocket` are gone from the package
|
|
45
45
|
- Files: `rtk/src/realtime.ts`, `rtk/src/realtime.test.ts`, `rtk/src/index.ts`, `rtk/README.md`
|
|
46
46
|
- Blocked by: Task 2.1
|
|
47
47
|
- Acceptance: package compile fails if those symbols are imported; `useSocketConnection` still exists
|
|
48
48
|
|
|
49
|
-
- [
|
|
49
|
+
- [x] **Task 2.4**: Remove example and bootstrap usage
|
|
50
50
|
- Delivers: example-backend/example-frontend/MCP bootstrap do not configure RTK realtime
|
|
51
51
|
- Files: `example-backend/src/api/todos.ts`, `example-frontend/store/sdk.ts`, `example-frontend/app/_layout.tsx`, MCP bootstrap templates
|
|
52
52
|
- Blocked by: Task 2.3
|
|
53
53
|
- Acceptance: todos stay on `sync` + syncdb; `setRealtimeSocket` / `realtimeList` / `realtimeDocument` are gone; `RealtimeApp` remains registered
|
|
54
54
|
|
|
55
|
-
- [
|
|
55
|
+
- [x] **Task 2.5**: Docs, skills, changelog, 58.0.0 upgrade note
|
|
56
56
|
- Delivers: upgrade note lists every removed symbol and the syncdb replacement
|
|
57
57
|
- Files: `docs/how-to/migrate-rtk-to-syncdb.md`, `docs/reference/api.md`, `.rulesync/skills/terreno-data-fetching/references/realtime.md`, `.rulesync/skills/terreno-backend-api/references/model-router.md`, `mcp-server/src/docs/upgrades/58.0.0.md`, changelog
|
|
58
58
|
- Blocked by: Task 2.4
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Task List: Remove @terreno/rtk and Redux in Terreno 58
|
|
2
|
+
|
|
3
|
+
See: [`docs/implementationPlans/remove-rtk.md`](../implementationPlans/remove-rtk.md)
|
|
4
|
+
|
|
5
|
+
**Target:** Terreno **58.0.0**, branch `remove-rtk-58`, one PR into `release-58.0.0`.
|
|
6
|
+
|
|
7
|
+
Wide refactor: **expand → migrate → contract**. Every task leaves the branch compiling and
|
|
8
|
+
green. Phase 4.1 (delete `rtk/`) is blocked by every migration task.
|
|
9
|
+
|
|
10
|
+
**Supporting skills:** `terreno-data-fetching`, `terreno-backend-api`,
|
|
11
|
+
`mongoose-schema-safety`, `building-terreno-apps`, `building-admin-interfaces`, `terreno-ui`,
|
|
12
|
+
`backend-test-env`, `verify-ui-changes`, `update-docs`, `generate-sdk` (rewrite in 4.2).
|
|
13
|
+
|
|
14
|
+
## Phase 1: Expand syncdb
|
|
15
|
+
|
|
16
|
+
- [x] **Task 1.1** (tracer): Request client + query/mutation hooks + `/config`
|
|
17
|
+
- Delivers: `createApiClient({baseUrl, authProvider, credentials?, headers?})` and `useApiQuery` / `useLazyApiQuery` / `useApiMutation` / `ApiClientProvider`, with a shared per-client cache keyed by URL+args, tag invalidation, `{data}` / list-envelope unwrap matching RTK, 401 → `authProvider.refresh` → retry, `App-Version` / `App-Platform` headers. `@terreno/syncdb/config` exports `baseUrl`, `baseWebsocketsUrl`, `resolveBaseUrls`, `resolveDevApiPort` (moved from `rtk/src/constants.ts` with their tests). example-frontend profile screen reads `GET /auth/me` through `useApiQuery`; `store/syncdb.ts` imports `baseUrl` from `@terreno/syncdb/config`.
|
|
18
|
+
- Files: `syncdb/src/api/{client,cache,hooks}.ts` + tests, `syncdb/src/config/baseUrl.ts` + tests, `syncdb/package.json` exports, `admin-frontend/src/{adminRequest,useAdminRpc}.ts` (wrap the syncdb client), `example-frontend/app/(tabs)/profile.tsx`, `example-frontend/store/syncdb.ts`
|
|
19
|
+
- Blocked by: none
|
|
20
|
+
- Acceptance: bun tests for dedupe, tag invalidation, envelope unwrap, refresh-retry, abort/timeout; admin-frontend tests still pass unchanged; profile e2e passes
|
|
21
|
+
- Docs: `docs/reference/syncdb.md` (API client, config sections)
|
|
22
|
+
|
|
23
|
+
- [x] **Task 1.2**: Codegen for every non-synced OpenAPI operation
|
|
24
|
+
- Delivers: `terreno-syncdb generate` also emits typed request/response types and `useXQuery` / `useXMutation` hooks for every operation without `x-terreno-sync`, including plain routes (`/auth/me`, `/consents/pending`, `/files/upload` multipart, `/version-check`). Tags inferred per path. example-frontend `bun run sdk` runs it and writes `store/apiSdk.ts`; profile screen switches to the generated `useGetAuthMeQuery`.
|
|
25
|
+
- Also: add OpenAPI docs for the 13 frontend-called routes the spec omits — `GET/PATCH /auth/me`, `POST /auth/{sendVerification,forgotPassword,verifyEmail}`, `POST /resetPassword` (`api`); `GET /feature-flags/flagConfiguration` (`feature-flags`); `GET /version-check` (`api`); `GET /consents/pending`, `POST /consents/respond` (`api`); `GET /announcements/{pending,feed}`, `POST /announcements/{id}/{acknowledge,click,impression}` (`announcements`); `POST /files/upload` multipart (`ai`).
|
|
26
|
+
- Files: `syncdb/src/codegen/{emitApi,discoverOperations}.ts` + fixtures/tests, `syncdb/src/codegen/{cli,generate}.ts`, `example-frontend/scripts/generate-sdk.ts`, `example-frontend/store/apiSdk.ts` (generated), OpenAPI registrations in the owning packages + their route tests
|
|
27
|
+
- Blocked by: 1.1
|
|
28
|
+
- Acceptance: codegen tests against fixture spec cover query, mutation, path params, multipart, synced ops excluded; generated file compiles in example-frontend; live `/openapi.json` lists all 13 previously missing routes
|
|
29
|
+
- Docs: `docs/reference/syncdb.md` (codegen), `docs/how-to/` page for regenerating the SDK
|
|
30
|
+
|
|
31
|
+
- [x] **Task 1.3**: `@terreno/syncdb/auth` — Better Auth client + session without Redux
|
|
32
|
+
- Delivers: `createBetterAuthClient`, `createStorageAdapter`, cookie-jar repair (moved with tests), `SessionProvider` + `useSession()` → `{userId, user, isLoading, isAuthenticated, error, logout}`; `logout` signs out, stops syncdb, wipes local data. example-frontend `lib/betterAuth.ts` imports from syncdb.
|
|
33
|
+
- Files: `syncdb/src/auth/{betterAuthClient,session,SessionProvider}.ts(x)` + tests, `syncdb/package.json` (move `better-auth`, `@better-auth/expo`, `expo-secure-store`, async-storage deps/peers), `example-frontend/lib/betterAuth.ts`
|
|
34
|
+
- Blocked by: 1.1
|
|
35
|
+
- Acceptance: ported `betterAuthClient` / `betterAuthSlice` behaviours as hook tests (session sync on start, after login, logout side effects)
|
|
36
|
+
- Docs: `docs/reference/syncdb.md` (auth), `docs/explanation/authentication.md`, `docs/how-to/configure-better-auth.md`
|
|
37
|
+
|
|
38
|
+
- [x] **Task 1.4**: Port legacy JWT frontend auth
|
|
39
|
+
- Delivers: `jwtAuthAdapter` (token storage on SecureStore/AsyncStorage, refresh when < 2 min to expiry, mutex, 401 → refresh → retry, logout on refresh failure) and `useJwtAuth()` (`login`, `signup`, `googleLogin`, `resetPassword`, `logout`) feeding `SessionProvider`; token-expiry helpers (`getTokenExpirationTimes`, `shouldShowStillThereModal`).
|
|
40
|
+
- Files: `syncdb/src/auth/{jwtAuthAdapter,useJwtAuth,tokenExpiry}.ts` + tests (ported from `rtk/src/authSlice*.test.ts`, `rtk/src/isolated/emptyApi*.isolated.ts`)
|
|
41
|
+
- Blocked by: 1.3
|
|
42
|
+
- Acceptance: AC9 — ported tests pass against an `api` test server using JWT auth
|
|
43
|
+
- Docs: `docs/explanation/authentication.md`, `docs/reference/syncdb.md`
|
|
44
|
+
|
|
45
|
+
- [x] **Task 1.5**: Socket event API + `@terreno/syncdb/flags`
|
|
46
|
+
- Delivers: `client.onSocketEvent` / `useSocketEvent`; `useFeatureFlags(client)` / `useTerrenoFeatureFlags` (OpenFeature provider) fetching via the request client and refetching on the flags push event. example-frontend `_layout.tsx` drops `useSocketConnection` / `useRealtimeDebug`. Server deprecation message updated.
|
|
47
|
+
- Files: `syncdb/src/sync/socketTransport.ts`, `syncdb/src/react/useSocketEvent.ts`, `syncdb/src/flags/*` + tests (ported from `rtk/src/useFeatureFlags.test.ts`, `useTerrenoFeatureFlags.test.ts`), `feature-flags/src/featureFlagsApp.ts`, `example-frontend/app/_layout.tsx`, `(tabs)/{ai,documents,profile}.tsx`
|
|
48
|
+
- Blocked by: 1.1
|
|
49
|
+
- Acceptance: AC7 — Playwright spec asserts one socket.io connection and a pushed flag change updates the UI
|
|
50
|
+
- Docs: `docs/reference/feature-flags.md`, `docs/how-to/add-feature-flags.md`, `docs/how-to/websocket-integration.md`
|
|
51
|
+
|
|
52
|
+
- [x] **Task 1.6**: `@terreno/syncdb/app` and `/buildNumber`
|
|
53
|
+
- Delivers: `useUpgradeCheck` (on the request client), `hasPermission` / `canOpenAdminPage`, `installDevConsoleLogger`, `useMCPTools` (token from the shared AuthProvider, fixing the Better Auth gap), `buildNumber` node subpath — all moved with tests. example-frontend uses them.
|
|
54
|
+
- Files: `syncdb/src/app/*`, `syncdb/src/buildNumber.ts` + tests, `example-frontend/app/_layout.tsx`, `app/admin/_layout.tsx`, `(tabs)/{ai,profile}.tsx`
|
|
55
|
+
- Blocked by: 1.1
|
|
56
|
+
- Acceptance: ported `useUpgradeCheck*`, `usePermissions`, `devConsoleLogger`, `useMCPTools`, `buildNumber` tests pass
|
|
57
|
+
- Docs: `docs/how-to/upgrade-banner.md`, `docs/how-to/expose-mcp-tools.md`, `docs/reference/syncdb.md`
|
|
58
|
+
|
|
59
|
+
## Phase 2: Backend sync for GptHistory and McpServiceToken
|
|
60
|
+
|
|
61
|
+
- [x] **Task 2.1**: GptHistory synced with string ids + migration
|
|
62
|
+
- Delivers: String `_id` (UUID default), `syncPlugin` + `isDeletedPlugin`, `sync: {scope: owner}` on `/gpt/histories`; `AIDataset.historyId` String; `gpt-history-string-ids` migration; SSE / turn / actions routes accept string ids. Backend example registers the stream.
|
|
63
|
+
- Files: `ai/src/models/{gptHistory,aiDataset}.ts`, `ai/src/routes/{gptHistories,gpt,gptActions}.ts`, `ai/src/migrations/gptHistoryStringIds.ts` + tests, `example-backend/src/server.ts`
|
|
64
|
+
- Blocked by: none
|
|
65
|
+
- Acceptance: AC5; existing `ai` route tests pass with string ids; sync snapshot test returns only the owner's histories
|
|
66
|
+
- Docs: `docs/reference/ai.md`, `.rulesync/rules/ai/00-ai.md`, 58.0.0 upgrade notes (run migration first)
|
|
67
|
+
- Skills: `mongoose-schema-safety`
|
|
68
|
+
|
|
69
|
+
- [x] **Task 2.2**: McpServiceToken synced read-only + actions + migration
|
|
70
|
+
- Delivers: `modelRouter("/mcp/service-tokens", McpServiceToken, {sync})` with client writes disabled, sync `responseHandler` stripping `tokenHash`; `collectionActions.create` (plaintext once), `instanceActions.revoke`; `mcp-service-token-string-ids` migration; `verify` unchanged.
|
|
71
|
+
- Files: `api/src/models/mcpServiceToken.ts`, `api/src/mcp/serviceTokens.ts`, `api/src/migrations/` (built-in migration), tests
|
|
72
|
+
- Blocked by: none
|
|
73
|
+
- Acceptance: AC6; migration idempotence test; existing MCP auth tests pass
|
|
74
|
+
- Docs: `docs/reference/mcp-server.md` / service-token how-to, upgrade notes
|
|
75
|
+
|
|
76
|
+
## Phase 3: Migrate consumers
|
|
77
|
+
|
|
78
|
+
- [x] **Task 3.1**: `@terreno/ui` consents and announcements take `client`
|
|
79
|
+
- Delivers: `TerrenoRequestClient` structural interface; `ConsentNavigator`, `AnnouncementNavigator`, `useConsentForms`, `useSubmitConsent`, `useAnnouncements`, `useAcknowledgeAnnouncement` take `client`; no `injectEndpoints`. Tests use a fake client.
|
|
80
|
+
- Files: `ui/src/requestClient.ts`, the six source files above and their tests, `ui/src/OfflineBanner.tsx` (JSDoc)
|
|
81
|
+
- Blocked by: 1.1
|
|
82
|
+
- Acceptance: ui suite green; `rg injectEndpoints ui/src` → none
|
|
83
|
+
- Docs: `docs/reference/ui.md` (consent / announcement props)
|
|
84
|
+
|
|
85
|
+
- [x] **Task 3.2**: example-frontend — remove Redux store, session, auth screens
|
|
86
|
+
- Delivers: delete `store/index.ts`, `store/appState.ts` Redux slice (→ context + `useStoredState`), `store/errors.ts` middleware (→ client `onError` reporting to Sentry), `store/betterAuthApi.ts`; root layout uses `SessionProvider` + `ApiClientProvider`; login, signup, forgot / reset password, verify email use generated hooks / `useSession`.
|
|
87
|
+
- Files: `example-frontend/store/*`, `app/_layout.tsx`, `app/{login,signup,forgotPassword,resetPassword,verifyEmail}.tsx`, `lib/authRecoveryActions.ts`, related tests
|
|
88
|
+
- Blocked by: 1.2, 1.3, 1.5, 1.6, 3.1
|
|
89
|
+
- Acceptance: auth e2e shard green; unit suite green
|
|
90
|
+
- Docs: `example-frontend/README.md`, `.rulesync/rules/example-frontend/00-example-frontend.md`
|
|
91
|
+
|
|
92
|
+
- [x] **Task 3.3**: example-frontend — profile, admin layout, notifications, documents, push tokens
|
|
93
|
+
- Delivers: all remaining non-AI screens on generated hooks; `store/sdk.ts`, `store/openApiSdk.ts`, `store/commsOpenApiSdk.ts`, `openapi-config.ts`, `comms-openapi-config.ts` deleted.
|
|
94
|
+
- Files: `app/(tabs)/{profile,documents}.tsx`, `app/admin/**`, `components/NotificationCenter.tsx`, `components/TodoSummaryCard.tsx`, `app/gcs-settings.tsx`, `hooks/useSyncLabEngines.ts`, `app/admin/SyncLabScreen.tsx`
|
|
95
|
+
- Blocked by: 3.2
|
|
96
|
+
- Acceptance: app + admin-core + admin-table e2e shards green
|
|
97
|
+
- Docs: none beyond 3.2 (record skip)
|
|
98
|
+
|
|
99
|
+
- [x] **Task 3.4**: example-frontend — AI screen and MCP settings on syncdb
|
|
100
|
+
- Delivers: `ai.tsx` histories via `useQuery("gptHistories")` / `useMutate` (rename, delete), no `updateQueryData` / `invalidateTags`; SSE uses the shared auth provider; MCP settings list via `useQuery("mcpServiceTokens")`, create/revoke via generated action hooks; `useMCPTools` from `/app`.
|
|
101
|
+
- Files: `app/(tabs)/ai.tsx`, `app/settings/mcp/index.tsx`, `store/syncdb.ts` (collections), `lib/gptAsks.ts`
|
|
102
|
+
- Blocked by: 2.1, 2.2, 3.2
|
|
103
|
+
- Acceptance: `ai-chat` e2e green incl. list / rename / delete across reload; new MCP tokens spec green
|
|
104
|
+
- Docs: `docs/how-to/` AI chat page if it names RTK hooks
|
|
105
|
+
|
|
106
|
+
- [x] **Task 3.5**: example-frontend tests off RTK
|
|
107
|
+
- Delivers: `tests/bunSetup.ts` / `testPreload.ts` no longer import or mock `@/store/sdk`; `documents.test.tsx`, `NotificationCenter.test.tsx`, `orgMembersRoute.test.tsx`, `errors.test.ts`, `gptAsks.test.ts`, `TodoSummaryCard.test.tsx` use the syncdb client / fake transport; e2e allowlists and comments drop RTK entries (`consoleAllowlist.ts`, `syncdbSuite.ts`, `offlineHelpers.ts`, `adminAuth.ts`, `login` / `signup` / `admin-todo-crud` specs).
|
|
108
|
+
- Files: listed above
|
|
109
|
+
- Blocked by: 3.3, 3.4
|
|
110
|
+
- Acceptance: AC3 and AC4 for example-frontend
|
|
111
|
+
- Docs: none (record skip)
|
|
112
|
+
|
|
113
|
+
- [x] **Task 3.6**: admin-spa off Redux
|
|
114
|
+
- Delivers: `StoreProvider` / `AdminGate` use `SessionProvider` (cookie mode); profile via the request client with `credentials: "same-origin"`; `store/sdk.ts` deleted; Redux deps removed.
|
|
115
|
+
- Files: `admin-spa/components/{StoreProvider,AdminGate,AdminSpaShell}.tsx`, `admin-spa/app/orgs/index.tsx`, `admin-spa/store/*`, `admin-spa/src/adminSpaUiCoverage.test.tsx`, `admin-spa/package.json`, `admin-spa/metro.config.js`
|
|
116
|
+
- Blocked by: 1.1, 1.3
|
|
117
|
+
- Acceptance: `bun run admin-spa:test` + admin-spa e2e and integration specs green
|
|
118
|
+
- Docs: `docs/reference/admin-spa*` / `docs/reference/admin-frontend.md` references
|
|
119
|
+
|
|
120
|
+
- [x] **Task 3.7**: admin-frontend RTK-shaped test doubles
|
|
121
|
+
- Delivers: observability / prompts isolated tests use fake request clients instead of `injectEndpoints` APIs; RTK wording in assertions removed.
|
|
122
|
+
- Files: `admin-frontend/src/isolated/{observabilityFakeApi,aiObservabilityScreens,AiPromptsListScreen,AiPromptEditorScreen,adminRpcHooks}.isolated.tsx`, the other test files named in the IP research
|
|
123
|
+
- Blocked by: 1.1
|
|
124
|
+
- Acceptance: admin-frontend suite green; `rg -i "rtk|injectEndpoints" admin-frontend/src` → none
|
|
125
|
+
- Docs: `.rulesync/rules/admin-frontend/00-admin-frontend.md` (layout example imports `baseUrl` from `/config`)
|
|
126
|
+
|
|
127
|
+
- [x] **Task 3.8**: Generators, MCP tools, cli
|
|
128
|
+
- Delivers: `create-terreno-app` scaffolds syncdb client, `SessionProvider`, generated `apiSdk.ts`, no Redux / rtk; `mcp-server` bootstrap templates, prompts, `tools.ts` (`generateInstallAdmin`), `resources.ts` (drop `terreno://docs/rtk`) updated; `get_rtk_state` and `terreno state --slice rtk` removed in favour of syncdb state tools.
|
|
129
|
+
- Files: `create-terreno-app/src/generate.ts` + tests, `mcp-server/src/{tools,prompts,bootstrap,resources}.ts`, `mcp-server/src/docs/templates/**`, `mcp-server/src/local/**`, `cli/src/commands/project.ts`, `cli/src/help.ts` + tests
|
|
130
|
+
- Blocked by: 1.2, 1.3, 1.5, 1.6
|
|
131
|
+
- Acceptance: AC10; generated app compiles in a temp dir
|
|
132
|
+
- Docs: `docs/how-to/create-a-terreno-app.md`, `docs/reference/mcp-server.md`, `docs/reference/cli.md`
|
|
133
|
+
|
|
134
|
+
## Phase 4: Contract
|
|
135
|
+
|
|
136
|
+
- [x] **Task 4.1**: Delete `rtk/` and its wiring
|
|
137
|
+
- Delivers: `rtk/` removed; root workspaces, `rtk:*` scripts, catalog entries (`@reduxjs/toolkit`, `@rtk-query/codegen-openapi`, `redux-persist`, `react-redux`, `axios-retry`, `async-mutex`, `jwt-decode` if unused); metro aliases; `example-backend/Dockerfile`; `knip.jsonc`; `biome.jsonc`; `codecov.yml`; CircleCI (`config.yml`, `continue-config.yml`); GitHub workflows (`rtk-ci.yml` deleted; `publish-on-tag`, `cd`, `docs-deploy`, `eas-pr`, `frontend-example-deploy`, `admin-spa-ci`, `dependabot`, issue templates, `architectural-pr-review.ts`); `scripts/**` maps and their tests; `website/scripts` + docusaurus redirect; `mcp-server/scripts/sync-package-guidelines.ts`. Apps declare native deps rtk used to pull in (`expo-secure-store`, `@better-auth/expo`, `better-auth`, `socket.io-client`, `expo-network` if still used); Expo fingerprint change recorded.
|
|
138
|
+
- Files: listed above, `bun.lock`
|
|
139
|
+
- Blocked by: 3.1–3.8
|
|
140
|
+
- Acceptance: AC1, AC2; `bun install && bun run compile`; `bun run check:knip`; `bun run analyze:full`
|
|
141
|
+
- Docs: none beyond 4.2
|
|
142
|
+
|
|
143
|
+
- [x] **Task 4.2**: Docs, rules, skills, upgrade notes
|
|
144
|
+
- Delivers: `docs/how-to/migrate-rtk-to-syncdb.md` rewritten as the 58 upgrade path (every removed export → replacement table); `docs/reference/legacy/rtk.md` and `docs/explanation/announcements/rtk-deprecation.md` updated to "removed in 58"; `docs/explanation/local-first-data.md`, `docs/reference/environment-variables.md`, remaining single mentions; `mcp-server/src/docs/upgrades/58.0.0.md`; `changelog/unreleased/remove-rtk.md`; `.rulesync/rules/rtk/00-rtk.md` deleted, root / syncdb / example-frontend / mcp-server rules updated; plugin skills (`terreno-data-fetching`, `building-terreno-apps`, `generate-sdk`, `upgrading-terreno`, `building-admin-interfaces`); `README.md`, `AGENTS.md`, `CLAUDE.md`, `CLAUDE-consumer.md`, `CONTRIBUTING.md`; regenerate rulesync outputs and `bun run skills:sync`.
|
|
145
|
+
- Files: listed above
|
|
146
|
+
- Blocked by: 4.1
|
|
147
|
+
- Acceptance: AC12
|
|
148
|
+
- Skills: `update-docs`, `update-agent-docs`
|
|
149
|
+
|
|
150
|
+
- [x] **Task 4.3**: Full verification and UI evidence
|
|
151
|
+
- Delivers: `bun run prepush`; full `frontend:e2e`; admin-spa e2e; `maestro:test`; screenshots / videos for AC11 under `/opt/cursor/artifacts/`.
|
|
152
|
+
- Files: none (evidence only)
|
|
153
|
+
- Blocked by: 4.2
|
|
154
|
+
- Acceptance: AC3, AC4, AC11 with commands and artifact paths recorded in the PR Verification table
|
|
155
|
+
- Skills: `verify-ui-changes`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localTools.d.ts","sourceRoot":"","sources":["../../src/local/localTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,8BAA8B,CAAC;AAGvD,OAAO,EAAkB,UAAU,EAAC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"localTools.d.ts","sourceRoot":"","sources":["../../src/local/localTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,8BAA8B,CAAC;AAGvD,OAAO,EAAkB,UAAU,EAAC,MAAM,oBAAoB,CAAC;AA4B/D,eAAO,MAAM,aAAa,EAAE,IAAI,EAuN/B,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,gBAAe,OAAO,UAAuB,KAC5C,CAAC,CACF,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAAA;CAAC,CAAC,CA8I3D,CAAC;AAEF,eAAO,MAAM,mBAAmB,SAlJxB,MAAM,QACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAAA;CAAC,CAgJI,CAAC"}
|
package/dist/local/localTools.js
CHANGED
|
@@ -3,9 +3,9 @@ import { isBrowserAction, useBrowser } from "./tools/browser.js";
|
|
|
3
3
|
import { databaseQuery } from "./tools/databaseQuery.js";
|
|
4
4
|
import { databaseSchema } from "./tools/databaseSchema.js";
|
|
5
5
|
import { lastError, readLogs } from "./tools/readLogs.js";
|
|
6
|
-
import { evaluate,
|
|
6
|
+
import { evaluate, navigate } from "./tools/runtime.js";
|
|
7
7
|
import { getSyncDbState, syncDbAction, syncDbSnapshot } from "./tools/syncDb.js";
|
|
8
|
-
const
|
|
8
|
+
const SYNCDB_STATE_INPUT_SCHEMA = {
|
|
9
9
|
additionalProperties: false,
|
|
10
10
|
properties: {
|
|
11
11
|
collection: { description: "SyncDB: optional collection filter", type: "string" },
|
|
@@ -22,18 +22,9 @@ const CLIENT_STATE_INPUT_SCHEMA = {
|
|
|
22
22
|
description: "SyncDB: client/store name; defaults to the first registered client",
|
|
23
23
|
type: "string",
|
|
24
24
|
},
|
|
25
|
-
query: {
|
|
26
|
-
description: "RTK: when slice is rtk/terreno-rtk (or omitted), filter cache rows whose endpoint name or serialized args contain this substring (case-insensitive).",
|
|
27
|
-
type: "string",
|
|
28
|
-
},
|
|
29
|
-
slice: {
|
|
30
|
-
description: "RTK: `auth`, `betterAuth`, `rtk`/`terreno-rtk`, or any top-level Redux state key. Omit for auth + RTK Query cache summary.",
|
|
31
|
-
type: "string",
|
|
32
|
-
},
|
|
33
25
|
},
|
|
34
26
|
type: "object",
|
|
35
27
|
};
|
|
36
|
-
const GET_CLIENT_STATE_DESCRIPTION = "Inspect the running app's client data layer. Detects the RTK Query Redux store (`registerTerrenoDevStore` / `globalThis.__TERRENO_STORE__`) and the SyncDB client (`createSyncDb({debug: true})` / `globalThis.__TERRENO_SYNCDB__`), in-process or via CDP. Returns JSON with `layer`: `rtk`, `syncdb`, `syncdb+rtk` (both present; both payloads returned), or `none`. `rtk` holds auth plus an RTK Query cache summary (queries/mutations with endpoint, status, args), narrowed by `slice`/`query`. `syncdb` holds the SyncDB inspect output (status, entities, outbox, conflicts, cursors, streams, debug events), narrowed by `name`/`collection`/`entityId`/`limit`/`includeDebugEvents`. `none` returns a setup `hint`, per-layer `reasons`, and the CDP `connection` status. Sensitive fields are redacted. Use `get_syncdb_state` for SyncDB-only reads.";
|
|
37
28
|
export const localMcpTools = [
|
|
38
29
|
{
|
|
39
30
|
description: "Read the consumer app's package.json workspaces and key dependency versions (@terreno/*, Expo, React Native, Mongoose). Looks in `backend/` or `example-backend/`, and `frontend/` or `example-frontend/`. Call at the start of each chat and write version-specific code (Boost-style).",
|
|
@@ -103,38 +94,9 @@ export const localMcpTools = [
|
|
|
103
94
|
},
|
|
104
95
|
name: "last_error",
|
|
105
96
|
},
|
|
106
|
-
{
|
|
107
|
-
description: GET_CLIENT_STATE_DESCRIPTION,
|
|
108
|
-
inputSchema: CLIENT_STATE_INPUT_SCHEMA,
|
|
109
|
-
name: "get_client_state",
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
description: "Deprecated: use `get_client_state`. Alias kept for one release; it runs the same handler and returns the same `{layer, rtk?, syncdb?}` response.",
|
|
113
|
-
inputSchema: CLIENT_STATE_INPUT_SCHEMA,
|
|
114
|
-
name: "get_rtk_state",
|
|
115
|
-
},
|
|
116
97
|
{
|
|
117
98
|
description: "Inspect a live SyncDB client registered by createSyncDb({debug: true}): status, entities (including tombstones/pending metadata), decoded outbox, conflicts, cursors, streams, repairs, values, and debugger events. Sensitive fields are redacted.",
|
|
118
|
-
inputSchema:
|
|
119
|
-
additionalProperties: false,
|
|
120
|
-
properties: {
|
|
121
|
-
collection: { description: "Optional collection filter", type: "string" },
|
|
122
|
-
entityId: { description: "Optional entity id filter", type: "string" },
|
|
123
|
-
includeDebugEvents: {
|
|
124
|
-
description: "Set false to return debug stats without event bodies",
|
|
125
|
-
type: "boolean",
|
|
126
|
-
},
|
|
127
|
-
limit: {
|
|
128
|
-
description: "Entity limit per collection (default 500, max 2000)",
|
|
129
|
-
type: "number",
|
|
130
|
-
},
|
|
131
|
-
name: {
|
|
132
|
-
description: "Client/store name; defaults to the first registered client",
|
|
133
|
-
type: "string",
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
type: "object",
|
|
137
|
-
},
|
|
99
|
+
inputSchema: SYNCDB_STATE_INPUT_SCHEMA,
|
|
138
100
|
name: "get_syncdb_state",
|
|
139
101
|
},
|
|
140
102
|
{
|
|
@@ -313,19 +275,6 @@ export const createLocalToolCallHandler = (browserRunner = useBrowser) => {
|
|
|
313
275
|
});
|
|
314
276
|
return { content: [{ text, type: "text" }] };
|
|
315
277
|
}
|
|
316
|
-
case "get_client_state":
|
|
317
|
-
case "get_rtk_state": {
|
|
318
|
-
const text = await getClientState({
|
|
319
|
-
collection: typeof args.collection === "string" ? args.collection : undefined,
|
|
320
|
-
entityId: typeof args.entityId === "string" ? args.entityId : undefined,
|
|
321
|
-
includeDebugEvents: typeof args.includeDebugEvents === "boolean" ? args.includeDebugEvents : undefined,
|
|
322
|
-
limit: typeof args.limit === "number" ? args.limit : undefined,
|
|
323
|
-
name: typeof args.name === "string" ? args.name : undefined,
|
|
324
|
-
query: typeof args.query === "string" ? args.query : undefined,
|
|
325
|
-
slice: typeof args.slice === "string" ? args.slice : undefined,
|
|
326
|
-
});
|
|
327
|
-
return { content: [{ text, type: "text" }] };
|
|
328
|
-
}
|
|
329
278
|
case "get_syncdb_state": {
|
|
330
279
|
const text = await getSyncDbState({
|
|
331
280
|
collection: typeof args.collection === "string" ? args.collection : undefined,
|