@beignet/react-query 0.0.55 → 0.0.56

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @beignet/react-query
2
2
 
3
+ ## 0.0.56
4
+
5
+ ### Patch Changes
6
+
7
+ - e00c302: Use direct React Query options and declarative invalidation in generated components, with guidance for extracting shared client behavior.
8
+
3
9
  ## 0.0.55
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -71,53 +71,57 @@ export function Providers({ children }: { children: ReactNode }) {
71
71
  }
72
72
  ```
73
73
 
74
- ### 3. Add feature client helpers
74
+ ### 3. Use contracts in components
75
75
 
76
- Keep root `client/` for shared adapter setup, then put feature-specific query
77
- options, mutation options, invalidation helpers, and hooks under
78
- `features/<feature>/client/`:
76
+ Import the app's shared `rq` adapter and browser-safe feature contracts. Pass
77
+ options directly to TanStack Query; `invalidates` selects the queries to refresh
78
+ after a successful mutation:
79
79
 
80
- ```ts
81
- // features/todos/client/queries.ts
82
- import type { QueryClient } from "@tanstack/react-query";
80
+ ```tsx
81
+ "use client";
82
+
83
+ import { useMutation, useQuery } from "@tanstack/react-query";
83
84
  import { rq } from "@/client";
84
85
  import { createTodo, listTodos } from "@/features/todos/contracts";
85
86
 
86
- export function listTodosQueryOptions() {
87
- return rq(listTodos).queryOptions({ query: {} });
88
- }
87
+ export function TodoList() {
88
+ const todos = useQuery(rq(listTodos).queryOptions());
89
+ const create = useMutation(
90
+ rq(createTodo).mutationOptions({
91
+ invalidates: () => [rq(listTodos).contractFilter()],
92
+ }),
93
+ );
89
94
 
90
- export function createTodoMutationOptions() {
91
- return rq(createTodo).mutationOptions();
92
- }
95
+ if (todos.isPending) return <p>Loading todos…</p>;
96
+ if (todos.isError) return <p role="alert">{todos.error.message}</p>;
93
97
 
94
- export function invalidateTodos(queryClient: QueryClient) {
95
- return rq(listTodos).invalidate(queryClient);
98
+ return (
99
+ <div>
100
+ <button
101
+ type="button"
102
+ disabled={create.isPending}
103
+ onClick={() => create.mutate({ body: { title: "New todo" } })}
104
+ >
105
+ Add todo
106
+ </button>
107
+ {create.isError && <p role="alert">{create.error.message}</p>}
108
+ <ul>
109
+ {todos.data.items.map((todo) => <li key={todo.id}>{todo.title}</li>)}
110
+ </ul>
111
+ </div>
112
+ );
96
113
  }
97
114
  ```
98
115
 
99
- Components can import those helpers and keep UI state separate from cache-key
100
- construction:
101
-
102
- ```tsx
103
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
104
- import {
105
- createTodoMutationOptions,
106
- invalidateTodos,
107
- listTodosQueryOptions,
108
- } from "@/features/todos/client/queries";
109
-
110
- function TodoList() {
111
- const queryClient = useQueryClient();
112
- const todosQuery = useQuery(listTodosQueryOptions());
113
- const createTodoMutation = useMutation({
114
- ...createTodoMutationOptions(),
115
- onSuccess: () => invalidateTodos(queryClient),
116
- });
116
+ Pass lifecycle callbacks inside `mutationOptions({ ... })`. Beignet awaits
117
+ `onSuccess`, then the selected invalidations before the mutation settles.
118
+ Declarative invalidation requires TanStack React Query 5.102.0 or newer in v5.
119
+ See [Declarative mutation invalidation](#declarative-mutation-invalidation).
117
120
 
118
- return <div>{/* ... */}</div>;
119
- }
120
- ```
121
+ Keep adapter setup in root `client/`. Extract
122
+ [feature client helpers](https://beignetjs.com/react-query#feature-client-helpers)
123
+ for shared query defaults, pagination, optimistic updates, or cache filters used
124
+ by mutations and broadcasts.
121
125
 
122
126
  ## Usage
123
127
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beignet/react-query",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "type": "module",
5
5
  "description": "TanStack Query integration for Beignet",
6
6
  "main": "./dist/index.js",
@@ -34,39 +34,34 @@ export function makeQueryClient() {
34
34
  Reuse the app's existing helper names and client options. Do not introduce a
35
35
  parallel Beignet client unless the app already has a multi-client convention.
36
36
 
37
- ## Feature Client Helpers
37
+ ## Direct Options And Shared Behavior
38
38
 
39
- Feature-specific query options, mutations, and hooks may live under the
40
- feature. Prefer the canonical directory form for new apps:
39
+ Import contracts, the root `rq` adapter, and TanStack hooks in the component.
40
+ Inside its body, pass options directly to the hooks:
41
41
 
42
- ```txt
43
- features/todos/client/queries.ts
44
- ```
45
-
46
- Existing apps may use:
47
-
48
- ```txt
49
- features/todos/client.ts
42
+ ```ts
43
+ const todos = useQuery(rq(listTodos).queryOptions());
44
+ const create = useMutation(
45
+ rq(createTodo).mutationOptions({
46
+ invalidates: () => [rq(listTodos).contractFilter()],
47
+ }),
48
+ );
50
49
  ```
51
50
 
52
- Follow the existing style unless intentionally migrating. Do not mix both
53
- within one feature.
51
+ Extract feature client modules only when they own reusable behavior: shared
52
+ query defaults, pagination, optimistic updates and rollback, or filters used by
53
+ mutations and broadcasts. Prefer `features/<feature>/client/queries.ts` for
54
+ extracted options. Existing apps may use `features/<feature>/client.ts`; follow
55
+ their style without creating both forms. Keep component callbacks inside
56
+ `mutationOptions({ ... })` so they compose with declarative invalidation.
54
57
 
55
58
  ```ts
56
- import type { QueryClient } from "@tanstack/react-query";
59
+ // features/todos/client/queries.ts: a shared freshness default
57
60
  import { rq } from "@/client";
58
- import { createTodo, listTodos } from "@/features/todos/contracts";
61
+ import { listTodos } from "@/features/todos/contracts";
59
62
 
60
63
  export function listTodosQueryOptions() {
61
- return rq(listTodos).queryOptions({ query: { limit: 20 } });
62
- }
63
-
64
- export function createTodoMutationOptions() {
65
- return rq(createTodo).mutationOptions();
66
- }
67
-
68
- export function invalidateTodos(queryClient: QueryClient) {
69
- return rq(listTodos).invalidate(queryClient);
64
+ return rq(listTodos).queryOptions({ staleTime: 30_000 });
70
65
  }
71
66
  ```
72
67
 
@@ -160,9 +155,9 @@ If `beignet lint` says a client component reaches a use-case module:
160
155
 
161
156
  1. Move shared DTOs and validation to `features/<feature>/schemas.ts`.
162
157
  2. Remove imports from use cases, routes, infra, providers, or `server/`.
163
- 3. Add a feature client helper that imports only contracts and root client
164
- helpers.
165
- 4. Update components to call the helper through TanStack Query.
158
+ 3. Import browser-safe contracts and the root `rq` adapter in the component.
159
+ 4. Pass `rq(contract).queryOptions()` or `.mutationOptions()` to TanStack Query;
160
+ extract a feature client helper only for shared behavior.
166
161
 
167
162
  Then run:
168
163