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,110 @@
1
+ # Resilience Patterns (TanStack Flow)
2
+
3
+ Load this file when implementing async UX behavior, route-level error handling, or mutation failure feedback.
4
+
5
+ ## 1) Suspense + Skeleton for Initial Route Data
6
+
7
+ Use this when route data is preloaded with `ensureQueryData`.
8
+
9
+ ```tsx
10
+ import { Suspense } from "react";
11
+
12
+ import { ProductListPage } from "@/presentation/product/ProductList.page";
13
+ import { ProductListSkeleton } from "@/presentation/product/components/ProductListSkeleton";
14
+
15
+ export const ProductListWithFallback = () => {
16
+ return (
17
+ <Suspense fallback={<ProductListSkeleton />}>
18
+ <ProductListPage />
19
+ </Suspense>
20
+ );
21
+ };
22
+ ```
23
+
24
+ Guidelines:
25
+
26
+ - Skeleton shape should mirror real layout to avoid jarring transitions.
27
+ - Do not add route-initial `isLoading` branches in the page if Suspense already wraps it.
28
+
29
+ ## 2) Route Error Boundary (404 vs 500 + Retry)
30
+
31
+ Use this for routes that fetch remote data in `loader`.
32
+
33
+ ```tsx
34
+ import { createFileRoute, useRouter } from "@tanstack/react-router";
35
+
36
+ import { productQueries } from "@/application/product/product.queries";
37
+ import { NotFoundPage } from "@/presentation/shared/components/NotFoundPage";
38
+ import { RouteErrorPage } from "@/presentation/shared/components/RouteErrorPage";
39
+
40
+ const isNotFoundError = (error: unknown) => error instanceof Error && error.message.includes("404");
41
+
42
+ function ProductsErrorBoundary({ error }: { error: unknown }) {
43
+ const router = useRouter();
44
+
45
+ if (isNotFoundError(error)) {
46
+ return <NotFoundPage />;
47
+ }
48
+
49
+ return <RouteErrorPage title="Unable to load products" onRetry={() => router.invalidate()} />;
50
+ }
51
+
52
+ export const Route = createFileRoute("/products")({
53
+ loader: async ({ context: { queryClient }, params }) => {
54
+ await queryClient.ensureQueryData(productQueries.detail(params.productId));
55
+ },
56
+ errorComponent: ProductsErrorBoundary,
57
+ component: ProductsPage,
58
+ });
59
+ ```
60
+
61
+ Guidelines:
62
+
63
+ - Throw from loader to boundary instead of swallowing errors.
64
+ - Classify not-found paths separately from generic failures.
65
+ - Retry should invalidate route/query state, not force full page reload.
66
+
67
+ ## 3) Mutation Error Feedback without Page Crash
68
+
69
+ Use this for write operations (forms, toggles, destructive actions).
70
+
71
+ ```typescript
72
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
73
+
74
+ import { productKeys } from "@/application/product/product.queries";
75
+ import { ProductRepository } from "@/infrastructure/product/product.repository";
76
+
77
+ export const useUpdateProduct = (
78
+ onSuccessFeedback: (message: string) => void,
79
+ onErrorFeedback: (message: string) => void
80
+ ) => {
81
+ const queryClient = useQueryClient();
82
+
83
+ return useMutation({
84
+ mutationFn: ProductRepository.update,
85
+ onSuccess: async (updated) => {
86
+ await queryClient.invalidateQueries({
87
+ queryKey: productKeys.detail(updated.id),
88
+ });
89
+ onSuccessFeedback("Product updated");
90
+ },
91
+ onError: () => {
92
+ onErrorFeedback("Failed to update product. Please retry.");
93
+ },
94
+ });
95
+ };
96
+ ```
97
+
98
+ Guidelines:
99
+
100
+ - Keep user-entered state when mutation fails.
101
+ - Keep feedback adapters (toast/snackbar) in Presentation and inject callbacks.
102
+ - Prefer focused feedback (toast/inline message) over global crash UI.
103
+ - Retry should be user-driven and explicit.
104
+
105
+ ## Decision Checklist
106
+
107
+ - Is this route-initial data? Use Suspense + boundary.
108
+ - Is this a user write action? Use mutation `onError` feedback.
109
+ - Is this a recoverable not-found case? Route-level typed not-found UI.
110
+ - Is this transient infra failure? Show retry action and preserve user context.
@@ -0,0 +1,82 @@
1
+ # Suspense Consumption Examples
2
+
3
+ Use these examples in `src/application/{feature}/hooks` and `src/presentation/{feature}`.
4
+
5
+ ## A. Application Hook for Route Search Data
6
+
7
+ ```typescript
8
+ import { useSuspenseQuery } from "@tanstack/react-query";
9
+ import { getRouteApi } from "@tanstack/react-router";
10
+
11
+ import { productQueries } from "@/application/product/product.queries";
12
+ import { usePreferencesStore } from "@/application/product/store/preferences.store";
13
+
14
+ const productsRouteApi = getRouteApi("/products/");
15
+
16
+ export const useProductsFromRoute = () => {
17
+ const search = productsRouteApi.useSearch();
18
+ const storeId = usePreferencesStore((state) => state.storeId);
19
+
20
+ if (!storeId) {
21
+ throw new Error("storeId is required to fetch products");
22
+ }
23
+
24
+ return useSuspenseQuery(productQueries.list(storeId, search));
25
+ };
26
+ ```
27
+
28
+ ## B. Presentation Page Consuming Application Hook
29
+
30
+ ```tsx
31
+ import { useProductsFromRoute } from "@/application/product/hooks/useProductsFromRoute";
32
+
33
+ export const ProductListPage = () => {
34
+ const { data } = useProductsFromRoute();
35
+
36
+ return (
37
+ <section>
38
+ <h1>Products</h1>
39
+ <ul>
40
+ {data.items.map((product) => (
41
+ <li key={product.id}>{product.name}</li>
42
+ ))}
43
+ </ul>
44
+ </section>
45
+ );
46
+ };
47
+ ```
48
+
49
+ ## C. Partial Refresh Pattern
50
+
51
+ When the page has route-critical data and local UI interactions:
52
+
53
+ - Keep initial data preload in loader + `ensureQueryData`.
54
+ - Use query-keyed local controls for client-side refetches.
55
+ - Avoid returning to manual `isLoading` guards for first render.
56
+
57
+ ## D. Suspense Rules
58
+
59
+ - Prefer Suspense path for first route render data.
60
+ - Keep error handling in route boundaries or route-level components.
61
+ - Reserve direct presentation-level `useSuspenseQuery` for very simple pages.
62
+
63
+ ## E. Route Entry Fallback Composition
64
+
65
+ ```tsx
66
+ import { Suspense } from "react";
67
+
68
+ import { ProductListPage } from "@/presentation/product/ProductList.page";
69
+ import { ProductListSkeleton } from "@/presentation/product/components/ProductListSkeleton";
70
+
71
+ export const ProductListRouteView = () => (
72
+ <Suspense fallback={<ProductListSkeleton />}>
73
+ <ProductListPage />
74
+ </Suspense>
75
+ );
76
+ ```
77
+
78
+ Guidelines:
79
+
80
+ - Keep fallback shape aligned to page layout.
81
+ - Avoid parallel manual `isLoading` branches for the same initial route data.
82
+ - See [resilience-patterns.md](resilience-patterns.md) for error boundary and retry patterns.
@@ -0,0 +1,241 @@
1
+ ---
2
+ name: tanstack-query
3
+ description: >
4
+ Advanced TanStack Query v5 extensions. Trigger: when implementing advanced Query patterns, v5 migrations, cache
5
+ optimizations, mutation lifecycle handling, or query error propagation strategies.
6
+ license: Apache-2.0
7
+ metadata:
8
+ author: jmgomezdev
9
+ version: "1.0"
10
+ ---
11
+
12
+ ## Required Base
13
+
14
+ This skill **always** applies **after** the tanstack skill and **never** contradicts it.
15
+
16
+ - Direct reference: use the tanstack skill as the mandatory foundation.
17
+ - Everything not mentioned here follows tanstack rules.
18
+
19
+ ## Objective
20
+
21
+ Provide advanced rules, v5 issue prevention, and cache optimization patterns that complement the
22
+ “render-as-you-fetch” flow defined in tanstack.
23
+
24
+ ## Dependencies
25
+
26
+ - Base skill: tanstack
27
+ - Packages: @tanstack/react-query
28
+
29
+ ## Render-as-you-fetch Alignment (tanstack)
30
+
31
+ This skill **extends** the render-as-you-fetch flow defined in the tanstack skill:
32
+
33
+ - Define `queryOptions` / `infiniteQueryOptions` in Application.
34
+ - Use Router loaders with `queryClient.ensureQueryData` / `ensureInfiniteQueryData`.
35
+ - Prefer consuming in Presentation via an Application hook that wraps `useSuspenseQuery` /
36
+ `useSuspenseInfiniteQuery`. Use direct hooks only for very simple cases.
37
+ - Never fetch server data in `useEffect`.
38
+
39
+ ## References
40
+
41
+ - Base tanstack skill: [.github/skills/tanstack/SKILL.md](../tanstack/SKILL.md)
42
+ - Advanced patterns and hooks: [references/advanced-hooks.md](references/advanced-hooks.md)
43
+ - Cache strategies: [references/cache-strategies.md](references/cache-strategies.md)
44
+ - Best practices: [references/best-practices.md](references/best-practices.md)
45
+ - Common patterns: [references/common-patterns.md](references/common-patterns.md)
46
+ - Top errors & fixes: [references/top-errors.md](references/top-errors.md)
47
+ - Resilience and mutations: [references/resilience-and-mutations.md](references/resilience-and-mutations.md)
48
+ - TypeScript patterns: [references/typescript.md](references/typescript.md)
49
+ - v4 → v5 migration: [references/migration-v5.md](references/migration-v5.md)
50
+ - Testing: [references/testing.md](references/testing.md)
51
+
52
+ ## Reference Router (Mandatory Loading)
53
+
54
+ Loading protocol:
55
+
56
+ 1. Pick one scenario first.
57
+ 2. MANDATORY: read only the selected reference before implementing.
58
+ 3. Do NOT load all references by default.
59
+ 4. If blocked, load exactly one additional reference.
60
+
61
+ | Scenario | MANDATORY Reference | Do NOT Load (unless needed) |
62
+ | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | --------------------------- |
63
+ | Advanced hook composition (`useQueries`, `useMutationState`, infinite hooks) | [references/advanced-hooks.md](references/advanced-hooks.md) | `migration-v5.md` |
64
+ | Cache lifetimes, invalidation, refetch strategy | [references/cache-strategies.md](references/cache-strategies.md) | `migration-v5.md` |
65
+ | v5 migration and API breakages | [references/migration-v5.md](references/migration-v5.md) | `advanced-hooks.md` |
66
+ | Query errors, callback confusion, common pitfalls | [references/top-errors.md](references/top-errors.md) | `testing.md` |
67
+ | Mutation resilience and feedback ownership | [references/resilience-and-mutations.md](references/resilience-and-mutations.md) | `migration-v5.md` |
68
+ | Query typing constraints and TS inference | [references/typescript.md](references/typescript.md) | `cache-strategies.md` |
69
+
70
+ ## Compatibility Checklist with tanstack
71
+
72
+ Before applying this skill, confirm:
73
+
74
+ 1. Use of queryOptions and loaders per tanstack.
75
+ 2. Object syntax in hooks.
76
+ 3. Query keys as arrays.
77
+ 4. Suspense + loaders for required data.
78
+
79
+ ## Quick Application (Summary)
80
+
81
+ - `useMutationState` for global tracking.
82
+ - `networkMode` for offline/PWA.
83
+ - `useQueries` with `combine` for aggregated parallel results.
84
+ - `infiniteQueryOptions` and `maxPages` for efficient pagination.
85
+ - v5 issue prevention (removed callbacks, `gcTime`, `isPending`).
86
+
87
+ ## Essential Rules (Must)
88
+
89
+ - Use object syntax and array query keys everywhere.
90
+ - Keep route-required data in the tanstack flow (Application `queryOptions` → Loader `ensureQueryData` →
91
+ Presentation `useSuspenseQuery`).
92
+ - Set `staleTime` by data volatility and `gcTime` by revisit frequency.
93
+ - Invalidate with precise keys after mutations; use `refetchType: 'all'` only when inactive queries must refetch.
94
+ - Optimistic updates require: `cancelQueries` → snapshot → optimistic `setQueryData` → rollback on error →
95
+ invalidate on settle.
96
+ - Infinite queries must set `initialPageParam`; `maxPages` requires bi-directional pagination.
97
+ - Use `useQueries` for optional/secondary data, not required route data.
98
+ - Use `prefetchQuery` only for optional navigation (hover/background), never for required route data.
99
+ - Keep mutation feedback layer-safe: inject feedback callbacks or return mutation state; do not import presentation
100
+ toasts in Application hooks.
101
+
102
+ ## TanStack Query v5 — Critical Rules, Issues, and Anti‑Patterns
103
+
104
+ > These rules **extend** the tanstack skill. If there is a conflict, tanstack wins.
105
+
106
+ ### Critical Rules (Always Do)
107
+
108
+ ✅ Use object syntax in all hooks:
109
+
110
+ ```tsx
111
+ useQuery({ queryKey, queryFn, ...options });
112
+ useMutation({ mutationFn, ...options });
113
+ ```
114
+
115
+ ✅ Query keys always as arrays:
116
+
117
+ ```tsx
118
+ queryKey: ["todos"];
119
+ queryKey: ["todos", id];
120
+ queryKey: ["todos", { filter }];
121
+ ```
122
+
123
+ ✅ Configure `staleTime` appropriately for the use case.
124
+
125
+ ✅ Use `isPending` for initial loading state.
126
+
127
+ ✅ Always throw `Error` in `queryFn` on failure.
128
+
129
+ ✅ Invalidate queries after mutations with `queryClient.invalidateQueries`.
130
+
131
+ ✅ Use `queryOptions` for reusable patterns.
132
+
133
+ ✅ Use `gcTime`, not `cacheTime`.
134
+
135
+ ### Forbidden (Never Do)
136
+
137
+ ❌ v4 syntax (array/function).
138
+
139
+ ❌ Callbacks in queries (`onSuccess`, `onError`, `onSettled`) - this does not apply to mutations.
140
+
141
+ ❌ `cacheTime`, `isLoading` for initial state, `keepPreviousData`, `useErrorBoundary`.
142
+
143
+ ❌ Using `enabled` with `useSuspenseQuery`.
144
+
145
+ ❌ Omitting `initialPageParam` in infinite queries.
146
+
147
+ ❌ Relying on `refetchOnMount: false` for errored queries (use `retryOnMount: false`).
148
+
149
+ ### Known Issues and Prevention
150
+
151
+ #### #2 Query callbacks removed
152
+
153
+ - **Problem:** callbacks do not exist in v5 queries.
154
+ - **Prevention:** use `useEffect` with `data`.
155
+ - **Note:** mutation callbacks remain valid and are expected for optimistic flows and feedback.
156
+
157
+ #### #3 `status: loading` → `pending`
158
+
159
+ - **Problem:** UI out of sync.
160
+ - **Prevention:** use `isPending` for initial load.
161
+
162
+ #### #4 `cacheTime` → `gcTime`
163
+
164
+ - **Problem:** type errors.
165
+ - **Prevention:** replace with `gcTime`.
166
+
167
+ #### #5 `useSuspenseQuery` + `enabled`
168
+
169
+ - **Problem:** `enabled` not available.
170
+ - **Prevention:** conditional rendering outside the hook.
171
+
172
+ #### #6 `initialPageParam` required
173
+
174
+ - **Problem:** type errors.
175
+ - **Prevention:** set `initialPageParam` explicitly.
176
+
177
+ #### #7 `keepPreviousData` removed
178
+
179
+ - **Prevention:** `placeholderData: keepPreviousData`.
180
+
181
+ #### #8 Default Error type
182
+
183
+ - **Prevention:** throw `Error` or type the error explicitly.
184
+
185
+ #### #12 Mutation callback signature change (v5.89.0+)
186
+
187
+ - **Problem:** callbacks receive 4 parameters.
188
+ - **Prevention:** use `(data, variables, onMutateResult, context)` signature.
189
+
190
+ #### #13 Readonly query keys break partial matching (v5.90.8)
191
+
192
+ - **Prevention:** upgrade to v5.90.9+.
193
+
194
+ #### #14 `useMutationState` loses inference
195
+
196
+ - **Prevention:** cast in `select`.
197
+
198
+ #### #15 Cancellation in StrictMode with `fetchQuery`
199
+
200
+ - **Prevention:** expected behavior; use `staleTime: Infinity` to keep it observed.
201
+
202
+ #### #16 `invalidateQueries` only refetches active queries
203
+
204
+ - **Prevention:** use `refetchType: 'all'` if you need inactive ones.
205
+
206
+ ### Community Tips
207
+
208
+ #### Different options in the same query
209
+
210
+ - “Last write wins” for future options.
211
+ - **Recommended:** compute options on render using functions.
212
+
213
+ #### `refetch()` is not for new parameters
214
+
215
+ - **Rule:** change parameters in the `queryKey` and let Query refetch.
216
+
217
+ ### Anti‑Patterns (FORBIDDEN)
218
+
219
+ ```ts
220
+ // Do not store server state in Zustand/Redux
221
+ // Do not use string query keys
222
+ // Do not use cacheTime
223
+ // Do not use isLoading for initial state
224
+ // Do not invalidate EVERYTHING indiscriminately
225
+ // Do not forget cancelQueries in optimistic updates
226
+ // Do not mutate cache data directly
227
+ // Do not fetch in useEffect
228
+ // Do not import presentation feedback adapters (toast/snackbar) into application mutation hooks
229
+ ```
230
+
231
+ > For complete examples, see the tanstack skill.
232
+
233
+ ## Quality Gate (Self-Check)
234
+
235
+ Before finishing, verify:
236
+
237
+ - Query hooks use v5 object syntax and array query keys.
238
+ - Route-critical reads still follow loader + Suspense flow from `tanstack`.
239
+ - Query callbacks are not used (mutations may use callbacks).
240
+ - Mutation feedback does not import presentation adapters into Application hooks.
241
+ - Invalidation uses key factories and avoids broad indiscriminate invalidation.
@@ -0,0 +1,126 @@
1
+ # Advanced TanStack Query Patterns (v5)
2
+
3
+ > These practices **complement** the tanstack skill. They do not replace or contradict its rules.
4
+
5
+ ## useMutationState — Global mutation tracking
6
+
7
+ Access mutation state from any component without prop drilling:
8
+
9
+ ```tsx
10
+ import { useMutationState } from "@tanstack/react-query";
11
+
12
+ function GlobalLoadingIndicator() {
13
+ const pendingMutations = useMutationState({
14
+ filters: { status: "pending" },
15
+ select: (mutation) => mutation.state.variables,
16
+ });
17
+
18
+ if (pendingMutations.length === 0) return null;
19
+ return <div>Saving {pendingMutations.length} items...</div>;
20
+ }
21
+
22
+ // Filter by mutationKey
23
+ const todoMutations = useMutationState({
24
+ filters: { mutationKey: ["addTodo"] },
25
+ });
26
+ ```
27
+
28
+ ### Typing note
29
+
30
+ Due to fuzzy inference, `mutation.state.variables` can be `unknown`. See issue #14 in the tanstack-query SKILL.md.
31
+
32
+ ## Network Mode — Offline/PWA support
33
+
34
+ Control behavior when offline:
35
+
36
+ ```tsx
37
+ const queryClient = new QueryClient({
38
+ defaultOptions: {
39
+ queries: {
40
+ networkMode: "offlineFirst",
41
+ },
42
+ },
43
+ });
44
+
45
+ useQuery({
46
+ queryKey: ["todos"],
47
+ queryFn: fetchTodos,
48
+ networkMode: "always",
49
+ });
50
+ ```
51
+
52
+ | Mode | Behavior |
53
+ | ------------------ | ------------------------------------------- |
54
+ | `online` (default) | Only fetches when online |
55
+ | `always` | Always tries (local APIs or service worker) |
56
+ | `offlineFirst` | Uses cache first, fetches when back online |
57
+
58
+ **Paused state detection:**
59
+
60
+ ```tsx
61
+ const { isPending, fetchStatus } = useQuery(...)
62
+ // isPending + fetchStatus === 'paused' = offline, waiting for network
63
+ ```
64
+
65
+ ## useQueries with combine
66
+
67
+ Combine results from parallel queries (use for optional/secondary data, not required route data):
68
+
69
+ ```tsx
70
+ const results = useQueries({
71
+ queries: userIds.map((id) => ({
72
+ queryKey: ['user', id],
73
+ queryFn: () => fetchUser(id),
74
+ })),
75
+ combine: (results) => ({
76
+ data: results.map((r) => r.data),
77
+ pending: results.some((r) => r.isPending),
78
+ error: results.find((r) => r.error)?.error,
79
+ }),
80
+ });
81
+
82
+ if (results.pending) return <Loading />;
83
+ console.log(results.data);
84
+
85
+ > For required route data, keep the tanstack render-as-you-fetch flow: Application `queryOptions` → Loader `ensureQueryData` → Presentation `useSuspenseQuery`.
86
+ ```
87
+
88
+ ## infiniteQueryOptions helper
89
+
90
+ Typed factory for infinite queries (parallel to queryOptions):
91
+
92
+ ```tsx
93
+ import {
94
+ infiniteQueryOptions,
95
+ prefetchInfiniteQuery,
96
+ useInfiniteQuery,
97
+ } from "@tanstack/react-query";
98
+
99
+ const todosInfiniteOptions = infiniteQueryOptions({
100
+ queryKey: ["todos", "infinite"],
101
+ queryFn: ({ pageParam }) => fetchTodosPage(pageParam),
102
+ initialPageParam: 0,
103
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
104
+ });
105
+
106
+ useInfiniteQuery(todosInfiniteOptions);
107
+ useSuspenseInfiniteQuery(todosInfiniteOptions);
108
+ prefetchInfiniteQuery(queryClient, todosInfiniteOptions);
109
+ ```
110
+
111
+ ## maxPages — Memory optimization
112
+
113
+ Limit cached pages for infinite queries:
114
+
115
+ ```tsx
116
+ useInfiniteQuery({
117
+ queryKey: ["posts"],
118
+ queryFn: ({ pageParam }) => fetchPosts(pageParam),
119
+ initialPageParam: 0,
120
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
121
+ getPreviousPageParam: (firstPage) => firstPage.prevCursor,
122
+ maxPages: 3,
123
+ });
124
+ ```
125
+
126
+ **Rule:** `maxPages` requires bi-directional pagination.