@vertesia/appgen-docs 1.5.0-dev.20260910.051115Z → 1.6.0-dev.20260912.110338Z
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.
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Current-project Interactions Recipe
|
|
2
|
+
|
|
3
|
+
This recipe is generated with the installed `@vertesia/client` and `@vertesia/common` versions. Use it instead
|
|
4
|
+
of searching dependency source for the browser client signature.
|
|
5
|
+
|
|
6
|
+
## List interactions from React
|
|
7
|
+
|
|
8
|
+
```tsx
|
|
9
|
+
import type { InteractionRef } from '@vertesia/common';
|
|
10
|
+
import { useFetch } from '@vertesia/ui/core';
|
|
11
|
+
import { useUserSession } from '@vertesia/ui/session';
|
|
12
|
+
|
|
13
|
+
export function InteractionCatalog() {
|
|
14
|
+
const { client } = useUserSession();
|
|
15
|
+
const { data = [] } = useFetch<InteractionRef[]>(() => client.interactions.list(), {
|
|
16
|
+
deps: [client],
|
|
17
|
+
defaultValue: [],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return <ul>{data.map((interaction) => <li key={interaction.id}>{interaction.name}</li>)}</ul>;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Stable signatures
|
|
25
|
+
|
|
26
|
+
- `client.interactions.list(payload?: InteractionSearchPayload): Promise<InteractionRef[]>`.
|
|
27
|
+
- Empty input is valid. Use `client.interactions.list()` unless the task requires a server-side filter.
|
|
28
|
+
- The useful `InteractionRef` fields are `id`, `name`, `endpoint`, `description?`, `status`, `version`,
|
|
29
|
+
`tags`, and `updated_at`.
|
|
30
|
+
- `InteractionRef` deliberately has no `type` field. When a current-project catalog must display type, call
|
|
31
|
+
`client.interactions.catalog.listStoredInteractions()`, which returns `Promise<CatalogInteractionRef[]>`; do not
|
|
32
|
+
search generated declarations for `InteractionRef.type` or infer it from another field.
|
|
33
|
+
- `listStoredInteractions()` sends `GET /api/v1/interactions/catalog/stored` (plus optional `status` or `tag`
|
|
34
|
+
query parameters). Its JSON response is the bare `CatalogInteractionRef[]` array, never an `{ items: [...] }`
|
|
35
|
+
wrapper. A focused Playwright mock can route `**/api/v1/interactions/catalog/stored**` and fulfill that bare array.
|
|
36
|
+
- The useful `CatalogInteractionRef` fields are `type` (`'stored'` for this endpoint), `id`, `name`, `title`,
|
|
37
|
+
`description?`, `version?`, and `tags`. Use `client.interactions.catalog.list()` only when the task explicitly
|
|
38
|
+
asks for the combined system, app, and stored catalog rather than the current project's stored interactions.
|
|
39
|
+
- This recipe fully specifies the method, return type, endpoint, and response shape. Do not probe the live API, inspect
|
|
40
|
+
`node_modules`, or call `app_docs_grep`/`app_docs_read` to reconfirm them. Treat a concrete workspace typecheck or
|
|
41
|
+
Playwright failure as the only reason to inspect one exact symbol afterward.
|
|
42
|
+
- Keep SDK methods attached to their topic: call `client.interactions.list()`; do not destructure `list`.
|
|
43
|
+
- The session client is already scoped to the signed-in user's current project. Do not construct another client in
|
|
44
|
+
browser code and do not hardcode a project id.
|
|
45
|
+
- For schemas, use `client.interactions.export({})`; for the normal catalog, use `list()`.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# UI Components Recipe
|
|
2
|
+
|
|
3
|
+
This recipe is generated with the installed `@vertesia/ui` version. Use it for common app screens instead of
|
|
4
|
+
searching dependency source. For an API not covered here, search `appgen/ui-interfaces.d.ts` once by exact symbol.
|
|
5
|
+
|
|
6
|
+
For a current-project interaction catalog built with the table, button, and fetch APIs below, this recipe is complete.
|
|
7
|
+
After reading it, do not search generated declarations or dependency source for `Table`, `TBody`, `useFetch`, or
|
|
8
|
+
the interaction catalog merely to reconfirm these signatures. Implement the screen and let the first workspace typecheck
|
|
9
|
+
identify any real version drift; only then search once for the exact symbol named by that diagnostic.
|
|
10
|
+
|
|
11
|
+
## Imports
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import {
|
|
15
|
+
Button,
|
|
16
|
+
Table,
|
|
17
|
+
TableHeaderCell,
|
|
18
|
+
TBody,
|
|
19
|
+
THead,
|
|
20
|
+
TR,
|
|
21
|
+
useFetch,
|
|
22
|
+
} from '@vertesia/ui/core';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
These are runtime React values, not types. Import `Table`, `TBody`, `THead`, `TR`, `TableHeaderCell`, `Button`,
|
|
26
|
+
and `useFetch` with a normal `import`; using `import type` makes JSX fail with TS1361.
|
|
27
|
+
|
|
28
|
+
## Loading table with refresh
|
|
29
|
+
|
|
30
|
+
`TBody.columns` is required. It is the number of rendered columns and drives the loading skeleton.
|
|
31
|
+
Use `TableHeaderCell` instead of raw `<th>` so column scope is accessible by default.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
const { data = [], error, isLoading, refetch } = useFetch(loadRows, { deps: [projectId], defaultValue: [] });
|
|
35
|
+
|
|
36
|
+
<Button type="button" onClick={() => void refetch()} isLoading={isLoading}>
|
|
37
|
+
Refresh
|
|
38
|
+
</Button>
|
|
39
|
+
|
|
40
|
+
{error ? <p role="alert">{error.message}</p> : null}
|
|
41
|
+
<Table>
|
|
42
|
+
<THead>
|
|
43
|
+
<TR>
|
|
44
|
+
<TableHeaderCell>Name</TableHeaderCell>
|
|
45
|
+
<TableHeaderCell>Status</TableHeaderCell>
|
|
46
|
+
</TR>
|
|
47
|
+
</THead>
|
|
48
|
+
<TBody columns={2} isLoading={isLoading}>
|
|
49
|
+
{data.map((row) => (
|
|
50
|
+
<TR key={row.id}>
|
|
51
|
+
<td>{row.name}</td>
|
|
52
|
+
<td>{row.status}</td>
|
|
53
|
+
</TR>
|
|
54
|
+
))}
|
|
55
|
+
</TBody>
|
|
56
|
+
</Table>
|
|
57
|
+
{!isLoading && !error && data.length === 0 ? <p>No results found.</p> : null}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Stable signatures
|
|
61
|
+
|
|
62
|
+
- `useFetch<T>(fetcher, { deps, defaultValue, onSuccess, onError })` returns
|
|
63
|
+
`{ data, isLoading, error, setData, refetch }`.
|
|
64
|
+
- `TBody` accepts `{ columns: number; isLoading?: boolean; rows?: number; children: ReactNode }`.
|
|
65
|
+
- `Button` accepts normal button props plus `isLoading`, `isDisabled`, `variant`, and `size`.
|
|
66
|
+
- Icon-only buttons need `aria-label`. Text buttons should keep their visible text in the accessible name.
|
|
67
|
+
- Use a native `<section aria-label="…">` for a labeled table/overflow region. Do not put `role="region"` on a
|
|
68
|
+
`<div>`; Biome's `lint/a11y/useSemanticElements` requires the semantic element.
|
|
69
|
+
- Prefer semantic theme classes and plain HTML for layout. Do not guess private `@vertesia/ui` paths.
|
|
70
|
+
|
|
71
|
+
## Generated app tests
|
|
72
|
+
|
|
73
|
+
- The standard generated app runs Vitest in a Node environment and intentionally does not install jsdom,
|
|
74
|
+
happy-dom, or Testing Library. Do not search dependency trees or add a DOM-test dependency for a UI-only change.
|
|
75
|
+
- Put loading/error/empty/populated/refresh decisions in a separate production `*.state.ts` or `*.model.ts` module
|
|
76
|
+
imported and used by the component. Cover that state matrix by importing the pure module directly from the focused unit
|
|
77
|
+
test. Do not export the helper only from the component's TSX module: importing that file also loads the real
|
|
78
|
+
`@vertesia/ui` runtime, which the standard Node-only Vitest environment cannot execute. Do not copy the helper into
|
|
79
|
+
the test or walk rendered React element internals; the tested module must remain on the production import path.
|
|
80
|
+
- Source Playwright specs import `type { Page }` from `@playwright/test` and `{ expect, test }` from
|
|
81
|
+
`./vertesia`. Type shared helpers as `page: Page`; never hand-write a structural Page or Route type because
|
|
82
|
+
Playwright's overloaded callbacks will reject narrower substitutes. Use `page.route` to mock only the real API
|
|
83
|
+
path involved in the primary flow (interaction listing uses a path containing `/interactions`), then exercise the
|
|
84
|
+
page through accessible roles. Use the declared `test:e2e` script and its `PLAYWRIGHT_BASE_URL`; do not invent a
|
|
85
|
+
second browser harness.
|
|
86
|
+
- Scope repeated text to its semantic container and request an exact accessible name. For example, use
|
|
87
|
+
`table.getByRole('cell', { name: interactionName, exact: true })` when the same name can also occur in tags or
|
|
88
|
+
descriptions; an unscoped text or name locator can match several elements and waste a browser retry.
|
|
89
|
+
- For a responsive table, prove document-level overflow is absent and intentional overflow stays on one labeled table
|
|
90
|
+
region. Assert positive horizontal overflow only at the narrow viewport—a desktop table may fit—and scroll that region
|
|
91
|
+
before using `toBeInViewport()` on the final required column. DOM presence or `toBeVisible()` alone does not prove an
|
|
92
|
+
off-screen mobile column is reachable.
|