ghcopilot-hub 1.0.0

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.
Files changed (109) hide show
  1. package/README.md +176 -0
  2. package/hub/agents/README.md +243 -0
  3. package/hub/agents/archiver.agent.md +231 -0
  4. package/hub/agents/explore.agent.md +49 -0
  5. package/hub/agents/implementador.agent.md +176 -0
  6. package/hub/agents/librarian.agent.md +34 -0
  7. package/hub/agents/momus.agent.md +130 -0
  8. package/hub/agents/oracle.agent.md +52 -0
  9. package/hub/agents/plan-guardian.agent.md +109 -0
  10. package/hub/agents/planificador.agent.md +295 -0
  11. package/hub/agents/test-sentinel.agent.md +106 -0
  12. package/hub/base/.github/copilot-instructions.md +10 -0
  13. package/hub/base/.github/instructions/ghcopilot-hub.instructions.md +6 -0
  14. package/hub/base/.github/prompts/ghcopilot-hub-maintenance.prompt.md +8 -0
  15. package/hub/base/.vscode/settings.json +1 -0
  16. package/hub/packs/base-web.json +4 -0
  17. package/hub/packs/nextjs-ssr.json +4 -0
  18. package/hub/packs/node-api.json +4 -0
  19. package/hub/packs/spa-tanstack.json +4 -0
  20. package/hub/skills/architecture-testing/SKILL.md +108 -0
  21. package/hub/skills/architecture-testing/references/archunitts.md +46 -0
  22. package/hub/skills/ghcopilot-hub-consumer/SKILL.md +115 -0
  23. package/hub/skills/ghcopilot-hub-consumer/references/workflow.md +39 -0
  24. package/hub/skills/mermaid-expert/SKILL.md +152 -0
  25. package/hub/skills/mermaid-expert/assets/examples/c4_model.md +121 -0
  26. package/hub/skills/mermaid-expert/assets/examples/flowchart.md +123 -0
  27. package/hub/skills/mermaid-expert/assets/examples/img/base_minimal.png +0 -0
  28. package/hub/skills/mermaid-expert/assets/examples/img/corporate.png +0 -0
  29. package/hub/skills/mermaid-expert/assets/examples/img/dark.png +0 -0
  30. package/hub/skills/mermaid-expert/assets/examples/img/dark_neo.png +0 -0
  31. package/hub/skills/mermaid-expert/assets/examples/img/default_neo.png +0 -0
  32. package/hub/skills/mermaid-expert/assets/examples/img/forest_corp.png +0 -0
  33. package/hub/skills/mermaid-expert/assets/examples/img/handdrawn.png +0 -0
  34. package/hub/skills/mermaid-expert/assets/examples/img/neo.png +0 -0
  35. package/hub/skills/mermaid-expert/assets/examples/img/neutral_sketch.png +0 -0
  36. package/hub/skills/mermaid-expert/assets/examples/img/retro.png +0 -0
  37. package/hub/skills/mermaid-expert/assets/examples/sequence.md +116 -0
  38. package/hub/skills/mermaid-expert/assets/examples/styles_and_looks.md +102 -0
  39. package/hub/skills/mermaid-expert/assets/examples/technical.md +130 -0
  40. package/hub/skills/mermaid-expert/assets/examples.md +57 -0
  41. package/hub/skills/mermaid-expert/references/cheatsheet.md +88 -0
  42. package/hub/skills/mermaid-expert/references/validation.md +66 -0
  43. package/hub/skills/react/SKILL.md +235 -0
  44. package/hub/skills/react/references/common-mistakes.md +518 -0
  45. package/hub/skills/react/references/composition-patterns.md +526 -0
  46. package/hub/skills/react/references/effects-patterns.md +396 -0
  47. package/hub/skills/react/references/react-compiler.md +268 -0
  48. package/hub/skills/react-hook-form/SKILL.md +291 -0
  49. package/hub/skills/react-hook-form/references/field-arrays.md +98 -0
  50. package/hub/skills/react-hook-form/references/integration.md +102 -0
  51. package/hub/skills/react-hook-form/references/performance.md +96 -0
  52. package/hub/skills/skill-creator/SKILL.md +152 -0
  53. package/hub/skills/skill-creator/assets/SKILL-TEMPLATE.md +84 -0
  54. package/hub/skills/skill-judge/README.md +261 -0
  55. package/hub/skills/skill-judge/SKILL.md +806 -0
  56. package/hub/skills/tailwind/SKILL.md +200 -0
  57. package/hub/skills/tanstack/SKILL.md +284 -0
  58. package/hub/skills/tanstack/references/loader-adapter-examples.md +79 -0
  59. package/hub/skills/tanstack/references/query-options-examples.md +115 -0
  60. package/hub/skills/tanstack/references/resilience-patterns.md +110 -0
  61. package/hub/skills/tanstack/references/suspense-consumption-examples.md +82 -0
  62. package/hub/skills/tanstack-query/SKILL.md +241 -0
  63. package/hub/skills/tanstack-query/references/advanced-hooks.md +126 -0
  64. package/hub/skills/tanstack-query/references/best-practices.md +241 -0
  65. package/hub/skills/tanstack-query/references/cache-strategies.md +474 -0
  66. package/hub/skills/tanstack-query/references/common-patterns.md +239 -0
  67. package/hub/skills/tanstack-query/references/migration-v5.md +93 -0
  68. package/hub/skills/tanstack-query/references/resilience-and-mutations.md +63 -0
  69. package/hub/skills/tanstack-query/references/testing.md +116 -0
  70. package/hub/skills/tanstack-query/references/top-errors.md +148 -0
  71. package/hub/skills/tanstack-query/references/typescript.md +176 -0
  72. package/hub/skills/tanstack-router/SKILL.md +145 -0
  73. package/hub/skills/tanstack-router/references/code-splitting.md +31 -0
  74. package/hub/skills/tanstack-router/references/errors-and-boundaries.md +44 -0
  75. package/hub/skills/tanstack-router/references/loaders-and-preload.md +51 -0
  76. package/hub/skills/tanstack-router/references/navigation.md +24 -0
  77. package/hub/skills/tanstack-router/references/private-routes.md +169 -0
  78. package/hub/skills/tanstack-router/references/router-context.md +35 -0
  79. package/hub/skills/tanstack-router/references/search-params.md +29 -0
  80. package/hub/skills/tanstack-router/references/typescript.md +24 -0
  81. package/hub/skills/testing/SKILL.md +187 -0
  82. package/hub/skills/testing/references/assertions.md +64 -0
  83. package/hub/skills/testing/references/async-testing.md +66 -0
  84. package/hub/skills/testing/references/e2e-strategy.md +69 -0
  85. package/hub/skills/testing/references/layer-matrix.md +67 -0
  86. package/hub/skills/testing/references/performance.md +49 -0
  87. package/hub/skills/testing/references/tooling-map.md +81 -0
  88. package/hub/skills/testing/references/zustand-mocking.md +84 -0
  89. package/hub/skills/typescript/SKILL.md +232 -0
  90. package/hub/skills/typescript/references/perf-additional-concerns.md +248 -0
  91. package/hub/skills/typescript/references/perf-execution-cache-locality.md +178 -0
  92. package/hub/skills/typescript/references/reduce-branching.md +147 -0
  93. package/hub/skills/typescript/references/reduce-looping.md +203 -0
  94. package/hub/skills/typescript/references/style-and-types.md +171 -0
  95. package/hub/skills/typescript/references/type-vs-interface.md +27 -0
  96. package/hub/skills/zod/SKILL.md +219 -0
  97. package/hub/skills/zustand/SKILL.md +273 -0
  98. package/package.json +59 -0
  99. package/tooling/cli/src/bin.js +11 -0
  100. package/tooling/cli/src/cli.js +409 -0
  101. package/tooling/cli/src/lib/catalog-loader.js +191 -0
  102. package/tooling/cli/src/lib/constants.js +39 -0
  103. package/tooling/cli/src/lib/errors.js +8 -0
  104. package/tooling/cli/src/lib/frontmatter.js +41 -0
  105. package/tooling/cli/src/lib/fs-utils.js +77 -0
  106. package/tooling/cli/src/lib/managed-header.js +74 -0
  107. package/tooling/cli/src/lib/manifest.js +105 -0
  108. package/tooling/cli/src/lib/resolver.js +53 -0
  109. package/tooling/cli/src/lib/sync-engine.js +262 -0
@@ -0,0 +1,239 @@
1
+ # Common TanStack Query Patterns
2
+
3
+ **Reusable patterns for real-world applications**
4
+
5
+ > Alignment note: For required route data, follow the tanstack render-as-you-fetch flow
6
+ > (Application `queryOptions` → Loader `ensureQueryData` → Presentation `useSuspenseQuery`).
7
+ > Examples below use `useQuery` for brevity and are intended for non-route or optional data.
8
+
9
+ ---
10
+
11
+ ## Pattern 1: Dependent Queries
12
+
13
+ ```tsx
14
+ function UserPosts({ userId }) {
15
+ const { data: user } = useQuery({
16
+ queryKey: ["users", userId],
17
+ queryFn: () => fetchUser(userId),
18
+ });
19
+
20
+ const { data: posts } = useQuery({
21
+ queryKey: ["users", userId, "posts"],
22
+ queryFn: () => fetchUserPosts(userId),
23
+ enabled: !!user, // Not for useSuspenseQuery
24
+ });
25
+ }
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Pattern 2: Parallel Queries with useQueries
31
+
32
+ ```tsx
33
+ function TodoDetails({ ids }) {
34
+ const results = useQueries({
35
+ queries: ids.map((id) => ({
36
+ queryKey: ["todos", id],
37
+ queryFn: () => fetchTodo(id),
38
+ })),
39
+ });
40
+
41
+ const isLoading = results.some((r) => r.isPending);
42
+ const data = results.map((r) => r.data);
43
+ }
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Pattern 3: Paginated Queries with placeholderData
49
+
50
+ ```tsx
51
+ import { keepPreviousData } from "@tanstack/react-query";
52
+
53
+ function PaginatedTodos() {
54
+ const [page, setPage] = useState(0);
55
+
56
+ const { data } = useQuery({
57
+ queryKey: ["todos", page],
58
+ queryFn: () => fetchTodos(page),
59
+ placeholderData: keepPreviousData,
60
+ });
61
+ }
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Pattern 4: Infinite Scroll
67
+
68
+ ```tsx
69
+ function InfiniteList() {
70
+ const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
71
+ queryKey: ["items"],
72
+ queryFn: ({ pageParam }) => fetchItems(pageParam),
73
+ initialPageParam: 0,
74
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
75
+ });
76
+
77
+ const ref = useRef();
78
+ useEffect(() => {
79
+ const observer = new IntersectionObserver(
80
+ ([entry]) => entry.isIntersecting && hasNextPage && fetchNextPage()
81
+ );
82
+ if (ref.current) observer.observe(ref.current);
83
+ return () => observer.disconnect();
84
+ }, [fetchNextPage, hasNextPage]);
85
+
86
+ return (
87
+ <>
88
+ {data.pages.map((page) => page.data.map((item) => <div>{item}</div>))}
89
+ <div ref={ref}>Loading...</div>
90
+ </>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Pattern 5: Optimistic Updates
98
+
99
+ ```tsx
100
+ function useOptimisticToggle() {
101
+ const queryClient = useQueryClient();
102
+
103
+ return useMutation({
104
+ mutationFn: updateTodo,
105
+ onMutate: async (updated) => {
106
+ await queryClient.cancelQueries({ queryKey: ["todos"] });
107
+ const previous = queryClient.getQueryData(["todos"]);
108
+
109
+ queryClient.setQueryData(["todos"], (old) =>
110
+ old.map((todo) => (todo.id === updated.id ? updated : todo))
111
+ );
112
+
113
+ return { previous };
114
+ },
115
+ onError: (err, vars, context) => {
116
+ queryClient.setQueryData(["todos"], context.previous);
117
+ },
118
+ onSettled: () => {
119
+ queryClient.invalidateQueries({ queryKey: ["todos"] });
120
+ },
121
+ });
122
+ }
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Pattern 6: Prefetching on Hover
128
+
129
+ ```tsx
130
+ function TodoList() {
131
+ const queryClient = useQueryClient();
132
+
133
+ const prefetch = (id) => {
134
+ queryClient.prefetchQuery({
135
+ queryKey: ["todos", id],
136
+ queryFn: () => fetchTodo(id),
137
+ });
138
+ };
139
+
140
+ return (
141
+ <ul>
142
+ {todos.map((todo) => (
143
+ <li onMouseEnter={() => prefetch(todo.id)}>
144
+ <Link to={`/todos/${todo.id}`}>{todo.title}</Link>
145
+ </li>
146
+ ))}
147
+ </ul>
148
+ );
149
+ }
150
+ ```
151
+
152
+ > Use prefetching only for optional navigation, not required route data.
153
+
154
+ ---
155
+
156
+ ## Pattern 7: Search/Debounce
157
+
158
+ ```tsx
159
+ import { useDeferredValue, useState } from "react";
160
+
161
+ function Search() {
162
+ const [search, setSearch] = useState("");
163
+ const deferredSearch = useDeferredValue(search);
164
+
165
+ const { data } = useQuery({
166
+ queryKey: ["search", deferredSearch],
167
+ queryFn: ({ signal }) =>
168
+ fetch(`/api/search?q=${deferredSearch}`, { signal }).then((r) => r.json()),
169
+ enabled: deferredSearch.length >= 2,
170
+ });
171
+ }
172
+ ```
173
+
174
+ ---
175
+
176
+ ## Pattern 8: Polling/Refetch Interval
177
+
178
+ ```tsx
179
+ const { data } = useQuery({
180
+ queryKey: ["stock-price"],
181
+ queryFn: fetchStockPrice,
182
+ refetchInterval: 1000 * 30,
183
+ refetchIntervalInBackground: true,
184
+ });
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Pattern 9: Conditional Fetching
190
+
191
+ ```tsx
192
+ const { data } = useQuery({
193
+ queryKey: ["user", userId],
194
+ queryFn: () => fetchUser(userId),
195
+ enabled: !!userId && isAuthenticated,
196
+ });
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Pattern 10: Initial Data from Cache
202
+
203
+ ```tsx
204
+ const { data: todo } = useQuery({
205
+ queryKey: ["todos", id],
206
+ queryFn: () => fetchTodo(id),
207
+ initialData: () => queryClient.getQueryData(["todos"])?.find((t) => t.id === id),
208
+ });
209
+ ```
210
+
211
+ ---
212
+
213
+ ## Pattern 11: Mutation with Multiple Invalidations
214
+
215
+ ```tsx
216
+ useMutation({
217
+ mutationFn: updateTodo,
218
+ onSuccess: (updated) => {
219
+ queryClient.setQueryData(["todos", updated.id], updated);
220
+ queryClient.invalidateQueries({ queryKey: ["todos"] });
221
+ queryClient.invalidateQueries({ queryKey: ["stats"] });
222
+ queryClient.invalidateQueries({ queryKey: ["users", updated.userId] });
223
+ },
224
+ });
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Pattern 12: Error Boundaries with throwOnError
230
+
231
+ ```tsx
232
+ useQuery({
233
+ queryKey: ["todos"],
234
+ queryFn: fetchTodos,
235
+ throwOnError: true,
236
+ });
237
+ ```
238
+
239
+ > For route data, prefer `throwOnError` + route error boundaries handled by the router.
@@ -0,0 +1,93 @@
1
+ # TanStack Query v4 → v5 Migration Guide
2
+
3
+ **Migration checklist for upgrading from React Query v4 to TanStack Query v5**
4
+
5
+ ---
6
+
7
+ ## Breaking Changes Summary
8
+
9
+ ### 1. Object Syntax Required
10
+
11
+ ```tsx
12
+ useQuery({
13
+ queryKey: ["todos"],
14
+ queryFn: fetchTodos,
15
+ staleTime: 5000,
16
+ });
17
+ ```
18
+
19
+ ### 2. Query Callbacks Removed
20
+
21
+ ```tsx
22
+ const { data } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos });
23
+ useEffect(() => {
24
+ if (data) console.log(data);
25
+ }, [data]);
26
+ ```
27
+
28
+ ### 3. `isLoading` → `isPending`
29
+
30
+ ```tsx
31
+ const { isPending } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos });
32
+ ```
33
+
34
+ ### 4. `cacheTime` → `gcTime`
35
+
36
+ ```tsx
37
+ gcTime: 1000 * 60 * 60;
38
+ ```
39
+
40
+ ### 5. `initialPageParam` Required for Infinite Queries
41
+
42
+ ```tsx
43
+ useInfiniteQuery({
44
+ queryKey: ["projects"],
45
+ queryFn: ({ pageParam }) => fetchProjects(pageParam),
46
+ initialPageParam: 0,
47
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
48
+ });
49
+ ```
50
+
51
+ ### 6. `keepPreviousData` → `placeholderData`
52
+
53
+ ```tsx
54
+ import { keepPreviousData } from "@tanstack/react-query";
55
+
56
+ useQuery({
57
+ queryKey: ["todos", page],
58
+ queryFn: () => fetchTodos(page),
59
+ placeholderData: keepPreviousData,
60
+ });
61
+ ```
62
+
63
+ ### 7. `useErrorBoundary` → `throwOnError`
64
+
65
+ ```tsx
66
+ useQuery({
67
+ queryKey: ["todos"],
68
+ queryFn: fetchTodos,
69
+ throwOnError: true,
70
+ });
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Step-by-Step Migration
76
+
77
+ 1. Update dependencies to the latest TanStack Query v5.
78
+ 2. Replace function overloads with object syntax.
79
+ 3. Replace query callbacks with `useEffect` or move to mutations.
80
+ 4. Replace `isLoading` with `isPending`.
81
+ 5. Replace `cacheTime` with `gcTime`.
82
+ 6. Add `initialPageParam` to infinite queries.
83
+ 7. Replace `keepPreviousData` with `placeholderData`.
84
+ 8. Update error boundaries with `throwOnError`.
85
+
86
+ ---
87
+
88
+ ## Common Migration Issues
89
+
90
+ - Callbacks not firing → use `useEffect`.
91
+ - `isLoading` always false → use `isPending`.
92
+ - `cacheTime` not recognized → use `gcTime`.
93
+ - Infinite query type error → add `initialPageParam`.
@@ -0,0 +1,63 @@
1
+ # Resilience and mutations
2
+
3
+ Use this reference for robust mutation flows, rollback behavior, and user-facing feedback without breaking layer boundaries.
4
+
5
+ ## Rules
6
+
7
+ - Query callbacks are removed in v5 queries, but mutation callbacks remain valid.
8
+ - Prefer optimistic updates with rollback for latency-sensitive UX.
9
+ - Keep feedback ownership in Presentation adapters; Application hooks should use callback injection or expose state.
10
+ - Preserve user-entered values on mutation failure for retry.
11
+
12
+ ## Pattern A: optimistic update + rollback
13
+
14
+ ```tsx
15
+ useMutation({
16
+ mutationFn: updateTodo,
17
+ onMutate: async (nextTodo) => {
18
+ await queryClient.cancelQueries({ queryKey: ["todos"] });
19
+ const previous = queryClient.getQueryData(["todos"]);
20
+ queryClient.setQueryData(["todos"], (old: Todo[] = []) =>
21
+ old.map((todo) => (todo.id === nextTodo.id ? nextTodo : todo))
22
+ );
23
+ return { previous };
24
+ },
25
+ onError: (_error, _vars, context) => {
26
+ queryClient.setQueryData(["todos"], context?.previous);
27
+ },
28
+ onSettled: () => {
29
+ queryClient.invalidateQueries({ queryKey: ["todos"] });
30
+ },
31
+ });
32
+ ```
33
+
34
+ ## Pattern B: layer-safe feedback bridge
35
+
36
+ ```typescript
37
+ export const useUpdateProduct = (onErrorFeedback: (message: string) => void) => {
38
+ return useMutation({
39
+ mutationFn: ProductRepository.update,
40
+ onError: () => {
41
+ onErrorFeedback("Failed to update product. Please retry.");
42
+ },
43
+ });
44
+ };
45
+ ```
46
+
47
+ ## Pattern C: throwOnError strategy for reads
48
+
49
+ ```tsx
50
+ useQuery({
51
+ queryKey: ["products"],
52
+ queryFn: fetchProducts,
53
+ throwOnError: (error) => error.status >= 500,
54
+ });
55
+ ```
56
+
57
+ Use route boundaries for route-critical reads and local handling for optional/background reads.
58
+
59
+ ## Pitfalls
60
+
61
+ - Treating query callback removal as mutation callback removal.
62
+ - Resetting forms on mutation error and losing user state.
63
+ - Importing UI toast adapters directly in Application hooks.
@@ -0,0 +1,116 @@
1
+ # Testing TanStack Query
2
+
3
+ **Testing queries, mutations, and components**
4
+
5
+ > Alignment note: for route data, test loaders with `ensureQueryData` and render pages with `useSuspenseQuery`.
6
+
7
+ ---
8
+
9
+ ## Test Utils
10
+
11
+ ```tsx
12
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
13
+ import { render } from "@testing-library/react";
14
+
15
+ export function createTestQueryClient() {
16
+ return new QueryClient({
17
+ defaultOptions: {
18
+ queries: {
19
+ retry: false,
20
+ gcTime: Infinity,
21
+ },
22
+ },
23
+ logger: {
24
+ log: console.log,
25
+ warn: console.warn,
26
+ error: () => {},
27
+ },
28
+ });
29
+ }
30
+
31
+ export function renderWithClient(ui: React.ReactElement) {
32
+ const testQueryClient = createTestQueryClient();
33
+ return render(<QueryClientProvider client={testQueryClient}>{ui}</QueryClientProvider>);
34
+ }
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Testing Queries
40
+
41
+ ```tsx
42
+ import { renderHook, waitFor } from "@testing-library/react";
43
+
44
+ describe("useTodos", () => {
45
+ it("fetches todos successfully", async () => {
46
+ const { result } = renderHook(() => useTodos(), {
47
+ wrapper: ({ children }) => (
48
+ <QueryClientProvider client={createTestQueryClient()}>{children}</QueryClientProvider>
49
+ ),
50
+ });
51
+
52
+ expect(result.current.isPending).toBe(true);
53
+ await waitFor(() => expect(result.current.isSuccess).toBe(true));
54
+ });
55
+ });
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Testing with MSW
61
+
62
+ ```tsx
63
+ import { HttpResponse, http } from "msw";
64
+ import { setupServer } from "msw/node";
65
+
66
+ const server = setupServer(
67
+ http.get("/api/todos", () => {
68
+ return HttpResponse.json([{ id: 1, title: "Test todo", completed: false }]);
69
+ })
70
+ );
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Testing Mutations
76
+
77
+ ```tsx
78
+ test("adds todo successfully", async () => {
79
+ const { result } = renderHook(() => useAddTodo());
80
+
81
+ act(() => {
82
+ result.current.mutate({ title: "New todo" });
83
+ });
84
+
85
+ await waitFor(() => expect(result.current.isSuccess).toBe(true));
86
+ });
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Testing Components with Suspense
92
+
93
+ ```tsx
94
+ import { Suspense } from "react";
95
+
96
+ render(
97
+ <QueryClientProvider client={createTestQueryClient()}>
98
+ <Suspense fallback={null}>
99
+ <TodoList />
100
+ </Suspense>
101
+ </QueryClientProvider>
102
+ );
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Best Practices
108
+
109
+ ✅ Disable retries in tests
110
+ ✅ Use MSW for consistent mocking
111
+ ✅ Test loading, success, and error states
112
+ ✅ Test optimistic updates and rollbacks
113
+ ✅ Use `waitFor` for async updates
114
+ ✅ Prefill cache when testing with existing data
115
+ ❌ Don't test implementation details
116
+ ❌ Don't mock TanStack Query internals
@@ -0,0 +1,148 @@
1
+ # Top TanStack Query Errors & Solutions
2
+
3
+ **Complete error reference with fixes**
4
+
5
+ ---
6
+
7
+ ## Error #1: Object Syntax Required
8
+
9
+ **Why**: v5 removed function overloads; only object syntax works.
10
+
11
+ **Fix**:
12
+
13
+ ```tsx
14
+ useQuery({ queryKey: ["todos"], queryFn: fetchTodos });
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Error #2: Query Callbacks Not Working
20
+
21
+ **Why**: `onSuccess`, `onError`, `onSettled` removed from queries (still work in mutations).
22
+
23
+ **Fix**:
24
+
25
+ ```tsx
26
+ const { data } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos });
27
+ useEffect(() => {
28
+ if (data) console.log(data);
29
+ }, [data]);
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Error #3: isLoading Always False
35
+
36
+ **Why**: v5 changed `isLoading` meaning; use `isPending` for initial load.
37
+
38
+ **Fix**:
39
+
40
+ ```tsx
41
+ const { isPending } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos });
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Error #4: cacheTime Not Recognized
47
+
48
+ **Why**: Renamed to `gcTime`.
49
+
50
+ **Fix**:
51
+
52
+ ```tsx
53
+ gcTime: 1000 * 60 * 60;
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Error #5: useSuspenseQuery + enabled
59
+
60
+ **Why**: `enabled` not available with Suspense.
61
+
62
+ **Fix**:
63
+
64
+ ```tsx
65
+ {
66
+ id ? <TodoComponent id={id} /> : <div>No ID</div>;
67
+ }
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Error #6: initialPageParam Required
73
+
74
+ **Why**: v5 requires explicit `initialPageParam` for infinite queries.
75
+
76
+ **Fix**:
77
+
78
+ ```tsx
79
+ useInfiniteQuery({
80
+ queryKey: ["projects"],
81
+ queryFn: ({ pageParam }) => fetchProjects(pageParam),
82
+ initialPageParam: 0,
83
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
84
+ });
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Error #7: keepPreviousData Not Working
90
+
91
+ **Why**: replaced by `placeholderData`.
92
+
93
+ **Fix**:
94
+
95
+ ```tsx
96
+ import { keepPreviousData } from "@tanstack/react-query";
97
+
98
+ useQuery({
99
+ queryKey: ["todos", page],
100
+ queryFn: () => fetchTodos(page),
101
+ placeholderData: keepPreviousData,
102
+ });
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Error #8: Error Type Mismatch
108
+
109
+ **Why**: v5 defaults to `Error` instead of `unknown`.
110
+
111
+ **Fix**:
112
+
113
+ ```tsx
114
+ const { error } = useQuery<DataType, string>({
115
+ queryKey: ["data"],
116
+ queryFn: async () => {
117
+ if (fail) throw "custom error";
118
+ return data;
119
+ },
120
+ });
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Error #9: invalidateQueries Doesn’t Refetch Inactive
126
+
127
+ **Why**: `invalidateQueries` only refetches active queries by default.
128
+
129
+ **Fix**:
130
+
131
+ ```tsx
132
+ queryClient.invalidateQueries({
133
+ queryKey: ["todos"],
134
+ refetchType: "all",
135
+ });
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Quick Diagnosis Checklist
141
+
142
+ - [ ] Object syntax in all hooks?
143
+ - [ ] `isPending` for initial loading?
144
+ - [ ] `gcTime` instead of `cacheTime`?
145
+ - [ ] No query callbacks (`onSuccess`, etc.)?
146
+ - [ ] `initialPageParam` for infinite queries?
147
+ - [ ] Query keys are arrays?
148
+ - [ ] Errors thrown in `queryFn`?