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
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,7 +25,7 @@ Use `pnpm logs -- --service api --lines 120` to inspect API logs. Use `pnpm seed
25
25
26
26
See [docs/architecture.md](./docs/architecture.md) for the full picture.
27
27
28
-
Each business domain follows a strict layered model. The React UI uses TanStack Query for server-state fetching, mutation, caching, and invalidation. HTTP route contracts generate the OpenAPI spec and typed frontend client; see [docs/openapi.md](./docs/openapi.md).
28
+
Each business domain follows a strict layered model. The React UI uses TanStack Query for server-state fetching, mutation, caching, and invalidation. HTTP route contracts generate the OpenAPI spec, typed frontend client, and TanStack Query helper factories; see [docs/openapi.md](./docs/openapi.md).
|**runtime/**| Server routes, route contracts, background jobs, event handlers | types, config, repo, service |
25
-
|**ui/**| React components, hooks, pages; uses generated API client for HTTP | types, config (client-safe only), generated client |
26
+
|**ui/**| React components, hooks, pages; uses generated API client and TanStack Query helpers for HTTP | types, config (client-safe only), generated client |
26
27
27
-
Route contracts live in `runtime/contract.ts` because they describe the HTTP boundary. They depend on lower-layer Zod schemas and provider contract types, then feed generated artifacts under `src/generated/`. UI code may import the generated client and exported client-safe types, but it must not import runtime route modules directly.
28
+
Route contracts live in `runtime/contract.ts` because they describe the HTTP boundary. They depend on lower-layer Zod schemas and provider contract types, then feed generated artifacts under `src/generated/`. UI code may import the generated client, generated TanStack Query option factories, generated query keys, and exported client-safe types, but it must not import runtime route modules directly.
28
29
29
30
### Cross-Cutting Concerns (Providers)
30
31
@@ -47,7 +48,7 @@ These rules are enforced by the custom linter at `lints/check-deps.ts`:
47
48
2.**No cross-domain imports at lower layers.**`domainA/repo` cannot import `domainB/repo`. Cross-domain communication happens at the `service` layer or above.
48
49
3.**No direct cross-cutting imports.** Use `src/providers/`, not raw `pino` or `@opentelemetry/*` imports in domain code.
49
50
4.**UI only imports types and client-safe config.** No server-side code in the UI layer.
50
-
5.**Generated API client is the UI HTTP boundary.** Browser code should call`src/generated/api-client.generated.ts`, not hand-written `fetch` wrappers for app routes.
51
+
5.**Generated API client is the UI HTTP boundary.** Browser code should use`src/generated/api-client.generated.ts`, preferably through generated TanStack Query helpers, not hand-written `fetch` wrappers for app routes.
51
52
6.**Co-located tests are required.** Source modules must have adjacent unit or integration tests unless they are approved entrypoints, generated files, or barrel files.
52
53
7.**Structured logging only.** Application code must not use `console.*`; use providers so stack logs stay queryable.
Copy file name to clipboardExpand all lines: docs/implementation.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,7 +40,7 @@ When a feature adds or changes HTTP behavior:
40
40
2. Add or update the domain route contract in `runtime/contract.ts`, including `method`, `operationId`, `path`, `responses`, and `client` metadata for browser-callable routes.
41
41
3. Register the contract from `src/api-contracts.ts`.
42
42
4. Run `pnpm api:generate` to refresh `src/generated/openapi.generated.json` and `src/generated/api-client.generated.ts`.
43
-
5. Use the generated client from UI code instead of hand-written `fetch` calls.
43
+
5. Use the generated TanStack Query helpers from UI code instead of hand-written `fetch`, `queryKey`, `queryFn`, or `mutationFn` wrappers.
44
44
45
45
Use [openapi.md](./openapi.md) for the exact contract shape, client metadata fields, and verification checklist.
Copy file name to clipboardExpand all lines: docs/openapi.md
+54-4Lines changed: 54 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
Last verified: 2026-05-05
4
4
5
-
The HTTP contract is generated from TypeScript route contract metadata and Zod schemas. Domain runtime layers own their route contracts because routes are the HTTP boundary, and the generated frontend client imports only client-safe domain types.
5
+
The HTTP contract is generated from TypeScript route contract metadata and Zod schemas. Domain runtime layers own their route contracts because routes are the HTTP boundary, and the generated frontend client imports only client-safe domain types. The generated client also exposes TanStack Query option factories so UI code can share query keys, query functions, mutation keys, and mutation functions without hand-written wrappers.
6
6
7
7
## Files
8
8
@@ -12,7 +12,7 @@ The HTTP contract is generated from TypeScript route contract metadata and Zod s
| Generated frontend client and TanStack Query helpers |`src/generated/api-client.generated.ts`|
16
16
17
17
## Commands
18
18
@@ -29,7 +29,7 @@ The HTTP contract is generated from TypeScript route contract metadata and Zod s
29
29
2. Add or update the route contract in the domain `runtime/contract.ts`.
30
30
3. Implement the Fastify route in the domain `runtime/routes.ts`.
31
31
4. Run `pnpm api:generate`.
32
-
5. Use `src/generated/api-client.generated.ts`from UI code instead of hand-written `fetch` calls.
32
+
5. Use `apiQueries`, `apiMutations`, and `apiQueryKeys` from `src/generated/api-client.generated.ts`in UI code instead of hand-written `fetch`, `queryKey`, `queryFn`, or `mutationFn` wrappers.
33
33
34
34
## Contract Shape
35
35
@@ -131,6 +131,56 @@ client: {
131
131
132
132
For a `DELETE` route that returns `204`, omit `responseParser` and use `responseType: "void"`.
133
133
134
+
## Generated TanStack Query Helpers
135
+
136
+
The generator emits three TanStack-oriented surfaces:
137
+
138
+
| Export | Purpose |
139
+
|--------|---------|
140
+
|`apiQueryKeys`| Stable query key factories for GET routes. Use these for invalidation and cache reads. |
141
+
|`apiQueries`|`queryOptions(...)` factories for GET routes. Pass these directly to `useQuery`, `useSuspenseQuery`, `prefetchQuery`, or `useQueries`. |
142
+
|`apiMutations`|`mutationOptions(...)` factories for non-GET routes. Pass or spread these into `useMutation`. |
0 commit comments