From 6559d84c18f21dd1ad01654d61cfcd444d6a7cb8 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:10:06 +0400 Subject: [PATCH 01/22] docs: add query client docs completion design --- ...-21-query-client-docs-completion-design.md | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md diff --git a/docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md b/docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md new file mode 100644 index 000000000..ebb734900 --- /dev/null +++ b/docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md @@ -0,0 +1,85 @@ +# Query Client Docs Completion Design + +## Context + +The current documentation under `website/docs` has four query-client pages that still show the active-update notice: + +- `website/docs/query-client/getQueryState.mdx` +- `website/docs/query-client/resetQueries.mdx` +- `website/docs/query-client/getInfiniteQueryState.mdx` +- `website/docs/query-client/setInfiniteQueryData.mdx` + +These pages are part of the current docs and should be completed. Versioned documentation under `website/versioned_docs/*` is intentionally out of scope. If older versioned docs still contain the same notice, leave them unchanged so users are guided toward the current documentation for the most accurate contract. + +## Goal + +Complete the four current query-client reference pages so they match the surrounding documentation quality: + +- explain what the Qraft method does; +- point to the matching TanStack Query `QueryClient` API; +- document arguments and return values; +- show concrete examples using the existing `api` or `qraft` naming conventions; +- remove the active-update notice from the current docs pages. + +## Scope + +In scope: + +- Rewrite the four listed current docs pages. +- Make small, directly related consistency fixes in nearby query-client docs when the page being completed references them. +- Keep examples domain-specific and aligned with existing docs patterns, primarily `pet` and `files`. +- Validate that `website/docs` no longer contains `Documentation is actively being updated`. + +Out of scope: + +- Editing `website/versioned_docs/*`. +- Broad stylistic rewrites across the full query-client section. +- Changing generated code, runtime behavior, or public types. +- Adding new docs infrastructure. + +## Page Design + +### `getQueryState` + +Document it as a typed wrapper around `queryClient.getQueryState`. It accepts operation parameters, a typed `QueryKey`, or `void` for operations without required parameters. It returns the current query state or `undefined` when the query is not in the cache. + +Examples should cover reading state after cached data exists and using a typed query key. + +### `resetQueries` + +Document it as a typed wrapper around `queryClient.resetQueries`. It operates on query filters, not a single direct request. The filters should mirror the nearby `cancelQueries`, `removeQueries`, and `invalidateQueries` docs: + +- `filters.parameters` for operation parameters; +- `filters.queryKey` for an explicit typed query key; +- `filters.infinite` to distinguish regular and infinite query cache entries; +- `filters.predicate` for custom matching. + +The page must not call this method a hook. It should mention that it returns `Promise` and accepts TanStack reset options as the second argument. + +### `getInfiniteQueryState` + +Document it as the infinite-query counterpart to `getQueryState`. It still maps to TanStack `queryClient.getQueryState`, but uses the infinite query key shape and returns state for `OperationInfiniteData`-style cache data. + +Examples should show the method after an infinite query cache entry has been created and should make the `pages` / `pageParams` shape visible. + +### `setInfiniteQueryData` + +Document it as the infinite-query counterpart to `setQueryData`. It writes directly to the cache for one infinite query and accepts parameters or a typed infinite query key, an updater or direct value, and optional TanStack set-data options. + +Examples should show both direct replacement and functional update of `pages` / `pageParams` data. + +## Validation + +After implementation: + +- Run a scoped grep that checks only `website/docs` for `Documentation is actively being updated`. +- Run `git diff --check`. +- Run the repository's docs check/build only if there is a clear local command for it; otherwise record that static docs validation was used. + +Versioned docs are excluded from the active-update grep on purpose. + +## Risks + +- The generated type surface includes optional parameters for some operations, so examples should avoid implying that every operation requires parameters. +- Infinite-query examples can become too abstract if they only reference TanStack. They should show the Qraft-specific `pages` / `pageParams` cache data shape. +- A broad docs sweep could create unnecessary review noise. Keep related cleanup narrow. From 436dbbc1ffc1a02026795175c563fe92bcbbdddd Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:13:57 +0400 Subject: [PATCH 02/22] docs: add query client docs completion plan --- ...2026-05-21-query-client-docs-completion.md | 586 ++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-21-query-client-docs-completion.md diff --git a/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md b/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md new file mode 100644 index 000000000..f0d16193e --- /dev/null +++ b/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md @@ -0,0 +1,586 @@ +# Query Client Docs Completion Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Complete the four current query-client docs pages that still contain the active-update notice. + +**Architecture:** This is a documentation-only change. Each task rewrites one tightly scoped MDX reference page using the existing query-client docs style, with one final validation task that checks only current docs under `website/docs`. + +**Tech Stack:** Docusaurus MDX, TanStack Query v5 concepts, Qraft generated React client docs, Yarn 4 workspace scripts. + +--- + +## File Structure + +- Modify: `website/docs/query-client/getQueryState.mdx` + - Responsibility: document the typed `queryClient.getQueryState` wrapper for normal queries. +- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` + - Responsibility: document the infinite-query counterpart that uses infinite query keys and infinite cache data. +- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` + - Responsibility: document writing `pages` / `pageParams` cache data for one infinite query. +- Modify: `website/docs/query-client/resetQueries.mdx` + - Responsibility: document typed query-filter based reset behavior and remove the incorrect hook wording. +- Do not modify: `website/versioned_docs/*` + - Responsibility: keep historical docs unchanged; active-update notices there are intentionally allowed. + +## Task 1: Complete `getQueryState` Docs + +**Files:** +- Modify: `website/docs/query-client/getQueryState.mdx` + +- [ ] **Step 1: Replace the placeholder page with complete reference content** + +Replace the whole file with: + +````mdx +--- +sidebar_label: getQueryState() +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# getQueryState(...) + +The method enables direct access to the `QueryClient` cache state for a specific _Query_. +It is a strictly-typed wrapper around TanStack +[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate). + +```ts +const state = api...getQueryState(parameters); +``` + +## Arguments + +1. `parameters: { path, query, header } | QueryKey | void` + - Operation parameters used to build the _Query Key_, strictly-typed ✨ + - Instead of an object with `{ path, query, header }`, you can pass a typed `QueryKey` array. + - For operations without required parameters, call the method without arguments. + +## Returns + +`QueryState | undefined` - The current cache state for the query, or `undefined` if the query is not in the cache. + +## Example + + + + ```tsx + const parameters = { path: { petId: 123 } }; + + await api.pet.getPetById.fetchQuery(parameters); + + const state = api.pet.getPetById.getQueryState(parameters); + + expect(state?.status).toEqual('success'); + expect(state?.data?.id).toEqual(123); + ``` + + + ```tsx + const parameters = { path: { petId: 123 } }; + const queryKey = api.pet.getPetById.getQueryKey(parameters); + + await api.pet.getPetById.fetchQuery(parameters); + + const state = api.pet.getPetById.getQueryState(queryKey); + + expect(state?.status).toEqual('success'); + ``` + + + ```tsx + await api.pet.findPets.fetchQuery(); + + const state = api.pet.findPets.getQueryState(); + + expect(state?.status).toEqual('success'); + ``` + + +```` + +- [ ] **Step 2: Check the page no longer contains the active-update notice** + +Run: + +```bash +rg -n "Documentation is actively being updated" website/docs/query-client/getQueryState.mdx +``` + +Expected: command exits with no matches. + +- [ ] **Step 3: Commit Task 1** + +Run: + +```bash +git add website/docs/query-client/getQueryState.mdx +git commit -m "docs: complete getQueryState reference" +``` + +Expected: commit succeeds with only `getQueryState.mdx` staged. + +## Task 2: Complete `getInfiniteQueryState` Docs + +**Files:** +- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` + +- [ ] **Step 1: Replace the placeholder page with complete reference content** + +Replace the whole file with: + +````mdx +--- +sidebar_label: getInfiniteQueryState() +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# getInfiniteQueryState(...) + +The method enables direct access to the `QueryClient` cache state for a specific _Infinite Query_. +It is the infinite-query counterpart to [`getQueryState`](getQueryState.mdx): Qraft still calls TanStack +[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate), +but it builds an infinite query key and returns state for infinite cache data. + +```ts +const state = api...getInfiniteQueryState(parameters); +``` + +## Arguments + +1. `parameters: { path, query, header } | InfiniteQueryKey | void` + - Operation parameters used to build the _Infinite Query Key_, strictly-typed ✨ + - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. + - For operations without required parameters, call the method without arguments. + +## Returns + +`QueryState, TError> | undefined` - The current cache state for the infinite query, or `undefined` if the infinite query is not in the cache. + +## Example + + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + + api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + const state = api.pet.findPetsByStatus.getInfiniteQueryState(parameters); + + expect(state?.data).toEqual({ + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + ``` + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + const queryKey = api.pet.findPetsByStatus.getInfiniteQueryKey(parameters); + + api.pet.findPetsByStatus.setInfiniteQueryData(queryKey, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + const state = api.pet.findPetsByStatus.getInfiniteQueryState(queryKey); + + expect(state?.status).toEqual('success'); + ``` + + +```` + +- [ ] **Step 2: Check the page no longer contains the active-update notice** + +Run: + +```bash +rg -n "Documentation is actively being updated" website/docs/query-client/getInfiniteQueryState.mdx +``` + +Expected: command exits with no matches. + +- [ ] **Step 3: Commit Task 2** + +Run: + +```bash +git add website/docs/query-client/getInfiniteQueryState.mdx +git commit -m "docs: complete getInfiniteQueryState reference" +``` + +Expected: commit succeeds with only `getInfiniteQueryState.mdx` staged. + +## Task 3: Complete `setInfiniteQueryData` Docs + +**Files:** +- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` + +- [ ] **Step 1: Replace the placeholder page with complete reference content** + +Replace the whole file with: + +````mdx +--- +sidebar_label: setInfiniteQueryData() +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# setInfiniteQueryData(...) + +The method enables direct access to the `QueryClient` cache to set data for a specific _Infinite Query_. +It has the same role as [`setQueryData`](setQueryData.mdx), but writes infinite-query data with `pages` and `pageParams`. + +See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation. + +```ts +const data = api...setInfiniteQueryData( + parameters, + updater, + options +); +``` + +## Arguments + +1. `parameters: { path, query, header } | InfiniteQueryKey` + - **Required** parameters to set the data in the _Infinite Query Cache_. + - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. +2. `updater: InfiniteData | (oldData: InfiniteData | undefined) => InfiniteData | undefined` + - **Required** updater for the infinite-query cache data. + - If a non-function value is passed, the data will be updated to this value. + - If a function is passed, it receives the old infinite-query data and must return the next value. +3. `options?: SetQueryDataOptions` + - Optional options to set the data in the cache. + - See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation for more details. + +## Returns + +`InfiniteData | undefined` - The data that was written to the cache, or `undefined` if the updater returns `undefined`. + +## Example + + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + + const pets = api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + expect(pets).toEqual({ + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + ``` + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + + api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { + pages: [[]], + pageParams: [parameters], + }); + + const pets = api.pet.findPetsByStatus.setInfiniteQueryData( + parameters, + (oldData) => ({ + pages: [ + ...(oldData?.pages ?? []), + [{ id: 2, name: 'Bella', status: 'available' }], + ], + pageParams: [ + ...(oldData?.pageParams ?? []), + { query: { status: 'available', page: 2 } }, + ], + }) + ); + + expect(pets?.pages.at(-1)).toEqual([ + { id: 2, name: 'Bella', status: 'available' }, + ]); + ``` + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + const queryKey = api.pet.findPetsByStatus.getInfiniteQueryKey(parameters); + + api.pet.findPetsByStatus.setInfiniteQueryData(queryKey, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + expect(api.pet.findPetsByStatus.getInfiniteQueryData(parameters)?.pages).toHaveLength(1); + ``` + + +```` + +- [ ] **Step 2: Check line length around the long final example** + +Run: + +```bash +sed -n '90,135p' website/docs/query-client/setInfiniteQueryData.mdx +``` + +Expected: the final `expect(...)` line is readable. If it is too long for local style, split it as: + +```tsx +expect( + api.pet.findPetsByStatus.getInfiniteQueryData(parameters)?.pages +).toHaveLength(1); +``` + +- [ ] **Step 3: Check the page no longer contains the active-update notice** + +Run: + +```bash +rg -n "Documentation is actively being updated" website/docs/query-client/setInfiniteQueryData.mdx +``` + +Expected: command exits with no matches. + +- [ ] **Step 4: Commit Task 3** + +Run: + +```bash +git add website/docs/query-client/setInfiniteQueryData.mdx +git commit -m "docs: complete setInfiniteQueryData reference" +``` + +Expected: commit succeeds with only `setInfiniteQueryData.mdx` staged. + +## Task 4: Complete `resetQueries` Docs + +**Files:** +- Modify: `website/docs/query-client/resetQueries.mdx` + +- [ ] **Step 1: Replace the placeholder page with complete reference content** + +Replace the whole file with: + +````mdx +--- +sidebar_label: resetQueries() +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# resetQueries(...) + +The method resets matching queries in the `QueryClient` cache and refetches active queries. +It is a strictly-typed wrapper around TanStack +[_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries). + +```ts +await api...resetQueries(filters, options); +``` + +## Arguments + +1. `filters?: QueryFiltersByParameters | QueryFiltersByQueryKey` + - Optional [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters), strictly-typed ✨ + - `filters.parameters: { path, query, header }` filters queries by operation parameters. + - `filters.queryKey: QueryKey` filters queries by an explicit typed query key instead of parameters. + - `filters.parameters` and `filters.queryKey` are mutually exclusive. + - `filters.infinite: boolean` filters regular or infinite query cache entries. + - `filters.predicate?: (query: Query) => boolean` applies custom matching after the typed filter. +2. `options?: ResetOptions` + - Optional TanStack reset options. + - See the TanStack [_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries) documentation for more details. + +## Returns + +`Promise` - Resolves after matching active queries have been reset and refetched. + +## Example + + + + ```tsx + const parameters = { path: { petId: 123 } }; + + api.pet.getPetById.setQueryData(parameters, { + id: 123, + name: 'Rex', + }); + + await api.pet.getPetById.resetQueries({ + parameters, + infinite: false, + }); + ``` + + + ```tsx + const parameters = { path: { petId: 123 } }; + const queryKey = api.pet.getPetById.getQueryKey(parameters); + + await api.pet.getPetById.resetQueries({ + queryKey, + exact: true, + }); + ``` + + + ```tsx + await api.pet.getPetById.resetQueries({ + parameters: { path: { petId: 123 } }, + infinite: false, + predicate: (query) => query.state.status !== 'pending', + }); + ``` + + + ```tsx + await api.pet.getPetById.resetQueries( + { + parameters: { path: { petId: 123 } }, + infinite: false, + }, + { + cancelRefetch: false, + } + ); + ``` + + +```` + +- [ ] **Step 2: Confirm the incorrect hook wording is gone** + +Run: + +```bash +rg -n "Hook|hook" website/docs/query-client/resetQueries.mdx +``` + +Expected: command exits with no matches. + +- [ ] **Step 3: Check the page no longer contains the active-update notice** + +Run: + +```bash +rg -n "Documentation is actively being updated" website/docs/query-client/resetQueries.mdx +``` + +Expected: command exits with no matches. + +- [ ] **Step 4: Commit Task 4** + +Run: + +```bash +git add website/docs/query-client/resetQueries.mdx +git commit -m "docs: complete resetQueries reference" +``` + +Expected: commit succeeds with only `resetQueries.mdx` staged. + +## Task 5: Current Docs Validation + +**Files:** +- Inspect: `website/docs/query-client/getQueryState.mdx` +- Inspect: `website/docs/query-client/getInfiniteQueryState.mdx` +- Inspect: `website/docs/query-client/setInfiniteQueryData.mdx` +- Inspect: `website/docs/query-client/resetQueries.mdx` + +- [ ] **Step 1: Confirm the active-update notice is gone from current docs only** + +Run: + +```bash +rg -n "Documentation is actively being updated" website/docs +``` + +Expected: command exits with no matches. + +Do not run this check against `website/versioned_docs`; versioned docs are intentionally excluded. + +- [ ] **Step 2: Check MDX lint for the website** + +Run: + +```bash +yarn workspace openapi-qraft-website lint +``` + +Expected: PASS. If it fails on pre-existing unrelated files, capture the exact unrelated failures and still run Task 5 Step 3. + +- [ ] **Step 3: Check the Docusaurus build** + +Run: + +```bash +yarn workspace openapi-qraft-website build +``` + +Expected: PASS. If dependencies are unavailable in the worktree, report the missing dependency error and keep the static validation results. + +- [ ] **Step 4: Check whitespace** + +Run: + +```bash +git diff --check +``` + +Expected: no output and exit code 0. + +- [ ] **Step 5: Commit validation-only fixes if needed** + +If Task 5 Step 2, Step 3, or Step 4 required a small docs formatting fix, commit it: + +```bash +git add website/docs/query-client/getQueryState.mdx website/docs/query-client/getInfiniteQueryState.mdx website/docs/query-client/setInfiniteQueryData.mdx website/docs/query-client/resetQueries.mdx +git commit -m "docs: polish query client references" +``` + +Expected: commit succeeds only if there were validation fixes. If no fixes were needed, skip this commit. + +## Self-Review Notes + +- Spec coverage: all four target pages have dedicated tasks; versioned docs exclusion is covered in Task 5 Step 1. +- Placeholder scan: the plan contains no forbidden placeholder tokens or open-ended implementation steps. +- Type consistency: method argument and return descriptions are aligned with `ServiceOperationGetQueryState`, `ServiceOperationSetInfiniteQueryData`, and `ServiceOperationResetQueries`. From 9241833dea6d012fe7b94cc83ab53784b13674f0 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:19:40 +0400 Subject: [PATCH 03/22] docs: complete getQueryState reference --- website/docs/query-client/getQueryState.mdx | 64 +++++++++++++++++++-- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/website/docs/query-client/getQueryState.mdx b/website/docs/query-client/getQueryState.mdx index 82b4ea52c..8f74f8ef8 100644 --- a/website/docs/query-client/getQueryState.mdx +++ b/website/docs/query-client/getQueryState.mdx @@ -2,12 +2,64 @@ sidebar_label: getQueryState() --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # getQueryState(...) -See the TanStack -[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate) -documentation. +The method enables direct access to the `QueryClient` cache state for a specific _Query_. +It is a strictly-typed wrapper around TanStack +[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate). + +```ts +const state = api...getQueryState(parameters); +``` + +## Arguments + +1. `parameters: { path, query, header } | QueryKey | void` + - Operation parameters used to build the _Query Key_, strictly-typed ✨ + - Instead of an object with `{ path, query, header }`, you can pass a typed `QueryKey` array. + - For operations without required parameters, call the method without arguments. + +## Returns + +`QueryState | undefined` - The current cache state for the query, or `undefined` if the query is not in the cache. + +## Example + + + + ```tsx + const parameters = { path: { petId: 123 } }; + + await api.pet.getPetById.fetchQuery(parameters); + + const state = api.pet.getPetById.getQueryState(parameters); + + expect(state?.status).toEqual('success'); + expect(state?.data?.id).toEqual(123); + ``` + + + ```tsx + const parameters = { path: { petId: 123 } }; + const queryKey = api.pet.getPetById.getQueryKey(parameters); + + await api.pet.getPetById.fetchQuery(parameters); + + const state = api.pet.getPetById.getQueryState(queryKey); + + expect(state?.status).toEqual('success'); + ``` + + + ```tsx + await api.pet.findPets.fetchQuery(); + + const state = api.pet.findPets.getQueryState(); -:::info -Documentation is actively being updated 🚧 -::: + expect(state?.status).toEqual('success'); + ``` + + From 8a8e3b413cd554c0209e6209b5b129f2837754ad Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:20:24 +0400 Subject: [PATCH 04/22] docs: complete getInfiniteQueryState reference --- .../query-client/getInfiniteQueryState.mdx | 75 +++++++++++++++++-- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/website/docs/query-client/getInfiniteQueryState.mdx b/website/docs/query-client/getInfiniteQueryState.mdx index 15da1c452..94b6f7618 100644 --- a/website/docs/query-client/getInfiniteQueryState.mdx +++ b/website/docs/query-client/getInfiniteQueryState.mdx @@ -2,13 +2,74 @@ sidebar_label: getInfiniteQueryState() --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # getInfiniteQueryState(...) -The method is the same as the [`getQueryState`](getQueryState.mdx) method, but for infinite queries. -See the TanStack -[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate) -documentation. +The method enables direct access to the `QueryClient` cache state for a specific _Infinite Query_. +It is the infinite-query counterpart to [`getQueryState`](getQueryState.mdx): Qraft still calls TanStack +[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate), +but it builds an infinite query key and returns state for infinite cache data. + +```ts +const state = api...getInfiniteQueryState(parameters); +``` + +## Arguments + +1. `parameters: { path, query, header } | InfiniteQueryKey | void` + - Operation parameters used to build the _Infinite Query Key_, strictly-typed ✨ + - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. + - For operations without required parameters, call the method without arguments. + +## Returns + +`QueryState, TError> | undefined` - The current cache state for the infinite query, or `undefined` if the infinite query is not in the cache. + +## Example + + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + + api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + const state = api.pet.findPetsByStatus.getInfiniteQueryState(parameters); + + expect(state?.data).toEqual({ + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + ``` + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + const queryKey = api.pet.findPetsByStatus.getInfiniteQueryKey(parameters); + + api.pet.findPetsByStatus.setInfiniteQueryData(queryKey, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + const state = api.pet.findPetsByStatus.getInfiniteQueryState(queryKey); -:::info -Documentation is actively being updated 🚧 -::: + expect(state?.status).toEqual('success'); + ``` + + From 22fb0869134e9b2a3c7eddec1daecf3275b776eb Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:21:01 +0400 Subject: [PATCH 05/22] docs: complete setInfiniteQueryData reference --- .../query-client/setInfiniteQueryData.mdx | 109 +++++++++++++++++- 1 file changed, 104 insertions(+), 5 deletions(-) diff --git a/website/docs/query-client/setInfiniteQueryData.mdx b/website/docs/query-client/setInfiniteQueryData.mdx index 0d10d898a..157d0b972 100644 --- a/website/docs/query-client/setInfiniteQueryData.mdx +++ b/website/docs/query-client/setInfiniteQueryData.mdx @@ -2,13 +2,112 @@ sidebar_label: setInfiniteQueryData() --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # setInfiniteQueryData(...) -The method enables direct access to the `QueryClient` cache to set the data for a specific _Infinite Query_. -The method API is the same as the [`setQueryData`](setQueryData.mdx) method, but it is specifically for _Infinite Queries_. +The method enables direct access to the `QueryClient` cache to set data for a specific _Infinite Query_. +It has the same role as [`setQueryData`](setQueryData.mdx), but writes infinite-query data with `pages` and `pageParams`. See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation. -:::info -Documentation is actively being updated 🚧 -::: +```ts +const data = api...setInfiniteQueryData( + parameters, + updater, + options +); +``` + +## Arguments + +1. `parameters: { path, query, header } | InfiniteQueryKey` + - **Required** parameters to set the data in the _Infinite Query Cache_. + - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. +2. `updater: InfiniteData | (oldData: InfiniteData | undefined) => InfiniteData | undefined` + - **Required** updater for the infinite-query cache data. + - If a non-function value is passed, the data will be updated to this value. + - If a function is passed, it receives the old infinite-query data and must return the next value. +3. `options?: SetQueryDataOptions` + - Optional options to set the data in the cache. + - See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation for more details. + +## Returns + +`InfiniteData | undefined` - The data that was written to the cache, or `undefined` if the updater returns `undefined`. + +## Example + + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + + const pets = api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + expect(pets).toEqual({ + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + ``` + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + + api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { + pages: [[]], + pageParams: [parameters], + }); + + const pets = api.pet.findPetsByStatus.setInfiniteQueryData( + parameters, + (oldData) => ({ + pages: [ + ...(oldData?.pages ?? []), + [{ id: 2, name: 'Bella', status: 'available' }], + ], + pageParams: [ + ...(oldData?.pageParams ?? []), + { query: { status: 'available', page: 2 } }, + ], + }) + ); + + expect(pets?.pages.at(-1)).toEqual([ + { id: 2, name: 'Bella', status: 'available' }, + ]); + ``` + + + ```tsx + const parameters = { + query: { status: 'available' }, + }; + const queryKey = api.pet.findPetsByStatus.getInfiniteQueryKey(parameters); + + api.pet.findPetsByStatus.setInfiniteQueryData(queryKey, { + pages: [ + [{ id: 1, name: 'Rex', status: 'available' }], + ], + pageParams: [parameters], + }); + + expect( + api.pet.findPetsByStatus.getInfiniteQueryData(parameters)?.pages + ).toHaveLength(1); + ``` + + From 2704f3910459cea8b4ec7321729bbdf733fa1f34 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:21:31 +0400 Subject: [PATCH 06/22] docs: complete resetQueries reference --- website/docs/query-client/resetQueries.mdx | 85 ++++++++++++++++++++-- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/website/docs/query-client/resetQueries.mdx b/website/docs/query-client/resetQueries.mdx index 3f7612126..7c4586388 100644 --- a/website/docs/query-client/resetQueries.mdx +++ b/website/docs/query-client/resetQueries.mdx @@ -2,12 +2,85 @@ sidebar_label: resetQueries() --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # resetQueries(...) -The function is used to refetch a list of queries by their keys. -The API is the same as [_cancelQueries(...)_](cancelQueries.mdx) Hook. -See also the TanStack [_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries) documentation. +The method resets matching queries in the `QueryClient` cache and refetches active queries. +It is a strictly-typed wrapper around TanStack +[_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries). + +```ts +await api...resetQueries(filters, options); +``` + +## Arguments + +1. `filters?: QueryFiltersByParameters | QueryFiltersByQueryKey` + - Optional [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters), strictly-typed ✨ + - `filters.parameters: { path, query, header }` filters queries by operation parameters. + - `filters.queryKey: QueryKey` filters queries by an explicit typed query key instead of parameters. + - `filters.parameters` and `filters.queryKey` are mutually exclusive. + - `filters.infinite: boolean` filters regular or infinite query cache entries. + - `filters.predicate?: (query: Query) => boolean` applies custom matching after the typed filter. +2. `options?: ResetOptions` + - Optional TanStack reset options. + - See the TanStack [_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries) documentation for more details. + +## Returns + +`Promise` - Resolves after matching active queries have been reset and refetched. + +## Example + + + + ```tsx + const parameters = { path: { petId: 123 } }; + + api.pet.getPetById.setQueryData(parameters, { + id: 123, + name: 'Rex', + }); + + await api.pet.getPetById.resetQueries({ + parameters, + infinite: false, + }); + ``` + + + ```tsx + const parameters = { path: { petId: 123 } }; + const queryKey = api.pet.getPetById.getQueryKey(parameters); -:::info -Documentation is actively being updated 🚧 -::: + await api.pet.getPetById.resetQueries({ + queryKey, + exact: true, + }); + ``` + + + ```tsx + await api.pet.getPetById.resetQueries({ + parameters: { path: { petId: 123 } }, + infinite: false, + predicate: (query) => query.state.status !== 'pending', + }); + ``` + + + ```tsx + await api.pet.getPetById.resetQueries( + { + parameters: { path: { petId: 123 } }, + infinite: false, + }, + { + cancelRefetch: false, + } + ); + ``` + + From 2bcc156af99706e8bcfc768fa02ea990317d9374 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:37:22 +0400 Subject: [PATCH 07/22] docs: add queryable write docs contract design --- ...e-write-operations-docs-contract-design.md | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md diff --git a/docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md b/docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md new file mode 100644 index 000000000..35ac41ee6 --- /dev/null +++ b/docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md @@ -0,0 +1,149 @@ +# Queryable Write Operations Docs Contract Design + +## Context + +Qraft supports `--queryable-write-operations`, which generates query hooks and query-client methods for writable HTTP operations such as `POST`, `PUT`, and `PATCH`. In that mode, request `body` becomes part of the query parameters shape for the query surface: + +```ts +parameters: { path, query, header, body } | QueryKey | void +``` + +This is already covered by runtime tests, generated fixtures, and generated TSDoc examples. The current hand-written documentation under `website/docs` only documents this clearly in parts of `hooks/useQuery.mdx`; many other query hooks, query-client methods, cache helpers, and query filters still describe the parameters as `{ path, query, header }`. + +Versioned documentation under `website/versioned_docs/*` is out of scope and should remain unchanged. + +## Goal + +Make current `website/docs` accurately describe how `body` works for queryable write operations across the query surface. + +The docs should make three facts clear: + +- Queryable write operations can pass `body` inside `parameters` for query hooks and query-client methods. +- `body` participates in query key and cache identity. +- Mutation invoke calls keep `body` as a separate top-level argument and should not be documented as accepting `body` inside `parameters`. + +## Scope + +In scope: + +- Update current docs under `website/docs` only. +- Update query hook docs where parameter shapes or query lists are described: + - `website/docs/hooks/useQuery.mdx` + - `website/docs/hooks/useSuspenseQuery.mdx` + - `website/docs/hooks/useQueries.mdx` + - `website/docs/hooks/useSuspenseQueries.mdx` + - `website/docs/hooks/useInfiniteQuery.mdx` + - `website/docs/hooks/useSuspenseInfiniteQuery.mdx` +- Update query-client docs where query parameters, query keys, cache identity, or query filters are described: + - `fetchQuery`, `fetchInfiniteQuery` + - `ensureQueryData`, `ensureInfiniteQueryData` + - `getQueryKey`, `getInfiniteQueryKey` + - `getQueryData`, `getInfiniteQueryData` + - `getQueryState`, `getInfiniteQueryState` + - `setQueryData`, `setInfiniteQueryData`, `setQueriesData` + - `invalidateQueries`, `refetchQueries`, `cancelQueries`, `removeQueries`, `resetQueries`, `isFetching` +- Add concrete examples that show writable query operations with `body` in `parameters`. +- Keep the previous rule that active current docs are the source of truth, not versioned docs. + +Out of scope: + +- Editing `website/versioned_docs/*`. +- Changing generated code, runtime behavior, type definitions, snapshots, or tests. +- Rewriting mutation docs to use query-style `parameters.body`. +- Broad prose cleanup unrelated to queryable write operation body handling. + +## Contract Wording + +Use one consistent contract across the affected pages: + +```md +For operations generated with `--queryable-write-operations`, query parameters may also include `body`. +In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods. +Mutation calls keep `body` as a separate top-level argument. +``` + +Reference signatures should use one of these shapes when the page describes query-surface parameters: + +```ts +parameters: { path, query, header, body } | QueryKey | void +``` + +```ts +filters.parameters: { path, query, header, body } +``` + +When a page needs to emphasize OpenAPI optionality, use prose rather than spelling `body?` everywhere. The actual generated type decides whether `body` is required or optional for a specific operation. + +## Example Design + +Add examples where they answer a user question directly instead of duplicating the same snippet everywhere. + +### `useQueries` + +Show two writable query entries for the same operation: + +- one entry passes `parameters` with `body`; +- one entry passes a `queryKey` created from parameters with a different `body`; +- the example explains that the two bodies produce different cache entries. + +### `fetchQuery` + +Show a writable operation where `fetchQuery({ parameters: { path, header, body } })` sends the body while still using query caching. + +### `getQueryKey` and Cache Helpers + +Show `getQueryKey(parametersWithBody)` and then reuse the same parameters with `setQueryData` / `getQueryData` or `getQueryState`. The point is to make `body` visible as part of cache identity, not only as transport input. + +## Mutation Boundary + +Mutation pages should not be mechanically changed from: + +```ts +parameters?: { path, query, header } +``` + +to: + +```ts +parameters?: { path, query, header, body } +``` + +For mutation invoke calls, `body` remains top-level: + +```ts +api.approvalPolicies.patchApprovalPoliciesId({ + parameters: { + path: { approval_policy_id: '2' }, + header: { 'x-monite-version': '1' }, + }, + body: { + name: 'New Name', + }, +}); +``` + +If mutation docs are touched, it should only be to add a short clarification that `parameters.body` belongs to queryable write operations, not mutation invoke calls. + +## Validation + +After implementation: + +- Run a scoped search over `website/docs` for stale query-surface wording: + +```bash +rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ path, query, header \\}" website/docs +``` + +- Review remaining matches manually. Matches are allowed when they are mutation-only docs or otherwise intentionally not query-surface. +- Run `yarn workspace openapi-qraft-website lint`. +- Run `yarn workspace openapi-qraft-website build`. +- Run `git diff --check`. + +Do not use `website/versioned_docs/*` as a blocker for this validation. + +## Risks + +- Updating all `{ path, query, header }` text mechanically would incorrectly document mutation invoke calls. +- Using `body?` everywhere can imply all writable query operation bodies are optional. The generated type decides requiredness from OpenAPI. +- Adding too many examples can make reference pages noisy. Prefer one strong body example per workflow family and concise cross-page notes elsewhere. +- Query filters can match by partial parameters, so wording should say `body` can be included in filters for queryable write operations without implying it is always required. From a8de39b52483874a7e132d9c0f1c9e6446100236 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:45:31 +0400 Subject: [PATCH 08/22] docs: add queryable write docs contract plan --- ...ueryable-write-operations-docs-contract.md | 710 ++++++++++++++++++ 1 file changed, 710 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md diff --git a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md new file mode 100644 index 000000000..40fd6df45 --- /dev/null +++ b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md @@ -0,0 +1,710 @@ +# Queryable Write Operations Docs Contract Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Update current `website/docs` so queryable write operations clearly document `body` inside query parameters, query keys, and cache identity. + +**Architecture:** This is a documentation-only pass over current docs. Keep mutation invoke docs separate from query-surface docs, update signatures and short contract notes in place, and add a few high-signal examples instead of duplicating large examples on every page. + +**Tech Stack:** Docusaurus MDX, TanStack Query v5, Qraft generated React client docs, Yarn 4 workspace scripts. + +--- + +## File Structure + +- Modify: `website/docs/hooks/useQuery.mdx` + - Responsibility: keep the existing queryable write section, align its signature with the canonical `body` wording, and avoid implying all bodies are optional. +- Modify: `website/docs/hooks/useSuspenseQuery.mdx` + - Responsibility: mirror `useQuery` parameter wording for Suspense queries. +- Modify: `website/docs/hooks/useInfiniteQuery.mdx` + - Responsibility: mirror queryable write parameter wording for infinite queries. +- Modify: `website/docs/hooks/useSuspenseInfiniteQuery.mdx` + - Responsibility: mirror queryable write parameter wording for Suspense infinite queries. +- Modify: `website/docs/hooks/useQueries.mdx` + - Responsibility: document `parameters.body` in query lists and add a concrete multi-query body example. +- Modify: `website/docs/hooks/useSuspenseQueries.mdx` + - Responsibility: document `parameters.body` in Suspense query lists and link the cache identity concept to `useQueries`. +- Modify: `website/docs/query-client/fetchQuery.mdx` + - Responsibility: document body-bearing query parameters for direct fetching and add a concrete writable query example. +- Modify: `website/docs/query-client/fetchInfiniteQuery.mdx` + - Responsibility: document body-bearing query parameters for infinite fetching. +- Modify: `website/docs/query-client/ensureQueryData.mdx` + - Responsibility: mirror `fetchQuery` parameter wording because it uses the same query identity contract. +- Modify: `website/docs/query-client/ensureInfiniteQueryData.mdx` + - Responsibility: mirror `fetchInfiniteQuery` parameter wording. +- Modify: `website/docs/query-client/getQueryKey.mdx` + - Responsibility: document `body` as part of normal query key identity and add a concrete queryable write example. +- Modify: `website/docs/query-client/getInfiniteQueryKey.mdx` + - Responsibility: document `body` as part of infinite query key identity. +- Modify: `website/docs/query-client/getQueryData.mdx` + - Responsibility: document `body` in cache lookup parameters. +- Modify: `website/docs/query-client/getInfiniteQueryData.mdx` + - Responsibility: document `body` in infinite cache lookup parameters. +- Modify: `website/docs/query-client/getQueryState.mdx` + - Responsibility: document `body` in query state lookup parameters. +- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` + - Responsibility: document `body` in infinite query state lookup parameters. +- Modify: `website/docs/query-client/setQueryData.mdx` + - Responsibility: document `body` in normal cache write parameters and show cache identity with body. +- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` + - Responsibility: document `body` in infinite cache write parameters. +- Modify: `website/docs/query-client/setQueriesData.mdx` + - Responsibility: document `body` in query filter parameters for cache writes. +- Modify: `website/docs/query-client/invalidateQueries.mdx` + - Responsibility: document `body` in query filter parameters. +- Modify: `website/docs/query-client/refetchQueries.mdx` + - Responsibility: document `body` in query filter parameters. +- Modify: `website/docs/query-client/cancelQueries.mdx` + - Responsibility: document `body` in query filter parameters. +- Modify: `website/docs/query-client/removeQueries.mdx` + - Responsibility: document `body` in query filter parameters. +- Modify: `website/docs/query-client/resetQueries.mdx` + - Responsibility: document `body` in query filter parameters. +- Modify: `website/docs/query-client/isFetching.mdx` + - Responsibility: document `body` in query filter parameters. +- Do not modify: `website/versioned_docs/*` + - Responsibility: historical docs are intentionally excluded from this pass. +- Do not modify mutation invoke pages unless a short boundary note is needed: + - `website/docs/hooks/useMutation.mdx` + - `website/docs/core/mutation-operation.mdx` + - Mutation invoke calls keep `body` as a top-level argument. + +## Shared Text Snippets + +Use these exact snippets when updating pages. Keep them short and repeat them inline; do not add a new MDX partial unless implementation discovers an existing docs convention for shared snippets. + +### Query Parameter Contract + +```md +For operations generated with `--queryable-write-operations`, query parameters may also include `body`. +In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods. +Mutation calls keep `body` as a separate top-level argument. +``` + +### Query Parameter Signature + +```md +`parameters: { path, query, header, body } | QueryKey | void` +``` + +### Infinite Query Parameter Signature + +```md +`parameters: { path, query, header, body } | InfiniteQueryKey | void` +``` + +### Query Filter Parameter Text + +```md +- `filters.parameters: { path, query, header, body }` filters queries by operation parameters. +- For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. +``` + +## Task 1: Align Single Query Hook Parameter Contracts + +**Files:** +- Modify: `website/docs/hooks/useQuery.mdx` +- Modify: `website/docs/hooks/useSuspenseQuery.mdx` +- Modify: `website/docs/hooks/useInfiniteQuery.mdx` +- Modify: `website/docs/hooks/useSuspenseInfiniteQuery.mdx` + +- [ ] **Step 1: Update `useQuery` argument wording** + +In `website/docs/hooks/useQuery.mdx`, replace the current first argument block with: + +```md +1. `parameters: { path, query, header, body } | QueryKey | void` + - **Required only if OpenAPI specification defines required parameters** + - If the operation has no required parameters according to OpenAPI, you can omit this argument + - `parameters` will be used to generate the `QueryKey` + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods + - Mutation calls keep `body` as a separate top-level argument + - Instead of an object with `{ path, query, header, body }`, you can pass a `QueryKey` as an array + which is also strictly-typed +``` + +- [ ] **Step 2: Update `useSuspenseQuery` argument wording** + +In `website/docs/hooks/useSuspenseQuery.mdx`, replace the current first argument block with: + +```md +1. `parameters: { path, query, header, body } | QueryKey | void` + - **Required only if OpenAPI specification defines required parameters** + - If the operation has no required parameters according to OpenAPI, you can omit this argument + - `parameters` will be used to generate the `QueryKey` + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods + - Mutation calls keep `body` as a separate top-level argument + - Instead of an object with `{ path, query, header, body }`, you can pass a `QueryKey` as an array + which is also strictly-typed ✨ +``` + +- [ ] **Step 3: Update infinite hook argument wording** + +In both `website/docs/hooks/useInfiniteQuery.mdx` and `website/docs/hooks/useSuspenseInfiniteQuery.mdx`, replace the current first argument block with: + +```md +1. `parameters: { path, query, header, body } | QueryKey | undefined` + - **Required only if OpenAPI specification defines required parameters** + - If the operation has no required parameters according to OpenAPI, you can omit this argument + - `parameters` will be used to generate the _Infinite Query Key_ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the infinite query key and cache identity + - Mutation calls keep `body` as a separate top-level argument + - Instead of an object with `{ path, query, header, body }`, you can pass an infinite `QueryKey` as an array + which is also strictly-typed ✨ +``` + +- [ ] **Step 4: Run a focused grep for old hook wording** + +Run: + +```bash +rg -n "\\{path, query, header\\}|\\{ path, query, header \\}" website/docs/hooks/useQuery.mdx website/docs/hooks/useSuspenseQuery.mdx website/docs/hooks/useInfiniteQuery.mdx website/docs/hooks/useSuspenseInfiniteQuery.mdx +``` + +Expected: no matches for the four files in this task. + +- [ ] **Step 5: Commit Task 1** + +Run: + +```bash +git add website/docs/hooks/useQuery.mdx website/docs/hooks/useSuspenseQuery.mdx website/docs/hooks/useInfiniteQuery.mdx website/docs/hooks/useSuspenseInfiniteQuery.mdx +git commit -m "docs: clarify queryable write hook parameters" +``` + +Expected: commit succeeds with only the four hook docs staged. + +## Task 2: Document Body-Aware Multi-Query Hooks + +**Files:** +- Modify: `website/docs/hooks/useQueries.mdx` +- Modify: `website/docs/hooks/useSuspenseQueries.mdx` + +- [ ] **Step 1: Add tab imports to `useQueries`** + +In `website/docs/hooks/useQueries.mdx`, add these imports after the frontmatter and before `# useQueries(...)`: + +```mdx +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +``` + +- [ ] **Step 2: Update `useQueries` query list wording** + +In `website/docs/hooks/useQueries.mdx`, replace the `options.queries` sub-bullets with: + +```md + - `options.queries: QueryOptions[]` + - **Required** array of _Queries_ to be executed + - `parameters: { path, query, header, body }` will be used for the request + - For operations generated with `--queryable-write-operations`, `body` is part of the query key and cache identity + - `queryKey: QueryKey` will be used for the request instead of the `parameters` + - `queryKey` and `parameters` are mutually exclusive +``` + +- [ ] **Step 3: Add a writable operation tab to `useQueries`** + +Replace the single `### Example` code block in `website/docs/hooks/useQueries.mdx` with a `Tabs` block. Keep the existing GET example as the first tab and add this second tab: + +````mdx + + + ```tsx + import { createAPIClient } from './api'; // generated by OpenAPI Qraft + + import { requestFn } from '@openapi-qraft/react'; + import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + + const queryClient = new QueryClient(); + + const api = createAPIClient({ + requestFn, + queryClient, + baseUrl: 'https://api.sandbox.monite.com/v1', + }); + + const useEntityQueries = () => { + return api.entities.getEntities.useQueries({ + queries: [ + { + parameters: { + header: { 'x-monite-version': '2023-09-01' }, + path: { entity_id: '3e3e-3e3e-3e3e' }, + }, + }, + { + parameters: { + header: { 'x-monite-version': '2023-09-01' }, + path: { entity_id: '5c5c-5c5c-5c5c' }, + }, + }, + ], + combine: (results) => results.map((result) => result.data), + }); + }; + ``` + + With body}> + ```tsx + const firstSearch = { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }; + + const secondSearch = { + ...firstSearch, + body: { + name: 'Another Name', + description: 'Another Description', + }, + }; + + const secondSearchKey = + api.approvalPolicies.patchApprovalPoliciesId.getQueryKey(secondSearch); + + const results = api.approvalPolicies.patchApprovalPoliciesId.useQueries({ + queries: [ + { parameters: firstSearch }, + { queryKey: secondSearchKey }, + ], + }); + + // `firstSearch.body` and `secondSearch.body` produce different cache entries. + ``` + + +```` + +- [ ] **Step 4: Update `useSuspenseQueries` query list wording** + +In `website/docs/hooks/useSuspenseQueries.mdx`, replace the `options.queries` sub-bullets with: + +```md + - `options.queries: QueryOptions[]` + - **Required** array of _Queries_ to be executed + - `parameters: { path, query, header, body }` will be used for the request + - For operations generated with `--queryable-write-operations`, `body` is part of the query key and cache identity + - `queryKey: QueryKey` will be used for the request instead of the `parameters` + - `queryKey` and `parameters` are mutually exclusive +``` + +- [ ] **Step 5: Add a short body example note to `useSuspenseQueries`** + +After the existing example in `website/docs/hooks/useSuspenseQueries.mdx`, add: + +````mdx +### Queryable Write Operations + +For operations generated with `--queryable-write-operations`, `useSuspenseQueries` accepts the same `parameters.body` +shape as `useQueries`. Each distinct body is part of the query key and creates a distinct cache entry. + +```tsx +const queryKey = + api.approvalPolicies.patchApprovalPoliciesId.getQueryKey({ + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { name: 'Another Name' }, + }); + +const results = api.approvalPolicies.patchApprovalPoliciesId.useSuspenseQueries({ + queries: [ + { + parameters: { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { name: 'New Name' }, + }, + }, + { queryKey }, + ], +}); +``` +```` + +- [ ] **Step 6: Run focused grep** + +Run: + +```bash +rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ path, query, header \\}" website/docs/hooks/useQueries.mdx website/docs/hooks/useSuspenseQueries.mdx +``` + +Expected: no matches. + +- [ ] **Step 7: Commit Task 2** + +Run: + +```bash +git add website/docs/hooks/useQueries.mdx website/docs/hooks/useSuspenseQueries.mdx +git commit -m "docs: show body in multi-query hooks" +``` + +Expected: commit succeeds with only the two multi-query docs staged. + +## Task 3: Align Fetch and Ensure Query-Client Methods + +**Files:** +- Modify: `website/docs/query-client/fetchQuery.mdx` +- Modify: `website/docs/query-client/fetchInfiniteQuery.mdx` +- Modify: `website/docs/query-client/ensureQueryData.mdx` +- Modify: `website/docs/query-client/ensureInfiniteQueryData.mdx` + +- [ ] **Step 1: Update normal fetch argument blocks** + +In both `fetchQuery.mdx` and `ensureQueryData.mdx`, replace the first `parameters` bullet with: + +```md +1. - `parameters: { path, query, header, body } | QueryKey | void` + - **Required**, OpenAPI request parameters for the query, strictly-typed ✨ + - `parameters` will be used to generate the `QueryKey` + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the query key and cache identity for query-client methods + - Mutation calls keep `body` as a separate top-level argument +``` + +Keep the existing `requestFn`, `baseUrl`, and options bullets after this block. + +- [ ] **Step 2: Add a writable `fetchQuery` example tab** + +In `website/docs/query-client/fetchQuery.mdx`, add this tab after the existing basic tab: + +````mdx + With body}> + ```ts + const policy = await api.approvalPolicies.patchApprovalPoliciesId.fetchQuery({ + parameters: { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }, + }); + ``` + +```` + +- [ ] **Step 3: Update infinite fetch argument blocks** + +In both `fetchInfiniteQuery.mdx` and `ensureInfiniteQueryData.mdx`, replace the first `parameters` bullet with: + +```md +1. - `parameters: { path, query, header, body } | QueryKey | void` + - OpenAPI request parameters for the query, strictly-typed ✨ + - `parameters` will be used to generate the _Infinite Query Key_ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the infinite query key and cache identity + - Mutation calls keep `body` as a separate top-level argument +``` + +Keep the existing fetch options bullets after this block. + +- [ ] **Step 4: Run focused grep** + +Run: + +```bash +rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query-client/fetchQuery.mdx website/docs/query-client/fetchInfiniteQuery.mdx website/docs/query-client/ensureQueryData.mdx website/docs/query-client/ensureInfiniteQueryData.mdx +``` + +Expected: no matches. + +- [ ] **Step 5: Commit Task 3** + +Run: + +```bash +git add website/docs/query-client/fetchQuery.mdx website/docs/query-client/fetchInfiniteQuery.mdx website/docs/query-client/ensureQueryData.mdx website/docs/query-client/ensureInfiniteQueryData.mdx +git commit -m "docs: clarify body in query fetching methods" +``` + +Expected: commit succeeds with only the four fetch and ensure docs staged. + +## Task 4: Align Query Key, Data, State, and Cache Write Methods + +**Files:** +- Modify: `website/docs/query-client/getQueryKey.mdx` +- Modify: `website/docs/query-client/getInfiniteQueryKey.mdx` +- Modify: `website/docs/query-client/getQueryData.mdx` +- Modify: `website/docs/query-client/getInfiniteQueryData.mdx` +- Modify: `website/docs/query-client/getQueryState.mdx` +- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` +- Modify: `website/docs/query-client/setQueryData.mdx` +- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` + +- [ ] **Step 1: Update normal query key/data/state signatures** + +In `getQueryKey.mdx`, `getQueryData.mdx`, `getQueryState.mdx`, and `setQueryData.mdx`, replace normal query parameter signatures and nearby QueryKey prose with: + +```md +`parameters: { path, query, header, body } | QueryKey | void` + +For operations generated with `--queryable-write-operations`, query parameters may also include `body`. +In that mode, `body` is part of the query key and cache identity for query-client methods. +Instead of an object with `{ path, query, header, body }`, you can pass a typed `QueryKey` array. +``` + +Use `| QueryKey` without `| void` in `setQueryData.mdx` if the existing method signature does not accept `void`. + +- [ ] **Step 2: Add a body cache identity example to `getQueryKey`** + +Add this tab to `website/docs/query-client/getQueryKey.mdx`: + +````mdx + With body}> + ```tsx + const queryKey = + api.approvalPolicies.patchApprovalPoliciesId.getQueryKey({ + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }); + + expect(queryKey[1]).toEqual({ + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }); + ``` + +```` + +- [ ] **Step 3: Add a body cache write/read example to `setQueryData`** + +Add this tab to `website/docs/query-client/setQueryData.mdx`: + +````mdx + With body}> + ```tsx + const parameters = { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }; + + api.approvalPolicies.patchApprovalPoliciesId.setQueryData(parameters, { + id: '2', + name: 'New Name', + description: 'New Description', + }); + + const policy = + api.approvalPolicies.patchApprovalPoliciesId.getQueryData(parameters); + + expect(policy?.name).toEqual('New Name'); + ``` + +```` + +- [ ] **Step 4: Update infinite key/data/state/cache signatures** + +In `getInfiniteQueryKey.mdx`, `getInfiniteQueryData.mdx`, `getInfiniteQueryState.mdx`, and `setInfiniteQueryData.mdx`, replace infinite query parameter signatures and nearby query key prose with: + +```md +`parameters: { path, query, header, body } | InfiniteQueryKey | void` + +For operations generated with `--queryable-write-operations`, query parameters may also include `body`. +In that mode, `body` is part of the infinite query key and cache identity. +Instead of an object with `{ path, query, header, body }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. +``` + +Use `| InfiniteQueryKey` without `| void` in `setInfiniteQueryData.mdx` if the existing method signature does not accept `void`. + +- [ ] **Step 5: Run focused grep** + +Run: + +```bash +rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query-client/getQueryKey.mdx website/docs/query-client/getInfiniteQueryKey.mdx website/docs/query-client/getQueryData.mdx website/docs/query-client/getInfiniteQueryData.mdx website/docs/query-client/getQueryState.mdx website/docs/query-client/getInfiniteQueryState.mdx website/docs/query-client/setQueryData.mdx website/docs/query-client/setInfiniteQueryData.mdx +``` + +Expected: no stale matches. If an example intentionally shows mutation invoke arguments, keep it and note it in the task summary. + +- [ ] **Step 6: Commit Task 4** + +Run: + +```bash +git add website/docs/query-client/getQueryKey.mdx website/docs/query-client/getInfiniteQueryKey.mdx website/docs/query-client/getQueryData.mdx website/docs/query-client/getInfiniteQueryData.mdx website/docs/query-client/getQueryState.mdx website/docs/query-client/getInfiniteQueryState.mdx website/docs/query-client/setQueryData.mdx website/docs/query-client/setInfiniteQueryData.mdx +git commit -m "docs: clarify body in query cache identity" +``` + +Expected: commit succeeds with only the eight query key/cache docs staged. + +## Task 5: Align Query Filter Pages + +**Files:** +- Modify: `website/docs/query-client/setQueriesData.mdx` +- Modify: `website/docs/query-client/invalidateQueries.mdx` +- Modify: `website/docs/query-client/refetchQueries.mdx` +- Modify: `website/docs/query-client/cancelQueries.mdx` +- Modify: `website/docs/query-client/removeQueries.mdx` +- Modify: `website/docs/query-client/resetQueries.mdx` +- Modify: `website/docs/query-client/isFetching.mdx` + +- [ ] **Step 1: Update filter parameter bullets across filter pages** + +In each file listed for this task, replace every query filter parameter bullet that currently says: + +```md +- `filters.parameters: { path, query, header }` will be used for filtering queries by parameters +``` + +or: + +```md +- `filters.parameters: { path, query, header }` filters queries by operation parameters. +``` + +with: + +```md +- `filters.parameters: { path, query, header, body }` filters queries by operation parameters. +- For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. +``` + +- [ ] **Step 2: Update setQueriesData QueryKey prose** + +In `website/docs/query-client/setQueriesData.mdx`, replace: + +```md +It's also possible to use a `QueryKey` as an array instead of an object with `{path, query, header}`: +``` + +with: + +```md +It's also possible to use a `QueryKey` as an array instead of an object with `{ path, query, header, body }`: +``` + +- [ ] **Step 3: Add one filter example with body** + +Add this short example after the first filter example in `website/docs/query-client/isFetching.mdx`: + +````mdx + For queryable write operations, `body` can be part of the filter parameters: + + ```ts + const matchingPolicySearches = + api.approvalPolicies.patchApprovalPoliciesId.isFetching({ + infinite: false, + parameters: { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { name: 'New Name' }, + }, + }); + ``` +```` + +- [ ] **Step 4: Run focused grep** + +Run: + +```bash +rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query-client/setQueriesData.mdx website/docs/query-client/invalidateQueries.mdx website/docs/query-client/refetchQueries.mdx website/docs/query-client/cancelQueries.mdx website/docs/query-client/removeQueries.mdx website/docs/query-client/resetQueries.mdx website/docs/query-client/isFetching.mdx +``` + +Expected: no stale query-filter matches. + +- [ ] **Step 5: Commit Task 5** + +Run: + +```bash +git add website/docs/query-client/setQueriesData.mdx website/docs/query-client/invalidateQueries.mdx website/docs/query-client/refetchQueries.mdx website/docs/query-client/cancelQueries.mdx website/docs/query-client/removeQueries.mdx website/docs/query-client/resetQueries.mdx website/docs/query-client/isFetching.mdx +git commit -m "docs: clarify body in query filters" +``` + +Expected: commit succeeds with only the seven filter docs staged. + +## Task 6: Boundary Review and Validation + +**Files:** +- Inspect: `website/docs` +- Do not inspect as blockers: `website/versioned_docs/*` + +- [ ] **Step 1: Run scoped stale wording search** + +Run: + +```bash +rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ path, query, header \\}" website/docs +``` + +Expected: remaining matches are only mutation-specific docs or intentionally unchanged mutation examples. Record the allowed files in the final summary. Query-surface matches should be fixed before continuing. + +- [ ] **Step 2: Check mutation boundary wording** + +Run: + +```bash +rg -n "body.*separate top-level|Mutation calls keep `body`|parameters\\.body" website/docs/hooks website/docs/query-client website/docs/core +``` + +Expected: query-surface pages explain `parameters.body`; mutation-boundary notes say mutation calls keep `body` top-level. There should be no mutation page claiming `parameters.body` for invoke calls. + +- [ ] **Step 3: Run website lint** + +Run: + +```bash +yarn workspace openapi-qraft-website lint +``` + +Expected: PASS. + +- [ ] **Step 4: Run website build** + +Run: + +```bash +yarn workspace openapi-qraft-website build +``` + +Expected: PASS. + +- [ ] **Step 5: Check whitespace** + +Run: + +```bash +git diff --check +``` + +Expected: no output and exit code 0. + +- [ ] **Step 6: Commit validation fixes if needed** + +If validation required small formatting or wording fixes, commit them: + +```bash +git add website/docs +git commit -m "docs: polish queryable write operation wording" +``` + +Expected: commit succeeds only if validation fixes were made. If no fixes were needed, skip this commit. + +## Self-Review Notes + +- Spec coverage: hooks, multi-query hooks, fetch/ensure methods, query key/cache helpers, query filters, mutation boundary, current-docs-only validation, and versioned docs exclusion are all represented. +- Placeholder scan: the plan contains no forbidden placeholder tokens or open-ended implementation steps. +- Type consistency: query surfaces use `parameters.body`; mutation invoke boundary keeps top-level `body`; infinite query surfaces use infinite query key wording. From fbf4fb416e6571940b8e15739ef9547894db02df Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:48:57 +0400 Subject: [PATCH 09/22] docs: clarify query key example in plan --- ...-21-queryable-write-operations-docs-contract.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md index 40fd6df45..0fcedb5e5 100644 --- a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md +++ b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md @@ -258,7 +258,7 @@ Replace the single `### Example` code block in `website/docs/hooks/useQueries.md }, }; - const secondSearch = { + const secondSearchParameters = { ...firstSearch, body: { name: 'Another Name', @@ -266,17 +266,21 @@ Replace the single `### Example` code block in `website/docs/hooks/useQueries.md }, }; - const secondSearchKey = - api.approvalPolicies.patchApprovalPoliciesId.getQueryKey(secondSearch); + const secondSearchQueryKey = + api.approvalPolicies.patchApprovalPoliciesId.getQueryKey( + secondSearchParameters + ); const results = api.approvalPolicies.patchApprovalPoliciesId.useQueries({ queries: [ { parameters: firstSearch }, - { queryKey: secondSearchKey }, + { queryKey: secondSearchQueryKey }, ], }); - // `firstSearch.body` and `secondSearch.body` produce different cache entries. + // Never pass `secondSearchParameters` as `queryKey` directly. + // `getQueryKey(...)` builds the tuple shape TanStack Query expects. + // `firstSearch.body` and `secondSearchParameters.body` produce different cache entries. ``` From 3819dbb1e2f0f6be493cb94325298ae16fbc0952 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:54:06 +0400 Subject: [PATCH 10/22] docs: clarify queryable write hook parameters --- website/docs/hooks/useInfiniteQuery.mdx | 10 ++++++---- website/docs/hooks/useQuery.mdx | 6 ++++-- website/docs/hooks/useSuspenseInfiniteQuery.mdx | 10 ++++++---- website/docs/hooks/useSuspenseQuery.mdx | 8 +++++--- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/website/docs/hooks/useInfiniteQuery.mdx b/website/docs/hooks/useInfiniteQuery.mdx index 04908ed30..01cee8d78 100644 --- a/website/docs/hooks/useInfiniteQuery.mdx +++ b/website/docs/hooks/useInfiniteQuery.mdx @@ -20,13 +20,15 @@ const query = api...useInfiniteQuery( ### Arguments -1. `parameters: { path, query, header } | QueryKey | undefined` +1. `parameters: { path, query, header, body } | QueryKey | undefined` - **Required only if OpenAPI specification defines required parameters** - If the operation has no required parameters according to OpenAPI, you can omit this argument - - `parameters` will be used to generate the `QueryKey` - - Instead of an object with `{path, query, header}`, you can pass a `QueryKey` as an array + - `parameters` will be used to generate the _Infinite Query Key_ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the infinite query key and cache identity + - Mutation calls keep `body` as a separate top-level argument + - Instead of an object with `{ path, query, header, body }`, you can pass an infinite `QueryKey` as an array which is also strictly-typed ✨ - - If operation does not require parameters, you must pass an empty object `{}` for strictness 2. `infiniteQueryOptions?: UseInfiniteQueryOptions` - **Optional**, represents the options of the [_useInfiniteQuery(...) 🌴_](https://tanstack.com/query/latest/docs/framework/react/reference/useInfiniteQuery) Hook diff --git a/website/docs/hooks/useQuery.mdx b/website/docs/hooks/useQuery.mdx index b3b840419..b5302b968 100644 --- a/website/docs/hooks/useQuery.mdx +++ b/website/docs/hooks/useQuery.mdx @@ -27,11 +27,13 @@ const query = api...useQuery( ### Arguments -1. `parameters: { path, query, header, body? } | QueryKey | void` +1. `parameters: { path, query, header, body } | QueryKey | void` - **Required only if OpenAPI specification defines required parameters** - If the operation has no required parameters according to OpenAPI, you can omit this argument - `parameters` will be used to generate the `QueryKey` - - For write operations (when using `--queryable-write-operations`), you can include a `body` parameter + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods + - Mutation calls keep `body` as a separate top-level argument - Instead of an object with `{ path, query, header, body }`, you can pass a `QueryKey` as an array which is also strictly-typed diff --git a/website/docs/hooks/useSuspenseInfiniteQuery.mdx b/website/docs/hooks/useSuspenseInfiniteQuery.mdx index 5678c2588..2d2a882e3 100644 --- a/website/docs/hooks/useSuspenseInfiniteQuery.mdx +++ b/website/docs/hooks/useSuspenseInfiniteQuery.mdx @@ -18,13 +18,15 @@ const query = api...useSuspenseInfiniteQuery( ### Arguments -1. `parameters: { path, query, header } | QueryKey | undefined` +1. `parameters: { path, query, header, body } | QueryKey | undefined` - **Required only if OpenAPI specification defines required parameters** - If the operation has no required parameters according to OpenAPI, you can omit this argument - - `parameters` will be used to generate the `QueryKey` - - Instead of an object with `{path, query, header}`, you can pass a `QueryKey` as an array + - `parameters` will be used to generate the _Infinite Query Key_ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the infinite query key and cache identity + - Mutation calls keep `body` as a separate top-level argument + - Instead of an object with `{ path, query, header, body }`, you can pass an infinite `QueryKey` as an array which is also strictly-typed ✨ - - If operation does not require parameters, you must pass an empty object `{}` for strictness 2. `suspenseInfiniteQueryOptions?: UseSuspenseInfiniteQueryOptions` - **Optional**, represents the options of the diff --git a/website/docs/hooks/useSuspenseQuery.mdx b/website/docs/hooks/useSuspenseQuery.mdx index 2297e3afa..2955a581d 100644 --- a/website/docs/hooks/useSuspenseQuery.mdx +++ b/website/docs/hooks/useSuspenseQuery.mdx @@ -20,13 +20,15 @@ const result = api...useSuspenseQuery( ### Arguments -1. `parameters: { path, query, header } | QueryKey | void` +1. `parameters: { path, query, header, body } | QueryKey | void` - **Required only if OpenAPI specification defines required parameters** - If the operation has no required parameters according to OpenAPI, you can omit this argument - `parameters` will be used to generate the `QueryKey` - - Instead of an object with `{path, query, header}`, you can pass a `QueryKey` as an array + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods + - Mutation calls keep `body` as a separate top-level argument + - Instead of an object with `{ path, query, header, body }`, you can pass a `QueryKey` as an array which is also strictly-typed ✨ - - If operation does not require parameters, you must pass an empty object `{}` for strictness 2. `queryOptions?: UseQueryOptions` - **Optional**, represents the options of the [_useSuspenseQuery(...) 🌴_](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseQuery) Hook From 7f402e45dde3e66f3d63a450a1c66b0a29d2e66e Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Thu, 21 May 2026 23:58:53 +0400 Subject: [PATCH 11/22] docs: show body in multi-query hooks --- website/docs/hooks/useQueries.mdx | 123 +++++++++++++--------- website/docs/hooks/useSuspenseQueries.mdx | 30 +++++- 2 files changed, 104 insertions(+), 49 deletions(-) diff --git a/website/docs/hooks/useQueries.mdx b/website/docs/hooks/useQueries.mdx index 782d88bbe..49fe32b07 100644 --- a/website/docs/hooks/useQueries.mdx +++ b/website/docs/hooks/useQueries.mdx @@ -2,6 +2,9 @@ sidebar_label: useQueries() --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + # useQueries(...) The Hook enables you to concurrently execute multiple asynchronous data fetching operations. @@ -20,7 +23,8 @@ const queries = api...useQueries( - **Required**, represents the options for queries, see [_useQueries(...) 🌴_](https://tanstack.com/query/latest/docs/framework/react/reference/useQueries) documentation - `options.queries: QueryOptions[]` - **Required** array of _Queries_ to be executed - - `parameters: { path, query, header }` will be used for the request + - `parameters: { path, query, header, body }` will be used for the request + - For operations generated with `--queryable-write-operations`, `body` is part of the query key and cache identity - `queryKey: QueryKey` will be used for the request instead of the `parameters` - `queryKey` and `parameters` are mutually exclusive - `options.combine?: (result: UseQueriesResults) => TCombinedResult` @@ -37,54 +41,77 @@ during code generation. ### Example -```tsx -import { createAPIClient } from './api'; // generated by OpenAPI Qraft - -import { requestFn } from '@openapi-qraft/react'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - -const queryClient = new QueryClient(); - -const api = createAPIClient({ - requestFn, - queryClient, - baseUrl: 'https://api.sandbox.monite.com/v1', -}); - -const useEntityQueries = () => { - /** - * Initiates two concurrent GET requests: - * ### - * GET /entities/3e3e-3e3e-3e3e - * x-monite-version: 2023-09-01 - * ### - * GET /entities/5c5c-5c5c-5c5c - * x-monite-version: 2023-09-01 - **/ - return api.entities.getEntities.useQueries({ - queries: [ - { - parameters: { - header: { - 'x-monite-version': '2023-09-01', + + + ```tsx + import { createAPIClient } from './api'; // generated by OpenAPI Qraft + + import { requestFn } from '@openapi-qraft/react'; + import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + + const queryClient = new QueryClient(); + + const api = createAPIClient({ + requestFn, + queryClient, + baseUrl: 'https://api.sandbox.monite.com/v1', + }); + + const useEntityQueries = () => { + return api.entities.getEntities.useQueries({ + queries: [ + { + parameters: { + header: { 'x-monite-version': '2023-09-01' }, + path: { entity_id: '3e3e-3e3e-3e3e' }, + }, }, - path: { - entity_id: '3e3e-3e3e-3e3e', + { + parameters: { + header: { 'x-monite-version': '2023-09-01' }, + path: { entity_id: '5c5c-5c5c-5c5c' }, + }, }, - }, + ], + combine: (results) => results.map((result) => result.data), + }); + }; + ``` + + With body}> + ```tsx + const firstSearch = { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', }, - { - parameters: { - header: { - 'x-monite-version': '2023-09-01', - }, - path: { - entity_id: '5c5c-5c5c-5c5c', - }, - }, + }; + + const secondSearchParameters = { + ...firstSearch, + body: { + name: 'Another Name', + description: 'Another Description', }, - ], - combine: (results) => results.map((result) => result.data), - }); -} -``` + }; + + const secondSearchQueryKey = + api.approvalPolicies.patchApprovalPoliciesId.getQueryKey( + secondSearchParameters + ); + + const results = api.approvalPolicies.patchApprovalPoliciesId.useQueries({ + queries: [ + { parameters: firstSearch }, + { queryKey: secondSearchQueryKey }, + ], + }); + + // Never pass `secondSearchParameters` as `queryKey` directly. + // `getQueryKey(...)` builds the tuple shape TanStack Query expects. + // `firstSearch.body` and `secondSearchParameters.body` produce different cache entries. + ``` + + diff --git a/website/docs/hooks/useSuspenseQueries.mdx b/website/docs/hooks/useSuspenseQueries.mdx index 6aa2bcbf7..567018e8d 100644 --- a/website/docs/hooks/useSuspenseQueries.mdx +++ b/website/docs/hooks/useSuspenseQueries.mdx @@ -23,7 +23,8 @@ const result = api...useSuspenseQueries( - **Required**, represents the options for queries, see [_useSuspenseQueries(...) 🌴_](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseQueries) documentation - `options.queries: QueryOptions[]` - **Required** array of _Queries_ to be executed - - `parameters: { path, query, header }` will be used for the request + - `parameters: { path, query, header, body }` will be used for the request + - For operations generated with `--queryable-write-operations`, `body` is part of the query key and cache identity - `queryKey: QueryKey` will be used for the request instead of the `parameters` - `queryKey` and `parameters` are mutually exclusive - `options.combine?: (result: UseQueriesResults) => TCombinedResult` @@ -109,3 +110,30 @@ export default function() { ) } ``` + +### Queryable Write Operations + +For operations generated with `--queryable-write-operations`, `useSuspenseQueries` accepts the same `parameters.body` +shape as `useQueries`. Each distinct body is part of the query key and creates a distinct cache entry. + +```tsx +const queryKey = + api.approvalPolicies.patchApprovalPoliciesId.getQueryKey({ + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { name: 'Another Name' }, + }); + +const results = api.approvalPolicies.patchApprovalPoliciesId.useSuspenseQueries({ + queries: [ + { + parameters: { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { name: 'New Name' }, + }, + }, + { queryKey }, + ], +}); +``` From 75b0acafabebc4c073f81a5a57d557c5359dfead Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 00:04:16 +0400 Subject: [PATCH 12/22] docs: clarify body in query fetching methods --- .../query-client/ensureInfiniteQueryData.mdx | 7 +++++-- website/docs/query-client/ensureQueryData.mdx | 5 ++++- .../docs/query-client/fetchInfiniteQuery.mdx | 7 +++++-- website/docs/query-client/fetchQuery.mdx | 19 ++++++++++++++++++- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/website/docs/query-client/ensureInfiniteQueryData.mdx b/website/docs/query-client/ensureInfiniteQueryData.mdx index 8efd6df53..40517c4a5 100644 --- a/website/docs/query-client/ensureInfiniteQueryData.mdx +++ b/website/docs/query-client/ensureInfiniteQueryData.mdx @@ -22,9 +22,12 @@ const result = api...ensureInfiniteQueryData({ ``` ### Arguments -1. - `parameters: { path, query, header } | QueryKey | void` +1. - `parameters: { path, query, header, body } | QueryKey | void` - OpenAPI request parameters for the query, strictly-typed ✨ - - `parameters` will be used to generate the `QueryKey` + - `parameters` will be used to generate the _Infinite Query Key_ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the infinite query key and cache identity + - Mutation calls keep `body` as a separate top-level argument - `fetchInfiniteQueryOptions?: FetchInfiniteQueryOptions` - `requestFn?: RequestFn` - **Optional**, a function that will be used to execute the request diff --git a/website/docs/query-client/ensureQueryData.mdx b/website/docs/query-client/ensureQueryData.mdx index 4b2b5225e..ec72763ce 100644 --- a/website/docs/query-client/ensureQueryData.mdx +++ b/website/docs/query-client/ensureQueryData.mdx @@ -22,9 +22,12 @@ const result = api...ensureQueryData({ ### Arguments -1. - `parameters: { path, query, header } | QueryKey | void` +1. - `parameters: { path, query, header, body } | QueryKey | void` - **Required**, OpenAPI request parameters for the query, strictly-typed ✨ - `parameters` will be used to generate the `QueryKey` + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the query key and cache identity for query-client methods + - Mutation calls keep `body` as a separate top-level argument - `requestFn?: RequestFn` - **Optional**, a function that will be used to execute the request - `revalidateIfStale?: boolean` diff --git a/website/docs/query-client/fetchInfiniteQuery.mdx b/website/docs/query-client/fetchInfiniteQuery.mdx index 28ae692f3..f0e49a3b6 100644 --- a/website/docs/query-client/fetchInfiniteQuery.mdx +++ b/website/docs/query-client/fetchInfiniteQuery.mdx @@ -26,9 +26,12 @@ const result = api...fetchInfiniteQuery( ### Arguments -1. - `parameters: { path, query, header } | QueryKey | void` +1. - `parameters: { path, query, header, body } | QueryKey | void` - OpenAPI request parameters for the query, strictly-typed ✨ - - `parameters` will be used to generate the `QueryKey` + - `parameters` will be used to generate the _Infinite Query Key_ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the infinite query key and cache identity + - Mutation calls keep `body` as a separate top-level argument - `fetchInfiniteQueryOptions?: FetchInfiniteQueryOptions` - `requestFn?: RequestFn` - **Optional**, a function that will be used to execute the request diff --git a/website/docs/query-client/fetchQuery.mdx b/website/docs/query-client/fetchQuery.mdx index 6ddd0636a..90c4d4205 100644 --- a/website/docs/query-client/fetchQuery.mdx +++ b/website/docs/query-client/fetchQuery.mdx @@ -29,9 +29,12 @@ const result = api...fetchQuery( ### Arguments -1. - `parameters: { path, query, header } | QueryKey | void` +1. - `parameters: { path, query, header, body } | QueryKey | void` - **Required**, OpenAPI request parameters for the query, strictly-typed ✨ - `parameters` will be used to generate the `QueryKey` + - For operations generated with `--queryable-write-operations`, query parameters may also include `body` + - In that mode, `body` is part of the query key and cache identity for query-client methods + - Mutation calls keep `body` as a separate top-level argument - `requestFn?: RequestFn` - **Optional**, a function that will be used to execute the request - `baseUrl?: string` @@ -70,6 +73,20 @@ const result = api...fetchQuery( ); ``` + With body}> + ```ts + const policy = await api.approvalPolicies.patchApprovalPoliciesId.fetchQuery({ + parameters: { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }, + }); + ``` + With queryFn}> ```ts import { createAPIClient } from './api'; // generated by OpenAPI Qraft CLI From 464a468c1708ff8534fbe67f5dfaf32a70229b05 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 00:11:08 +0400 Subject: [PATCH 13/22] docs: clarify body in query cache identity --- .../query-client/getInfiniteQueryData.mdx | 7 ++-- .../docs/query-client/getInfiniteQueryKey.mdx | 10 +++--- .../query-client/getInfiniteQueryState.mdx | 6 ++-- website/docs/query-client/getQueryData.mdx | 7 ++-- website/docs/query-client/getQueryKey.mdx | 28 ++++++++++++++-- website/docs/query-client/getQueryState.mdx | 6 ++-- .../query-client/setInfiniteQueryData.mdx | 6 ++-- website/docs/query-client/setQueryData.mdx | 32 ++++++++++++++++--- 8 files changed, 80 insertions(+), 22 deletions(-) diff --git a/website/docs/query-client/getInfiniteQueryData.mdx b/website/docs/query-client/getInfiniteQueryData.mdx index 7ed585f10..2107382d8 100644 --- a/website/docs/query-client/getInfiniteQueryData.mdx +++ b/website/docs/query-client/getInfiniteQueryData.mdx @@ -13,10 +13,11 @@ const data = api...getInfiniteQueryData(parameters); ### Arguments -1. `parameters: { path, query, header } | QueryKey | void` +1. `parameters: { path, query, header, body } | InfiniteQueryKey | void` - **Required** parameters to retrieve the data from the cache. - - Instead of an object with `{ path, query, header }`, you can pass a `QueryKey` as an array - which is also strictly-typed ✨ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the infinite query key and cache identity. + - Instead of an object with `{ path, query, header, body }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. ### Returns diff --git a/website/docs/query-client/getInfiniteQueryKey.mdx b/website/docs/query-client/getInfiniteQueryKey.mdx index eb7514754..a81c3761f 100644 --- a/website/docs/query-client/getInfiniteQueryKey.mdx +++ b/website/docs/query-client/getInfiniteQueryKey.mdx @@ -4,7 +4,7 @@ sidebar_label: getInfiniteQueryKey() # getInfiniteQueryKey(...) -The method provides a standardized way to generate `QueryKey` the _Infinite Queries_. +The method provides a standardized way to generate `InfiniteQueryKey` for _Infinite Queries_. See TanStack [_Query Keys 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) guide for more information. @@ -14,13 +14,15 @@ const queryKey = api...getInfiniteQueryKey(parameters); ### Arguments -1. - `parameters: { path, query, header } | QueryKey | void` +1. - `parameters: { path, query, header, body } | void` - **Required**, OpenAPI request parameters for the query, strictly-typed ✨ - - `parameters` will be used to generate the `QueryKey` + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the infinite query key and cache identity. + - The returned `InfiniteQueryKey` can be passed to query-client methods that accept typed infinite query key arrays. ### Returns -`QueryKey` - a query key for the _Infinite Queries_ +`InfiniteQueryKey` - an infinite query key for the _Infinite Queries_ ### Example diff --git a/website/docs/query-client/getInfiniteQueryState.mdx b/website/docs/query-client/getInfiniteQueryState.mdx index 94b6f7618..995d2307b 100644 --- a/website/docs/query-client/getInfiniteQueryState.mdx +++ b/website/docs/query-client/getInfiniteQueryState.mdx @@ -18,9 +18,11 @@ const state = api...getInfiniteQueryState(parameters); ## Arguments -1. `parameters: { path, query, header } | InfiniteQueryKey | void` +1. `parameters: { path, query, header, body } | InfiniteQueryKey | void` - Operation parameters used to build the _Infinite Query Key_, strictly-typed ✨ - - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the infinite query key and cache identity. + - Instead of an object with `{ path, query, header, body }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. - For operations without required parameters, call the method without arguments. ## Returns diff --git a/website/docs/query-client/getQueryData.mdx b/website/docs/query-client/getQueryData.mdx index ad59b2f74..90db73e8f 100644 --- a/website/docs/query-client/getQueryData.mdx +++ b/website/docs/query-client/getQueryData.mdx @@ -18,10 +18,11 @@ const data = api...getQueryData( ## Arguments -1. `parameters: { path, query, header } | QueryKey | void` +1. `parameters: { path, query, header, body } | QueryKey | void` - **Required** parameters to retrieve the data from the _Query Cache_. - - Instead of an object with `{ path, query, header }`, you can pass a `QueryKey` as an array - which is also strictly-typed ✨ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the query key and cache identity for query-client methods. + - Instead of an object with `{ path, query, header, body }`, you can pass a typed `QueryKey` array. ## Returns The data from the _Query Cache_ for the specific query, strictly-typed ✨ diff --git a/website/docs/query-client/getQueryKey.mdx b/website/docs/query-client/getQueryKey.mdx index b40755605..63063ce22 100644 --- a/website/docs/query-client/getQueryKey.mdx +++ b/website/docs/query-client/getQueryKey.mdx @@ -16,9 +16,11 @@ const queryKey = api...getQueryKey(parameters); ### Arguments -1. - `parameters: { path, query, header } | void` +1. - `parameters: { path, query, header, body } | void` - **Optional**, OpenAPI request parameters for the query, strictly-typed ✨ - - `parameters` will be used to generate the `QueryKey` + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the query key and cache identity for query-client methods. + - The returned `QueryKey` can be passed to query-client methods that accept typed query key arrays. ### Returns @@ -44,6 +46,28 @@ const queryKey = api...getQueryKey(parameters); ]); ``` + With body}> + ```tsx + const queryKey = + api.approvalPolicies.patchApprovalPoliciesId.getQueryKey({ + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }); + + expect(queryKey[1]).toEqual({ + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }); + ``` + Without parameters} default> In case all parameters are optional - you can pass nothing. diff --git a/website/docs/query-client/getQueryState.mdx b/website/docs/query-client/getQueryState.mdx index 8f74f8ef8..1a733f72a 100644 --- a/website/docs/query-client/getQueryState.mdx +++ b/website/docs/query-client/getQueryState.mdx @@ -17,9 +17,11 @@ const state = api...getQueryState(parameters); ## Arguments -1. `parameters: { path, query, header } | QueryKey | void` +1. `parameters: { path, query, header, body } | QueryKey | void` - Operation parameters used to build the _Query Key_, strictly-typed ✨ - - Instead of an object with `{ path, query, header }`, you can pass a typed `QueryKey` array. + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the query key and cache identity for query-client methods. + - Instead of an object with `{ path, query, header, body }`, you can pass a typed `QueryKey` array. - For operations without required parameters, call the method without arguments. ## Returns diff --git a/website/docs/query-client/setInfiniteQueryData.mdx b/website/docs/query-client/setInfiniteQueryData.mdx index 157d0b972..08eb1add7 100644 --- a/website/docs/query-client/setInfiniteQueryData.mdx +++ b/website/docs/query-client/setInfiniteQueryData.mdx @@ -22,9 +22,11 @@ const data = api...setInfiniteQueryData( ## Arguments -1. `parameters: { path, query, header } | InfiniteQueryKey` +1. `parameters: { path, query, header, body } | InfiniteQueryKey` - **Required** parameters to set the data in the _Infinite Query Cache_. - - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the infinite query key and cache identity. + - Instead of an object with `{ path, query, header, body }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. 2. `updater: InfiniteData | (oldData: InfiniteData | undefined) => InfiniteData | undefined` - **Required** updater for the infinite-query cache data. - If a non-function value is passed, the data will be updated to this value. diff --git a/website/docs/query-client/setQueryData.mdx b/website/docs/query-client/setQueryData.mdx index 3d0504474..fbd1d87f7 100644 --- a/website/docs/query-client/setQueryData.mdx +++ b/website/docs/query-client/setQueryData.mdx @@ -20,10 +20,11 @@ const data = qraft...setQueryData( ## Arguments -1. `parameters: { path, query, header } | QueryKey` +1. `parameters: { path, query, header, body } | QueryKey` - **Required** parameters to set the data in the _Query Cache_. - - Instead of an object with `{path, query, header}`, you can pass a `QueryKey` as an array - which is also strictly-typed ✨ + - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. + In that mode, `body` is part of the query key and cache identity for query-client methods. + - Instead of an object with `{ path, query, header, body }`, you can pass a typed `QueryKey` array. 2. `updater: TData | (oldData: TData | undefined) => TData | undefined` - **Required** updater for the cache data - If a non-function value is passed, the data will be updated to this value @@ -57,8 +58,31 @@ The `TData` from the updater or `undefined` if it returns nothing }); ``` + With body}> + ```tsx + const parameters = { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { + name: 'New Name', + description: 'New Description', + }, + }; + + qraft.approvalPolicies.patchApprovalPoliciesId.setQueryData(parameters, { + id: '2', + name: 'New Name', + description: 'New Description', + }); + + const policy = + qraft.approvalPolicies.patchApprovalPoliciesId.getQueryData(parameters); + + expect(policy?.name).toEqual('New Name'); + ``` + With QueryKey}> - It's also possible to use a `QueryKey` as an array instead of an object with `{path, query, header}`: + It's also possible to use a typed `QueryKey` array instead of an object with `{ path, query, header, body }`: ```tsx const pet = qraft.pet.getPetById.setQueryData( From c5b4a0d6131a5dec387535038941cb3b1ab21575 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 01:44:58 +0400 Subject: [PATCH 14/22] docs: correct query key docs wording --- ...ueryable-write-operations-docs-contract.md | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md index 0fcedb5e5..f58de646c 100644 --- a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md +++ b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md @@ -447,7 +447,7 @@ Expected: commit succeeds with only the four fetch and ensure docs staged. - [ ] **Step 1: Update normal query key/data/state signatures** -In `getQueryKey.mdx`, `getQueryData.mdx`, `getQueryState.mdx`, and `setQueryData.mdx`, replace normal query parameter signatures and nearby QueryKey prose with: +In `getQueryData.mdx`, `getQueryState.mdx`, and `setQueryData.mdx`, replace normal query parameter signatures and nearby QueryKey prose with: ```md `parameters: { path, query, header, body } | QueryKey | void` @@ -459,6 +459,16 @@ Instead of an object with `{ path, query, header, body }`, you can pass a typed Use `| QueryKey` without `| void` in `setQueryData.mdx` if the existing method signature does not accept `void`. +In `getQueryKey.mdx`, keep the argument signature limited to operation parameters: + +```md +`parameters: { path, query, header, body } | void` + +For operations generated with `--queryable-write-operations`, query parameters may also include `body`. +In that mode, `body` is part of the query key and cache identity for query-client methods. +The returned `QueryKey` can be passed to query-client methods that accept typed query key arrays. +``` + - [ ] **Step 2: Add a body cache identity example to `getQueryKey`** Add this tab to `website/docs/query-client/getQueryKey.mdx`: @@ -520,7 +530,7 @@ Add this tab to `website/docs/query-client/setQueryData.mdx`: - [ ] **Step 4: Update infinite key/data/state/cache signatures** -In `getInfiniteQueryKey.mdx`, `getInfiniteQueryData.mdx`, `getInfiniteQueryState.mdx`, and `setInfiniteQueryData.mdx`, replace infinite query parameter signatures and nearby query key prose with: +In `getInfiniteQueryData.mdx`, `getInfiniteQueryState.mdx`, and `setInfiniteQueryData.mdx`, replace infinite query parameter signatures and nearby query key prose with: ```md `parameters: { path, query, header, body } | InfiniteQueryKey | void` @@ -532,6 +542,16 @@ Instead of an object with `{ path, query, header, body }`, you can pass a typed Use `| InfiniteQueryKey` without `| void` in `setInfiniteQueryData.mdx` if the existing method signature does not accept `void`. +In `getInfiniteQueryKey.mdx`, keep the argument signature limited to operation parameters: + +```md +`parameters: { path, query, header, body } | void` + +For operations generated with `--queryable-write-operations`, query parameters may also include `body`. +In that mode, `body` is part of the infinite query key and cache identity. +The returned `InfiniteQueryKey` can be passed to query-client methods that accept typed infinite query key arrays. +``` + - [ ] **Step 5: Run focused grep** Run: From b10122537a15a4722fbbd8e3c207fe90d3461640 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 01:45:02 +0400 Subject: [PATCH 15/22] docs: correct query key docs wording --- website/docs/query-client/getInfiniteQueryData.mdx | 2 +- website/docs/query-client/getInfiniteQueryKey.mdx | 2 +- website/docs/query-client/getQueryData.mdx | 14 ++++++-------- website/docs/query-client/setQueryData.mdx | 9 +++++---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/website/docs/query-client/getInfiniteQueryData.mdx b/website/docs/query-client/getInfiniteQueryData.mdx index 2107382d8..bc9db647a 100644 --- a/website/docs/query-client/getInfiniteQueryData.mdx +++ b/website/docs/query-client/getInfiniteQueryData.mdx @@ -14,7 +14,7 @@ const data = api...getInfiniteQueryData(parameters); ### Arguments 1. `parameters: { path, query, header, body } | InfiniteQueryKey | void` - - **Required** parameters to retrieve the data from the cache. + - **Optional** parameters to retrieve the data from the cache. - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. In that mode, `body` is part of the infinite query key and cache identity. - Instead of an object with `{ path, query, header, body }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. diff --git a/website/docs/query-client/getInfiniteQueryKey.mdx b/website/docs/query-client/getInfiniteQueryKey.mdx index a81c3761f..519ac0281 100644 --- a/website/docs/query-client/getInfiniteQueryKey.mdx +++ b/website/docs/query-client/getInfiniteQueryKey.mdx @@ -15,7 +15,7 @@ const queryKey = api...getInfiniteQueryKey(parameters); ### Arguments 1. - `parameters: { path, query, header, body } | void` - - **Required**, OpenAPI request parameters for the query, strictly-typed ✨ + - **Optional**, OpenAPI request parameters for the query, strictly-typed ✨ - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. In that mode, `body` is part of the infinite query key and cache identity. - The returned `InfiniteQueryKey` can be passed to query-client methods that accept typed infinite query key arrays. diff --git a/website/docs/query-client/getQueryData.mdx b/website/docs/query-client/getQueryData.mdx index 90db73e8f..4468f67c1 100644 --- a/website/docs/query-client/getQueryData.mdx +++ b/website/docs/query-client/getQueryData.mdx @@ -19,7 +19,7 @@ const data = api...getQueryData( ## Arguments 1. `parameters: { path, query, header, body } | QueryKey | void` - - **Required** parameters to retrieve the data from the _Query Cache_. + - **Optional** parameters to retrieve the data from the _Query Cache_. - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. In that mode, `body` is part of the query key and cache identity for query-client methods. - Instead of an object with `{ path, query, header, body }`, you can pass a typed `QueryKey` array. @@ -41,13 +41,11 @@ The data from the _Query Cache_ for the specific query, strictly-typed ✨ ```tsx - const pet = api.pet.getPetById.getQueryData( - [ - { method: 'get', url: '/pet/{petId}', infinite: false, }, - { petId: 123 }, - ], - {} - ); + const queryKey = api.pet.getPetById.getQueryKey({ + path: { petId: 123 }, + }); + + const pet = api.pet.getPetById.getQueryData(queryKey); expect(pet?.id).toEqual(123); ``` diff --git a/website/docs/query-client/setQueryData.mdx b/website/docs/query-client/setQueryData.mdx index fbd1d87f7..00a114877 100644 --- a/website/docs/query-client/setQueryData.mdx +++ b/website/docs/query-client/setQueryData.mdx @@ -85,11 +85,12 @@ The `TData` from the updater or `undefined` if it returns nothing It's also possible to use a typed `QueryKey` array instead of an object with `{ path, query, header, body }`: ```tsx + const queryKey = qraft.pet.getPetById.getQueryKey({ + path: { petId: 123 }, + }); + const pet = qraft.pet.getPetById.setQueryData( - [ - { method: 'get', url: '/pet/{petId}', infinite: false }, - { petId: 123 }, - ], + queryKey, { id: 123, name: 'Rex' } ); ``` From dddc8cd621c185dac6bbbda4a04dc4c27c606b1b Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 00:28:26 +0400 Subject: [PATCH 16/22] docs: clarify body in query filters --- website/docs/query-client/cancelQueries.mdx | 6 ++++-- website/docs/query-client/invalidateQueries.mdx | 3 ++- website/docs/query-client/isFetching.mdx | 17 ++++++++++++++++- website/docs/query-client/refetchQueries.mdx | 6 ++++-- website/docs/query-client/removeQueries.mdx | 3 ++- website/docs/query-client/resetQueries.mdx | 3 ++- website/docs/query-client/setQueriesData.mdx | 15 ++++++++------- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/website/docs/query-client/cancelQueries.mdx b/website/docs/query-client/cancelQueries.mdx index 34fc0a79f..234f3cf12 100644 --- a/website/docs/query-client/cancelQueries.mdx +++ b/website/docs/query-client/cancelQueries.mdx @@ -25,7 +25,8 @@ guide for more information. 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite?: boolean` will be used to filter infinite or normal queries, **Required** if `predicate` is provided - `filters.queryKey?: QueryKey` will be used for filtering queries by _QueryKey_ instead of ~~`parameters`~~ - `filters.queryKey` and `filters.parameters` are mutually exclusive @@ -45,7 +46,8 @@ guide for more information. 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite?: boolean` will be used to filter infinite or normal queries, **Required** if `predicate` is provided - `filters.queryKey?: QueryKey` will be used for filtering queries by _QueryKey_ instead of ~~`parameters`~~ - `filters.queryKey` and `filters.parameters` are mutually exclusive diff --git a/website/docs/query-client/invalidateQueries.mdx b/website/docs/query-client/invalidateQueries.mdx index 2c5b92db4..9e15a6a73 100644 --- a/website/docs/query-client/invalidateQueries.mdx +++ b/website/docs/query-client/invalidateQueries.mdx @@ -26,7 +26,8 @@ guide for more information. 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive diff --git a/website/docs/query-client/isFetching.mdx b/website/docs/query-client/isFetching.mdx index 8aad68109..5bb4496c6 100644 --- a/website/docs/query-client/isFetching.mdx +++ b/website/docs/query-client/isFetching.mdx @@ -26,7 +26,8 @@ guide for more information. 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive @@ -76,6 +77,20 @@ guide for more information. expect(numberOfFetchingEntities).toEqual(1); ``` + + For queryable write operations, `body` can be part of the filter parameters: + + ```ts + const matchingPolicySearches = + qraft.approvalPolicies.patchApprovalPoliciesId.isFetching({ + infinite: false, + parameters: { + header: { 'x-monite-version': '1' }, + path: { approval_policy_id: '2' }, + body: { name: 'New Name' }, + }, + }); + ``` filters}> To check _all normal queries for a particular endpoint_, you can call `isFetching(...)` without `parameters`: diff --git a/website/docs/query-client/refetchQueries.mdx b/website/docs/query-client/refetchQueries.mdx index e24f1da86..439db281d 100644 --- a/website/docs/query-client/refetchQueries.mdx +++ b/website/docs/query-client/refetchQueries.mdx @@ -24,7 +24,8 @@ See also the TanStack [_queryClient.refetchQueries(...) 🌴_](https://tanstack. 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive @@ -47,7 +48,8 @@ See also the TanStack [_queryClient.refetchQueries(...) 🌴_](https://tanstack. 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive diff --git a/website/docs/query-client/removeQueries.mdx b/website/docs/query-client/removeQueries.mdx index b1d1d0cb1..a5e5d7964 100644 --- a/website/docs/query-client/removeQueries.mdx +++ b/website/docs/query-client/removeQueries.mdx @@ -19,7 +19,8 @@ qraft...removeQueries(filters) 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive diff --git a/website/docs/query-client/resetQueries.mdx b/website/docs/query-client/resetQueries.mdx index 7c4586388..44f797a46 100644 --- a/website/docs/query-client/resetQueries.mdx +++ b/website/docs/query-client/resetQueries.mdx @@ -19,7 +19,8 @@ await api...resetQueries(filters, options); 1. `filters?: QueryFiltersByParameters | QueryFiltersByQueryKey` - Optional [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters), strictly-typed ✨ - - `filters.parameters: { path, query, header }` filters queries by operation parameters. + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.queryKey: QueryKey` filters queries by an explicit typed query key instead of parameters. - `filters.parameters` and `filters.queryKey` are mutually exclusive. - `filters.infinite: boolean` filters regular or infinite query cache entries. diff --git a/website/docs/query-client/setQueriesData.mdx b/website/docs/query-client/setQueriesData.mdx index 7715fb438..1706565c4 100644 --- a/website/docs/query-client/setQueriesData.mdx +++ b/website/docs/query-client/setQueriesData.mdx @@ -25,7 +25,8 @@ See the TanStack [_queryClient.setQueriesData 🌴_](https://tanstack.com/query/ 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive @@ -47,7 +48,8 @@ See the TanStack [_queryClient.setQueriesData 🌴_](https://tanstack.com/query/ 1. `filters: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Required**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used, strictly-typed ✨ - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive @@ -94,15 +96,14 @@ See the TanStack [_queryClient.setQueriesData 🌴_](https://tanstack.com/query/ ``` With QueryKey}> - It's also possible to use a `QueryKey` as an array instead of an object with `{path, query, header}`: + It's also possible to use a typed `QueryKey` from `getQueryKey(...)` instead of an object with `{ path, query, header, body }`: ```tsx const pets = qraft.pet.getPetById.setQueriesData( { - queryKey: [ - { method: 'get', url: '/pet/{petId}', infinite: false }, - { petId: 123 }, - ], + queryKey: qraft.pet.getPetById.getQueryKey({ + path: { petId: 123 }, + }), }, { id: 123, name: 'Rex' } ); From 672f6e7580ddc4a914d2b2f1424230a454766148 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 00:39:41 +0400 Subject: [PATCH 17/22] docs: polish queryable write operation wording --- website/docs/hooks/useIsFetching.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/docs/hooks/useIsFetching.mdx b/website/docs/hooks/useIsFetching.mdx index 2832e2bf1..27a0a0ac8 100644 --- a/website/docs/hooks/useIsFetching.mdx +++ b/website/docs/hooks/useIsFetching.mdx @@ -20,7 +20,8 @@ const queriesNumber = api...useIsFetching( 1. `filters?: QueryFiltersByParameters | QueryFiltersByQueryKey` - **Optional**, represents the [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters) to be used. If not provided, _all_ normal and _Infinite_ queries will be used to filter. - - `filters.parameters: { path, query, header }` will be used for filtering queries by parameters + - `filters.parameters: { path, query, header, body }` filters queries by operation parameters. + - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. - `filters.infinite: boolean` will be used to filter infinite or normal queries - `filters.queryKey: QueryKey` will be used for filtering queries by _QueryKey_ instead of parameters - `filters.queryKey` and `filters.parameters` are mutually exclusive From 54102845babb0e7bbd0aab13ec13b383e38fef98 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 01:43:38 +0400 Subject: [PATCH 18/22] docs: address queryable write docs review --- ...2026-05-21-query-client-docs-completion.md | 42 +++++------ ...ueryable-write-operations-docs-contract.md | 74 +++++++++---------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md b/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md index f0d16193e..f9d4c7d3b 100644 --- a/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md +++ b/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md @@ -28,7 +28,7 @@ **Files:** - Modify: `website/docs/query-client/getQueryState.mdx` -- [ ] **Step 1: Replace the placeholder page with complete reference content** +- [x] **Step 1: Replace the placeholder page with complete reference content** Replace the whole file with: @@ -68,7 +68,7 @@ const state = api...getQueryState(parameters); ```tsx const parameters = { path: { petId: 123 } }; - await api.pet.getPetById.fetchQuery(parameters); + await api.pet.getPetById.fetchQuery({ parameters }); const state = api.pet.getPetById.getQueryState(parameters); @@ -81,7 +81,7 @@ const state = api...getQueryState(parameters); const parameters = { path: { petId: 123 } }; const queryKey = api.pet.getPetById.getQueryKey(parameters); - await api.pet.getPetById.fetchQuery(parameters); + await api.pet.getPetById.fetchQuery({ parameters }); const state = api.pet.getPetById.getQueryState(queryKey); @@ -100,7 +100,7 @@ const state = api...getQueryState(parameters); ```` -- [ ] **Step 2: Check the page no longer contains the active-update notice** +- [x] **Step 2: Check the page no longer contains the active-update notice** Run: @@ -110,7 +110,7 @@ rg -n "Documentation is actively being updated" website/docs/query-client/getQue Expected: command exits with no matches. -- [ ] **Step 3: Commit Task 1** +- [x] **Step 3: Commit Task 1** Run: @@ -126,7 +126,7 @@ Expected: commit succeeds with only `getQueryState.mdx` staged. **Files:** - Modify: `website/docs/query-client/getInfiniteQueryState.mdx` -- [ ] **Step 1: Replace the placeholder page with complete reference content** +- [x] **Step 1: Replace the placeholder page with complete reference content** Replace the whole file with: @@ -208,7 +208,7 @@ const state = api...getInfiniteQueryState(parameters); ```` -- [ ] **Step 2: Check the page no longer contains the active-update notice** +- [x] **Step 2: Check the page no longer contains the active-update notice** Run: @@ -218,7 +218,7 @@ rg -n "Documentation is actively being updated" website/docs/query-client/getInf Expected: command exits with no matches. -- [ ] **Step 3: Commit Task 2** +- [x] **Step 3: Commit Task 2** Run: @@ -234,7 +234,7 @@ Expected: commit succeeds with only `getInfiniteQueryState.mdx` staged. **Files:** - Modify: `website/docs/query-client/setInfiniteQueryData.mdx` -- [ ] **Step 1: Replace the placeholder page with complete reference content** +- [x] **Step 1: Replace the placeholder page with complete reference content** Replace the whole file with: @@ -352,7 +352,7 @@ const data = api...setInfiniteQueryData( ```` -- [ ] **Step 2: Check line length around the long final example** +- [x] **Step 2: Check line length around the long final example** Run: @@ -368,7 +368,7 @@ expect( ).toHaveLength(1); ``` -- [ ] **Step 3: Check the page no longer contains the active-update notice** +- [x] **Step 3: Check the page no longer contains the active-update notice** Run: @@ -378,7 +378,7 @@ rg -n "Documentation is actively being updated" website/docs/query-client/setInf Expected: command exits with no matches. -- [ ] **Step 4: Commit Task 3** +- [x] **Step 4: Commit Task 3** Run: @@ -394,7 +394,7 @@ Expected: commit succeeds with only `setInfiniteQueryData.mdx` staged. **Files:** - Modify: `website/docs/query-client/resetQueries.mdx` -- [ ] **Step 1: Replace the placeholder page with complete reference content** +- [x] **Step 1: Replace the placeholder page with complete reference content** Replace the whole file with: @@ -487,7 +487,7 @@ await api...resetQueries(filters, options); ```` -- [ ] **Step 2: Confirm the incorrect hook wording is gone** +- [x] **Step 2: Confirm the incorrect hook wording is gone** Run: @@ -497,7 +497,7 @@ rg -n "Hook|hook" website/docs/query-client/resetQueries.mdx Expected: command exits with no matches. -- [ ] **Step 3: Check the page no longer contains the active-update notice** +- [x] **Step 3: Check the page no longer contains the active-update notice** Run: @@ -507,7 +507,7 @@ rg -n "Documentation is actively being updated" website/docs/query-client/resetQ Expected: command exits with no matches. -- [ ] **Step 4: Commit Task 4** +- [x] **Step 4: Commit Task 4** Run: @@ -526,7 +526,7 @@ Expected: commit succeeds with only `resetQueries.mdx` staged. - Inspect: `website/docs/query-client/setInfiniteQueryData.mdx` - Inspect: `website/docs/query-client/resetQueries.mdx` -- [ ] **Step 1: Confirm the active-update notice is gone from current docs only** +- [x] **Step 1: Confirm the active-update notice is gone from current docs only** Run: @@ -538,7 +538,7 @@ Expected: command exits with no matches. Do not run this check against `website/versioned_docs`; versioned docs are intentionally excluded. -- [ ] **Step 2: Check MDX lint for the website** +- [x] **Step 2: Check MDX lint for the website** Run: @@ -548,7 +548,7 @@ yarn workspace openapi-qraft-website lint Expected: PASS. If it fails on pre-existing unrelated files, capture the exact unrelated failures and still run Task 5 Step 3. -- [ ] **Step 3: Check the Docusaurus build** +- [x] **Step 3: Check the Docusaurus build** Run: @@ -558,7 +558,7 @@ yarn workspace openapi-qraft-website build Expected: PASS. If dependencies are unavailable in the worktree, report the missing dependency error and keep the static validation results. -- [ ] **Step 4: Check whitespace** +- [x] **Step 4: Check whitespace** Run: @@ -568,7 +568,7 @@ git diff --check Expected: no output and exit code 0. -- [ ] **Step 5: Commit validation-only fixes if needed** +- [x] **Step 5: Commit validation-only fixes if needed** If Task 5 Step 2, Step 3, or Step 4 required a small docs formatting fix, commit it: diff --git a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md index f58de646c..fee56ccba 100644 --- a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md +++ b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md @@ -108,7 +108,7 @@ Mutation calls keep `body` as a separate top-level argument. - Modify: `website/docs/hooks/useInfiniteQuery.mdx` - Modify: `website/docs/hooks/useSuspenseInfiniteQuery.mdx` -- [ ] **Step 1: Update `useQuery` argument wording** +- [x] **Step 1: Update `useQuery` argument wording** In `website/docs/hooks/useQuery.mdx`, replace the current first argument block with: @@ -124,7 +124,7 @@ In `website/docs/hooks/useQuery.mdx`, replace the current first argument block w which is also strictly-typed ``` -- [ ] **Step 2: Update `useSuspenseQuery` argument wording** +- [x] **Step 2: Update `useSuspenseQuery` argument wording** In `website/docs/hooks/useSuspenseQuery.mdx`, replace the current first argument block with: @@ -140,23 +140,23 @@ In `website/docs/hooks/useSuspenseQuery.mdx`, replace the current first argument which is also strictly-typed ✨ ``` -- [ ] **Step 3: Update infinite hook argument wording** +- [x] **Step 3: Update infinite hook argument wording** In both `website/docs/hooks/useInfiniteQuery.mdx` and `website/docs/hooks/useSuspenseInfiniteQuery.mdx`, replace the current first argument block with: ```md -1. `parameters: { path, query, header, body } | QueryKey | undefined` +1. `parameters: { path, query, header, body } | InfiniteQueryKey | undefined` - **Required only if OpenAPI specification defines required parameters** - If the operation has no required parameters according to OpenAPI, you can omit this argument - `parameters` will be used to generate the _Infinite Query Key_ - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - In that mode, `body` is part of the infinite query key and cache identity - Mutation calls keep `body` as a separate top-level argument - - Instead of an object with `{ path, query, header, body }`, you can pass an infinite `QueryKey` as an array + - Instead of an object with `{ path, query, header, body }`, you can pass a typed `InfiniteQueryKey` from `getInfiniteQueryKey(...)` which is also strictly-typed ✨ ``` -- [ ] **Step 4: Run a focused grep for old hook wording** +- [x] **Step 4: Run a focused grep for old hook wording** Run: @@ -166,7 +166,7 @@ rg -n "\\{path, query, header\\}|\\{ path, query, header \\}" website/docs/hooks Expected: no matches for the four files in this task. -- [ ] **Step 5: Commit Task 1** +- [x] **Step 5: Commit Task 1** Run: @@ -183,7 +183,7 @@ Expected: commit succeeds with only the four hook docs staged. - Modify: `website/docs/hooks/useQueries.mdx` - Modify: `website/docs/hooks/useSuspenseQueries.mdx` -- [ ] **Step 1: Add tab imports to `useQueries`** +- [x] **Step 1: Add tab imports to `useQueries`** In `website/docs/hooks/useQueries.mdx`, add these imports after the frontmatter and before `# useQueries(...)`: @@ -192,7 +192,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ``` -- [ ] **Step 2: Update `useQueries` query list wording** +- [x] **Step 2: Update `useQueries` query list wording** In `website/docs/hooks/useQueries.mdx`, replace the `options.queries` sub-bullets with: @@ -205,7 +205,7 @@ In `website/docs/hooks/useQueries.mdx`, replace the `options.queries` sub-bullet - `queryKey` and `parameters` are mutually exclusive ``` -- [ ] **Step 3: Add a writable operation tab to `useQueries`** +- [x] **Step 3: Add a writable operation tab to `useQueries`** Replace the single `### Example` code block in `website/docs/hooks/useQueries.mdx` with a `Tabs` block. Keep the existing GET example as the first tab and add this second tab: @@ -286,7 +286,7 @@ Replace the single `### Example` code block in `website/docs/hooks/useQueries.md ```` -- [ ] **Step 4: Update `useSuspenseQueries` query list wording** +- [x] **Step 4: Update `useSuspenseQueries` query list wording** In `website/docs/hooks/useSuspenseQueries.mdx`, replace the `options.queries` sub-bullets with: @@ -299,7 +299,7 @@ In `website/docs/hooks/useSuspenseQueries.mdx`, replace the `options.queries` su - `queryKey` and `parameters` are mutually exclusive ``` -- [ ] **Step 5: Add a short body example note to `useSuspenseQueries`** +- [x] **Step 5: Add a short body example note to `useSuspenseQueries`** After the existing example in `website/docs/hooks/useSuspenseQueries.mdx`, add: @@ -332,7 +332,7 @@ const results = api.approvalPolicies.patchApprovalPoliciesId.useSuspenseQueries( ``` ```` -- [ ] **Step 6: Run focused grep** +- [x] **Step 6: Run focused grep** Run: @@ -342,7 +342,7 @@ rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ pat Expected: no matches. -- [ ] **Step 7: Commit Task 2** +- [x] **Step 7: Commit Task 2** Run: @@ -361,7 +361,7 @@ Expected: commit succeeds with only the two multi-query docs staged. - Modify: `website/docs/query-client/ensureQueryData.mdx` - Modify: `website/docs/query-client/ensureInfiniteQueryData.mdx` -- [ ] **Step 1: Update normal fetch argument blocks** +- [x] **Step 1: Update normal fetch argument blocks** In both `fetchQuery.mdx` and `ensureQueryData.mdx`, replace the first `parameters` bullet with: @@ -376,7 +376,7 @@ In both `fetchQuery.mdx` and `ensureQueryData.mdx`, replace the first `parameter Keep the existing `requestFn`, `baseUrl`, and options bullets after this block. -- [ ] **Step 2: Add a writable `fetchQuery` example tab** +- [x] **Step 2: Add a writable `fetchQuery` example tab** In `website/docs/query-client/fetchQuery.mdx`, add this tab after the existing basic tab: @@ -397,12 +397,12 @@ In `website/docs/query-client/fetchQuery.mdx`, add this tab after the existing b ```` -- [ ] **Step 3: Update infinite fetch argument blocks** +- [x] **Step 3: Update infinite fetch argument blocks** In both `fetchInfiniteQuery.mdx` and `ensureInfiniteQueryData.mdx`, replace the first `parameters` bullet with: ```md -1. - `parameters: { path, query, header, body } | QueryKey | void` +1. - `parameters: { path, query, header, body } | InfiniteQueryKey | void` - OpenAPI request parameters for the query, strictly-typed ✨ - `parameters` will be used to generate the _Infinite Query Key_ - For operations generated with `--queryable-write-operations`, query parameters may also include `body` @@ -412,7 +412,7 @@ In both `fetchInfiniteQuery.mdx` and `ensureInfiniteQueryData.mdx`, replace the Keep the existing fetch options bullets after this block. -- [ ] **Step 4: Run focused grep** +- [x] **Step 4: Run focused grep** Run: @@ -422,7 +422,7 @@ rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query Expected: no matches. -- [ ] **Step 5: Commit Task 3** +- [x] **Step 5: Commit Task 3** Run: @@ -445,7 +445,7 @@ Expected: commit succeeds with only the four fetch and ensure docs staged. - Modify: `website/docs/query-client/setQueryData.mdx` - Modify: `website/docs/query-client/setInfiniteQueryData.mdx` -- [ ] **Step 1: Update normal query key/data/state signatures** +- [x] **Step 1: Update normal query key/data/state signatures** In `getQueryData.mdx`, `getQueryState.mdx`, and `setQueryData.mdx`, replace normal query parameter signatures and nearby QueryKey prose with: @@ -469,7 +469,7 @@ In that mode, `body` is part of the query key and cache identity for query-clien The returned `QueryKey` can be passed to query-client methods that accept typed query key arrays. ``` -- [ ] **Step 2: Add a body cache identity example to `getQueryKey`** +- [x] **Step 2: Add a body cache identity example to `getQueryKey`** Add this tab to `website/docs/query-client/getQueryKey.mdx`: @@ -498,7 +498,7 @@ Add this tab to `website/docs/query-client/getQueryKey.mdx`: ```` -- [ ] **Step 3: Add a body cache write/read example to `setQueryData`** +- [x] **Step 3: Add a body cache write/read example to `setQueryData`** Add this tab to `website/docs/query-client/setQueryData.mdx`: @@ -528,7 +528,7 @@ Add this tab to `website/docs/query-client/setQueryData.mdx`: ```` -- [ ] **Step 4: Update infinite key/data/state/cache signatures** +- [x] **Step 4: Update infinite key/data/state/cache signatures** In `getInfiniteQueryData.mdx`, `getInfiniteQueryState.mdx`, and `setInfiniteQueryData.mdx`, replace infinite query parameter signatures and nearby query key prose with: @@ -552,7 +552,7 @@ In that mode, `body` is part of the infinite query key and cache identity. The returned `InfiniteQueryKey` can be passed to query-client methods that accept typed infinite query key arrays. ``` -- [ ] **Step 5: Run focused grep** +- [x] **Step 5: Run focused grep** Run: @@ -562,7 +562,7 @@ rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query Expected: no stale matches. If an example intentionally shows mutation invoke arguments, keep it and note it in the task summary. -- [ ] **Step 6: Commit Task 4** +- [x] **Step 6: Commit Task 4** Run: @@ -584,7 +584,7 @@ Expected: commit succeeds with only the eight query key/cache docs staged. - Modify: `website/docs/query-client/resetQueries.mdx` - Modify: `website/docs/query-client/isFetching.mdx` -- [ ] **Step 1: Update filter parameter bullets across filter pages** +- [x] **Step 1: Update filter parameter bullets across filter pages** In each file listed for this task, replace every query filter parameter bullet that currently says: @@ -605,7 +605,7 @@ with: - For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. ``` -- [ ] **Step 2: Update setQueriesData QueryKey prose** +- [x] **Step 2: Update setQueriesData QueryKey prose** In `website/docs/query-client/setQueriesData.mdx`, replace: @@ -619,7 +619,7 @@ with: It's also possible to use a `QueryKey` as an array instead of an object with `{ path, query, header, body }`: ``` -- [ ] **Step 3: Add one filter example with body** +- [x] **Step 3: Add one filter example with body** Add this short example after the first filter example in `website/docs/query-client/isFetching.mdx`: @@ -639,7 +639,7 @@ Add this short example after the first filter example in `website/docs/query-cli ``` ```` -- [ ] **Step 4: Run focused grep** +- [x] **Step 4: Run focused grep** Run: @@ -649,7 +649,7 @@ rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query Expected: no stale query-filter matches. -- [ ] **Step 5: Commit Task 5** +- [x] **Step 5: Commit Task 5** Run: @@ -666,7 +666,7 @@ Expected: commit succeeds with only the seven filter docs staged. - Inspect: `website/docs` - Do not inspect as blockers: `website/versioned_docs/*` -- [ ] **Step 1: Run scoped stale wording search** +- [x] **Step 1: Run scoped stale wording search** Run: @@ -676,7 +676,7 @@ rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ pat Expected: remaining matches are only mutation-specific docs or intentionally unchanged mutation examples. Record the allowed files in the final summary. Query-surface matches should be fixed before continuing. -- [ ] **Step 2: Check mutation boundary wording** +- [x] **Step 2: Check mutation boundary wording** Run: @@ -686,7 +686,7 @@ rg -n "body.*separate top-level|Mutation calls keep `body`|parameters\\.body" we Expected: query-surface pages explain `parameters.body`; mutation-boundary notes say mutation calls keep `body` top-level. There should be no mutation page claiming `parameters.body` for invoke calls. -- [ ] **Step 3: Run website lint** +- [x] **Step 3: Run website lint** Run: @@ -696,7 +696,7 @@ yarn workspace openapi-qraft-website lint Expected: PASS. -- [ ] **Step 4: Run website build** +- [x] **Step 4: Run website build** Run: @@ -706,7 +706,7 @@ yarn workspace openapi-qraft-website build Expected: PASS. -- [ ] **Step 5: Check whitespace** +- [x] **Step 5: Check whitespace** Run: @@ -716,7 +716,7 @@ git diff --check Expected: no output and exit code 0. -- [ ] **Step 6: Commit validation fixes if needed** +- [x] **Step 6: Commit validation fixes if needed** If validation required small formatting or wording fixes, commit them: From 594355bfde4bee021b547013d135d0b922147b36 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 01:43:40 +0400 Subject: [PATCH 19/22] docs: address queryable write docs review --- website/docs/hooks/useInfiniteQuery.mdx | 4 ++-- website/docs/hooks/useSuspenseInfiniteQuery.mdx | 4 ++-- website/docs/query-client/ensureInfiniteQueryData.mdx | 2 +- website/docs/query-client/fetchInfiniteQuery.mdx | 2 +- website/docs/query-client/getQueryState.mdx | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/website/docs/hooks/useInfiniteQuery.mdx b/website/docs/hooks/useInfiniteQuery.mdx index 01cee8d78..beb2c4696 100644 --- a/website/docs/hooks/useInfiniteQuery.mdx +++ b/website/docs/hooks/useInfiniteQuery.mdx @@ -20,14 +20,14 @@ const query = api...useInfiniteQuery( ### Arguments -1. `parameters: { path, query, header, body } | QueryKey | undefined` +1. `parameters: { path, query, header, body } | InfiniteQueryKey | undefined` - **Required only if OpenAPI specification defines required parameters** - If the operation has no required parameters according to OpenAPI, you can omit this argument - `parameters` will be used to generate the _Infinite Query Key_ - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - In that mode, `body` is part of the infinite query key and cache identity - Mutation calls keep `body` as a separate top-level argument - - Instead of an object with `{ path, query, header, body }`, you can pass an infinite `QueryKey` as an array + - Instead of an object with `{ path, query, header, body }`, you can pass a typed `InfiniteQueryKey` from `getInfiniteQueryKey(...)` which is also strictly-typed ✨ 2. `infiniteQueryOptions?: UseInfiniteQueryOptions` diff --git a/website/docs/hooks/useSuspenseInfiniteQuery.mdx b/website/docs/hooks/useSuspenseInfiniteQuery.mdx index 2d2a882e3..d3e769cd3 100644 --- a/website/docs/hooks/useSuspenseInfiniteQuery.mdx +++ b/website/docs/hooks/useSuspenseInfiniteQuery.mdx @@ -18,14 +18,14 @@ const query = api...useSuspenseInfiniteQuery( ### Arguments -1. `parameters: { path, query, header, body } | QueryKey | undefined` +1. `parameters: { path, query, header, body } | InfiniteQueryKey | undefined` - **Required only if OpenAPI specification defines required parameters** - If the operation has no required parameters according to OpenAPI, you can omit this argument - `parameters` will be used to generate the _Infinite Query Key_ - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - In that mode, `body` is part of the infinite query key and cache identity - Mutation calls keep `body` as a separate top-level argument - - Instead of an object with `{ path, query, header, body }`, you can pass an infinite `QueryKey` as an array + - Instead of an object with `{ path, query, header, body }`, you can pass a typed `InfiniteQueryKey` from `getInfiniteQueryKey(...)` which is also strictly-typed ✨ 2. `suspenseInfiniteQueryOptions?: UseSuspenseInfiniteQueryOptions` diff --git a/website/docs/query-client/ensureInfiniteQueryData.mdx b/website/docs/query-client/ensureInfiniteQueryData.mdx index 40517c4a5..ffb651bf3 100644 --- a/website/docs/query-client/ensureInfiniteQueryData.mdx +++ b/website/docs/query-client/ensureInfiniteQueryData.mdx @@ -22,7 +22,7 @@ const result = api...ensureInfiniteQueryData({ ``` ### Arguments -1. - `parameters: { path, query, header, body } | QueryKey | void` +1. - `parameters: { path, query, header, body } | InfiniteQueryKey | void` - OpenAPI request parameters for the query, strictly-typed ✨ - `parameters` will be used to generate the _Infinite Query Key_ - For operations generated with `--queryable-write-operations`, query parameters may also include `body` diff --git a/website/docs/query-client/fetchInfiniteQuery.mdx b/website/docs/query-client/fetchInfiniteQuery.mdx index f0e49a3b6..697a18e49 100644 --- a/website/docs/query-client/fetchInfiniteQuery.mdx +++ b/website/docs/query-client/fetchInfiniteQuery.mdx @@ -26,7 +26,7 @@ const result = api...fetchInfiniteQuery( ### Arguments -1. - `parameters: { path, query, header, body } | QueryKey | void` +1. - `parameters: { path, query, header, body } | InfiniteQueryKey | void` - OpenAPI request parameters for the query, strictly-typed ✨ - `parameters` will be used to generate the _Infinite Query Key_ - For operations generated with `--queryable-write-operations`, query parameters may also include `body` diff --git a/website/docs/query-client/getQueryState.mdx b/website/docs/query-client/getQueryState.mdx index 1a733f72a..cc2d34298 100644 --- a/website/docs/query-client/getQueryState.mdx +++ b/website/docs/query-client/getQueryState.mdx @@ -35,7 +35,7 @@ const state = api...getQueryState(parameters); ```tsx const parameters = { path: { petId: 123 } }; - await api.pet.getPetById.fetchQuery(parameters); + await api.pet.getPetById.fetchQuery({ parameters }); const state = api.pet.getPetById.getQueryState(parameters); @@ -48,7 +48,7 @@ const state = api...getQueryState(parameters); const parameters = { path: { petId: 123 } }; const queryKey = api.pet.getPetById.getQueryKey(parameters); - await api.pet.getPetById.fetchQuery(parameters); + await api.pet.getPetById.fetchQuery({ parameters }); const state = api.pet.getPetById.getQueryState(queryKey); From 28bdca4ee959249f479e9b666528e5ae312f5f7e Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Fri, 22 May 2026 01:47:43 +0400 Subject: [PATCH 20/22] docs: clarify conditional query parameters --- website/docs/query-client/getInfiniteQueryData.mdx | 3 ++- website/docs/query-client/getInfiniteQueryKey.mdx | 3 ++- website/docs/query-client/getQueryData.mdx | 3 ++- website/docs/query-client/getQueryKey.mdx | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/website/docs/query-client/getInfiniteQueryData.mdx b/website/docs/query-client/getInfiniteQueryData.mdx index bc9db647a..0e18ddd02 100644 --- a/website/docs/query-client/getInfiniteQueryData.mdx +++ b/website/docs/query-client/getInfiniteQueryData.mdx @@ -14,7 +14,8 @@ const data = api...getInfiniteQueryData(parameters); ### Arguments 1. `parameters: { path, query, header, body } | InfiniteQueryKey | void` - - **Optional** parameters to retrieve the data from the cache. + - **Required only if OpenAPI specification defines required parameters** to retrieve the data from the cache. + - If the operation has no required parameters according to OpenAPI, you can omit this argument. - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. In that mode, `body` is part of the infinite query key and cache identity. - Instead of an object with `{ path, query, header, body }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. diff --git a/website/docs/query-client/getInfiniteQueryKey.mdx b/website/docs/query-client/getInfiniteQueryKey.mdx index 519ac0281..73ee95a1b 100644 --- a/website/docs/query-client/getInfiniteQueryKey.mdx +++ b/website/docs/query-client/getInfiniteQueryKey.mdx @@ -15,7 +15,8 @@ const queryKey = api...getInfiniteQueryKey(parameters); ### Arguments 1. - `parameters: { path, query, header, body } | void` - - **Optional**, OpenAPI request parameters for the query, strictly-typed ✨ + - **Required only if OpenAPI specification defines required parameters**, strictly-typed ✨ + - If the operation has no required parameters according to OpenAPI, you can omit this argument. - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. In that mode, `body` is part of the infinite query key and cache identity. - The returned `InfiniteQueryKey` can be passed to query-client methods that accept typed infinite query key arrays. diff --git a/website/docs/query-client/getQueryData.mdx b/website/docs/query-client/getQueryData.mdx index 4468f67c1..7b7989caf 100644 --- a/website/docs/query-client/getQueryData.mdx +++ b/website/docs/query-client/getQueryData.mdx @@ -19,7 +19,8 @@ const data = api...getQueryData( ## Arguments 1. `parameters: { path, query, header, body } | QueryKey | void` - - **Optional** parameters to retrieve the data from the _Query Cache_. + - **Required only if OpenAPI specification defines required parameters** to retrieve the data from the _Query Cache_. + - If the operation has no required parameters according to OpenAPI, you can omit this argument. - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. In that mode, `body` is part of the query key and cache identity for query-client methods. - Instead of an object with `{ path, query, header, body }`, you can pass a typed `QueryKey` array. diff --git a/website/docs/query-client/getQueryKey.mdx b/website/docs/query-client/getQueryKey.mdx index 63063ce22..d087886b4 100644 --- a/website/docs/query-client/getQueryKey.mdx +++ b/website/docs/query-client/getQueryKey.mdx @@ -17,7 +17,8 @@ const queryKey = api...getQueryKey(parameters); ### Arguments 1. - `parameters: { path, query, header, body } | void` - - **Optional**, OpenAPI request parameters for the query, strictly-typed ✨ + - **Required only if OpenAPI specification defines required parameters**, strictly-typed ✨ + - If the operation has no required parameters according to OpenAPI, you can omit this argument. - For operations generated with `--queryable-write-operations`, query parameters may also include `body`. In that mode, `body` is part of the query key and cache identity for query-client methods. - The returned `QueryKey` can be passed to query-client methods that accept typed query key arrays. From efc0e2f3f0021ee92a4dd7618d627603dfaf0075 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Sun, 24 May 2026 22:34:51 +0400 Subject: [PATCH 21/22] Revert "docs: add query client docs completion design" --- ...2026-05-21-query-client-docs-completion.md | 586 -------------- ...ueryable-write-operations-docs-contract.md | 734 ------------------ ...-21-query-client-docs-completion-design.md | 85 -- ...e-write-operations-docs-contract-design.md | 149 ---- 4 files changed, 1554 deletions(-) delete mode 100644 docs/superpowers/plans/2026-05-21-query-client-docs-completion.md delete mode 100644 docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md delete mode 100644 docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md delete mode 100644 docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md diff --git a/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md b/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md deleted file mode 100644 index f9d4c7d3b..000000000 --- a/docs/superpowers/plans/2026-05-21-query-client-docs-completion.md +++ /dev/null @@ -1,586 +0,0 @@ -# Query Client Docs Completion Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Complete the four current query-client docs pages that still contain the active-update notice. - -**Architecture:** This is a documentation-only change. Each task rewrites one tightly scoped MDX reference page using the existing query-client docs style, with one final validation task that checks only current docs under `website/docs`. - -**Tech Stack:** Docusaurus MDX, TanStack Query v5 concepts, Qraft generated React client docs, Yarn 4 workspace scripts. - ---- - -## File Structure - -- Modify: `website/docs/query-client/getQueryState.mdx` - - Responsibility: document the typed `queryClient.getQueryState` wrapper for normal queries. -- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` - - Responsibility: document the infinite-query counterpart that uses infinite query keys and infinite cache data. -- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` - - Responsibility: document writing `pages` / `pageParams` cache data for one infinite query. -- Modify: `website/docs/query-client/resetQueries.mdx` - - Responsibility: document typed query-filter based reset behavior and remove the incorrect hook wording. -- Do not modify: `website/versioned_docs/*` - - Responsibility: keep historical docs unchanged; active-update notices there are intentionally allowed. - -## Task 1: Complete `getQueryState` Docs - -**Files:** -- Modify: `website/docs/query-client/getQueryState.mdx` - -- [x] **Step 1: Replace the placeholder page with complete reference content** - -Replace the whole file with: - -````mdx ---- -sidebar_label: getQueryState() ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# getQueryState(...) - -The method enables direct access to the `QueryClient` cache state for a specific _Query_. -It is a strictly-typed wrapper around TanStack -[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate). - -```ts -const state = api...getQueryState(parameters); -``` - -## Arguments - -1. `parameters: { path, query, header } | QueryKey | void` - - Operation parameters used to build the _Query Key_, strictly-typed ✨ - - Instead of an object with `{ path, query, header }`, you can pass a typed `QueryKey` array. - - For operations without required parameters, call the method without arguments. - -## Returns - -`QueryState | undefined` - The current cache state for the query, or `undefined` if the query is not in the cache. - -## Example - - - - ```tsx - const parameters = { path: { petId: 123 } }; - - await api.pet.getPetById.fetchQuery({ parameters }); - - const state = api.pet.getPetById.getQueryState(parameters); - - expect(state?.status).toEqual('success'); - expect(state?.data?.id).toEqual(123); - ``` - - - ```tsx - const parameters = { path: { petId: 123 } }; - const queryKey = api.pet.getPetById.getQueryKey(parameters); - - await api.pet.getPetById.fetchQuery({ parameters }); - - const state = api.pet.getPetById.getQueryState(queryKey); - - expect(state?.status).toEqual('success'); - ``` - - - ```tsx - await api.pet.findPets.fetchQuery(); - - const state = api.pet.findPets.getQueryState(); - - expect(state?.status).toEqual('success'); - ``` - - -```` - -- [x] **Step 2: Check the page no longer contains the active-update notice** - -Run: - -```bash -rg -n "Documentation is actively being updated" website/docs/query-client/getQueryState.mdx -``` - -Expected: command exits with no matches. - -- [x] **Step 3: Commit Task 1** - -Run: - -```bash -git add website/docs/query-client/getQueryState.mdx -git commit -m "docs: complete getQueryState reference" -``` - -Expected: commit succeeds with only `getQueryState.mdx` staged. - -## Task 2: Complete `getInfiniteQueryState` Docs - -**Files:** -- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` - -- [x] **Step 1: Replace the placeholder page with complete reference content** - -Replace the whole file with: - -````mdx ---- -sidebar_label: getInfiniteQueryState() ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# getInfiniteQueryState(...) - -The method enables direct access to the `QueryClient` cache state for a specific _Infinite Query_. -It is the infinite-query counterpart to [`getQueryState`](getQueryState.mdx): Qraft still calls TanStack -[_queryClient.getQueryState(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientgetquerystate), -but it builds an infinite query key and returns state for infinite cache data. - -```ts -const state = api...getInfiniteQueryState(parameters); -``` - -## Arguments - -1. `parameters: { path, query, header } | InfiniteQueryKey | void` - - Operation parameters used to build the _Infinite Query Key_, strictly-typed ✨ - - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. - - For operations without required parameters, call the method without arguments. - -## Returns - -`QueryState, TError> | undefined` - The current cache state for the infinite query, or `undefined` if the infinite query is not in the cache. - -## Example - - - - ```tsx - const parameters = { - query: { status: 'available' }, - }; - - api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { - pages: [ - [{ id: 1, name: 'Rex', status: 'available' }], - ], - pageParams: [parameters], - }); - - const state = api.pet.findPetsByStatus.getInfiniteQueryState(parameters); - - expect(state?.data).toEqual({ - pages: [ - [{ id: 1, name: 'Rex', status: 'available' }], - ], - pageParams: [parameters], - }); - ``` - - - ```tsx - const parameters = { - query: { status: 'available' }, - }; - const queryKey = api.pet.findPetsByStatus.getInfiniteQueryKey(parameters); - - api.pet.findPetsByStatus.setInfiniteQueryData(queryKey, { - pages: [ - [{ id: 1, name: 'Rex', status: 'available' }], - ], - pageParams: [parameters], - }); - - const state = api.pet.findPetsByStatus.getInfiniteQueryState(queryKey); - - expect(state?.status).toEqual('success'); - ``` - - -```` - -- [x] **Step 2: Check the page no longer contains the active-update notice** - -Run: - -```bash -rg -n "Documentation is actively being updated" website/docs/query-client/getInfiniteQueryState.mdx -``` - -Expected: command exits with no matches. - -- [x] **Step 3: Commit Task 2** - -Run: - -```bash -git add website/docs/query-client/getInfiniteQueryState.mdx -git commit -m "docs: complete getInfiniteQueryState reference" -``` - -Expected: commit succeeds with only `getInfiniteQueryState.mdx` staged. - -## Task 3: Complete `setInfiniteQueryData` Docs - -**Files:** -- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` - -- [x] **Step 1: Replace the placeholder page with complete reference content** - -Replace the whole file with: - -````mdx ---- -sidebar_label: setInfiniteQueryData() ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# setInfiniteQueryData(...) - -The method enables direct access to the `QueryClient` cache to set data for a specific _Infinite Query_. -It has the same role as [`setQueryData`](setQueryData.mdx), but writes infinite-query data with `pages` and `pageParams`. - -See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation. - -```ts -const data = api...setInfiniteQueryData( - parameters, - updater, - options -); -``` - -## Arguments - -1. `parameters: { path, query, header } | InfiniteQueryKey` - - **Required** parameters to set the data in the _Infinite Query Cache_. - - Instead of an object with `{ path, query, header }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. -2. `updater: InfiniteData | (oldData: InfiniteData | undefined) => InfiniteData | undefined` - - **Required** updater for the infinite-query cache data. - - If a non-function value is passed, the data will be updated to this value. - - If a function is passed, it receives the old infinite-query data and must return the next value. -3. `options?: SetQueryDataOptions` - - Optional options to set the data in the cache. - - See the TanStack [_queryClient.setQueryData 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientsetquerydata) documentation for more details. - -## Returns - -`InfiniteData | undefined` - The data that was written to the cache, or `undefined` if the updater returns `undefined`. - -## Example - - - - ```tsx - const parameters = { - query: { status: 'available' }, - }; - - const pets = api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { - pages: [ - [{ id: 1, name: 'Rex', status: 'available' }], - ], - pageParams: [parameters], - }); - - expect(pets).toEqual({ - pages: [ - [{ id: 1, name: 'Rex', status: 'available' }], - ], - pageParams: [parameters], - }); - ``` - - - ```tsx - const parameters = { - query: { status: 'available' }, - }; - - api.pet.findPetsByStatus.setInfiniteQueryData(parameters, { - pages: [[]], - pageParams: [parameters], - }); - - const pets = api.pet.findPetsByStatus.setInfiniteQueryData( - parameters, - (oldData) => ({ - pages: [ - ...(oldData?.pages ?? []), - [{ id: 2, name: 'Bella', status: 'available' }], - ], - pageParams: [ - ...(oldData?.pageParams ?? []), - { query: { status: 'available', page: 2 } }, - ], - }) - ); - - expect(pets?.pages.at(-1)).toEqual([ - { id: 2, name: 'Bella', status: 'available' }, - ]); - ``` - - - ```tsx - const parameters = { - query: { status: 'available' }, - }; - const queryKey = api.pet.findPetsByStatus.getInfiniteQueryKey(parameters); - - api.pet.findPetsByStatus.setInfiniteQueryData(queryKey, { - pages: [ - [{ id: 1, name: 'Rex', status: 'available' }], - ], - pageParams: [parameters], - }); - - expect(api.pet.findPetsByStatus.getInfiniteQueryData(parameters)?.pages).toHaveLength(1); - ``` - - -```` - -- [x] **Step 2: Check line length around the long final example** - -Run: - -```bash -sed -n '90,135p' website/docs/query-client/setInfiniteQueryData.mdx -``` - -Expected: the final `expect(...)` line is readable. If it is too long for local style, split it as: - -```tsx -expect( - api.pet.findPetsByStatus.getInfiniteQueryData(parameters)?.pages -).toHaveLength(1); -``` - -- [x] **Step 3: Check the page no longer contains the active-update notice** - -Run: - -```bash -rg -n "Documentation is actively being updated" website/docs/query-client/setInfiniteQueryData.mdx -``` - -Expected: command exits with no matches. - -- [x] **Step 4: Commit Task 3** - -Run: - -```bash -git add website/docs/query-client/setInfiniteQueryData.mdx -git commit -m "docs: complete setInfiniteQueryData reference" -``` - -Expected: commit succeeds with only `setInfiniteQueryData.mdx` staged. - -## Task 4: Complete `resetQueries` Docs - -**Files:** -- Modify: `website/docs/query-client/resetQueries.mdx` - -- [x] **Step 1: Replace the placeholder page with complete reference content** - -Replace the whole file with: - -````mdx ---- -sidebar_label: resetQueries() ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# resetQueries(...) - -The method resets matching queries in the `QueryClient` cache and refetches active queries. -It is a strictly-typed wrapper around TanStack -[_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries). - -```ts -await api...resetQueries(filters, options); -``` - -## Arguments - -1. `filters?: QueryFiltersByParameters | QueryFiltersByQueryKey` - - Optional [_Query Filters 🌴_](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters), strictly-typed ✨ - - `filters.parameters: { path, query, header }` filters queries by operation parameters. - - `filters.queryKey: QueryKey` filters queries by an explicit typed query key instead of parameters. - - `filters.parameters` and `filters.queryKey` are mutually exclusive. - - `filters.infinite: boolean` filters regular or infinite query cache entries. - - `filters.predicate?: (query: Query) => boolean` applies custom matching after the typed filter. -2. `options?: ResetOptions` - - Optional TanStack reset options. - - See the TanStack [_queryClient.resetQueries(...) 🌴_](https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientresetqueries) documentation for more details. - -## Returns - -`Promise` - Resolves after matching active queries have been reset and refetched. - -## Example - - - - ```tsx - const parameters = { path: { petId: 123 } }; - - api.pet.getPetById.setQueryData(parameters, { - id: 123, - name: 'Rex', - }); - - await api.pet.getPetById.resetQueries({ - parameters, - infinite: false, - }); - ``` - - - ```tsx - const parameters = { path: { petId: 123 } }; - const queryKey = api.pet.getPetById.getQueryKey(parameters); - - await api.pet.getPetById.resetQueries({ - queryKey, - exact: true, - }); - ``` - - - ```tsx - await api.pet.getPetById.resetQueries({ - parameters: { path: { petId: 123 } }, - infinite: false, - predicate: (query) => query.state.status !== 'pending', - }); - ``` - - - ```tsx - await api.pet.getPetById.resetQueries( - { - parameters: { path: { petId: 123 } }, - infinite: false, - }, - { - cancelRefetch: false, - } - ); - ``` - - -```` - -- [x] **Step 2: Confirm the incorrect hook wording is gone** - -Run: - -```bash -rg -n "Hook|hook" website/docs/query-client/resetQueries.mdx -``` - -Expected: command exits with no matches. - -- [x] **Step 3: Check the page no longer contains the active-update notice** - -Run: - -```bash -rg -n "Documentation is actively being updated" website/docs/query-client/resetQueries.mdx -``` - -Expected: command exits with no matches. - -- [x] **Step 4: Commit Task 4** - -Run: - -```bash -git add website/docs/query-client/resetQueries.mdx -git commit -m "docs: complete resetQueries reference" -``` - -Expected: commit succeeds with only `resetQueries.mdx` staged. - -## Task 5: Current Docs Validation - -**Files:** -- Inspect: `website/docs/query-client/getQueryState.mdx` -- Inspect: `website/docs/query-client/getInfiniteQueryState.mdx` -- Inspect: `website/docs/query-client/setInfiniteQueryData.mdx` -- Inspect: `website/docs/query-client/resetQueries.mdx` - -- [x] **Step 1: Confirm the active-update notice is gone from current docs only** - -Run: - -```bash -rg -n "Documentation is actively being updated" website/docs -``` - -Expected: command exits with no matches. - -Do not run this check against `website/versioned_docs`; versioned docs are intentionally excluded. - -- [x] **Step 2: Check MDX lint for the website** - -Run: - -```bash -yarn workspace openapi-qraft-website lint -``` - -Expected: PASS. If it fails on pre-existing unrelated files, capture the exact unrelated failures and still run Task 5 Step 3. - -- [x] **Step 3: Check the Docusaurus build** - -Run: - -```bash -yarn workspace openapi-qraft-website build -``` - -Expected: PASS. If dependencies are unavailable in the worktree, report the missing dependency error and keep the static validation results. - -- [x] **Step 4: Check whitespace** - -Run: - -```bash -git diff --check -``` - -Expected: no output and exit code 0. - -- [x] **Step 5: Commit validation-only fixes if needed** - -If Task 5 Step 2, Step 3, or Step 4 required a small docs formatting fix, commit it: - -```bash -git add website/docs/query-client/getQueryState.mdx website/docs/query-client/getInfiniteQueryState.mdx website/docs/query-client/setInfiniteQueryData.mdx website/docs/query-client/resetQueries.mdx -git commit -m "docs: polish query client references" -``` - -Expected: commit succeeds only if there were validation fixes. If no fixes were needed, skip this commit. - -## Self-Review Notes - -- Spec coverage: all four target pages have dedicated tasks; versioned docs exclusion is covered in Task 5 Step 1. -- Placeholder scan: the plan contains no forbidden placeholder tokens or open-ended implementation steps. -- Type consistency: method argument and return descriptions are aligned with `ServiceOperationGetQueryState`, `ServiceOperationSetInfiniteQueryData`, and `ServiceOperationResetQueries`. diff --git a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md b/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md deleted file mode 100644 index fee56ccba..000000000 --- a/docs/superpowers/plans/2026-05-21-queryable-write-operations-docs-contract.md +++ /dev/null @@ -1,734 +0,0 @@ -# Queryable Write Operations Docs Contract Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Update current `website/docs` so queryable write operations clearly document `body` inside query parameters, query keys, and cache identity. - -**Architecture:** This is a documentation-only pass over current docs. Keep mutation invoke docs separate from query-surface docs, update signatures and short contract notes in place, and add a few high-signal examples instead of duplicating large examples on every page. - -**Tech Stack:** Docusaurus MDX, TanStack Query v5, Qraft generated React client docs, Yarn 4 workspace scripts. - ---- - -## File Structure - -- Modify: `website/docs/hooks/useQuery.mdx` - - Responsibility: keep the existing queryable write section, align its signature with the canonical `body` wording, and avoid implying all bodies are optional. -- Modify: `website/docs/hooks/useSuspenseQuery.mdx` - - Responsibility: mirror `useQuery` parameter wording for Suspense queries. -- Modify: `website/docs/hooks/useInfiniteQuery.mdx` - - Responsibility: mirror queryable write parameter wording for infinite queries. -- Modify: `website/docs/hooks/useSuspenseInfiniteQuery.mdx` - - Responsibility: mirror queryable write parameter wording for Suspense infinite queries. -- Modify: `website/docs/hooks/useQueries.mdx` - - Responsibility: document `parameters.body` in query lists and add a concrete multi-query body example. -- Modify: `website/docs/hooks/useSuspenseQueries.mdx` - - Responsibility: document `parameters.body` in Suspense query lists and link the cache identity concept to `useQueries`. -- Modify: `website/docs/query-client/fetchQuery.mdx` - - Responsibility: document body-bearing query parameters for direct fetching and add a concrete writable query example. -- Modify: `website/docs/query-client/fetchInfiniteQuery.mdx` - - Responsibility: document body-bearing query parameters for infinite fetching. -- Modify: `website/docs/query-client/ensureQueryData.mdx` - - Responsibility: mirror `fetchQuery` parameter wording because it uses the same query identity contract. -- Modify: `website/docs/query-client/ensureInfiniteQueryData.mdx` - - Responsibility: mirror `fetchInfiniteQuery` parameter wording. -- Modify: `website/docs/query-client/getQueryKey.mdx` - - Responsibility: document `body` as part of normal query key identity and add a concrete queryable write example. -- Modify: `website/docs/query-client/getInfiniteQueryKey.mdx` - - Responsibility: document `body` as part of infinite query key identity. -- Modify: `website/docs/query-client/getQueryData.mdx` - - Responsibility: document `body` in cache lookup parameters. -- Modify: `website/docs/query-client/getInfiniteQueryData.mdx` - - Responsibility: document `body` in infinite cache lookup parameters. -- Modify: `website/docs/query-client/getQueryState.mdx` - - Responsibility: document `body` in query state lookup parameters. -- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` - - Responsibility: document `body` in infinite query state lookup parameters. -- Modify: `website/docs/query-client/setQueryData.mdx` - - Responsibility: document `body` in normal cache write parameters and show cache identity with body. -- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` - - Responsibility: document `body` in infinite cache write parameters. -- Modify: `website/docs/query-client/setQueriesData.mdx` - - Responsibility: document `body` in query filter parameters for cache writes. -- Modify: `website/docs/query-client/invalidateQueries.mdx` - - Responsibility: document `body` in query filter parameters. -- Modify: `website/docs/query-client/refetchQueries.mdx` - - Responsibility: document `body` in query filter parameters. -- Modify: `website/docs/query-client/cancelQueries.mdx` - - Responsibility: document `body` in query filter parameters. -- Modify: `website/docs/query-client/removeQueries.mdx` - - Responsibility: document `body` in query filter parameters. -- Modify: `website/docs/query-client/resetQueries.mdx` - - Responsibility: document `body` in query filter parameters. -- Modify: `website/docs/query-client/isFetching.mdx` - - Responsibility: document `body` in query filter parameters. -- Do not modify: `website/versioned_docs/*` - - Responsibility: historical docs are intentionally excluded from this pass. -- Do not modify mutation invoke pages unless a short boundary note is needed: - - `website/docs/hooks/useMutation.mdx` - - `website/docs/core/mutation-operation.mdx` - - Mutation invoke calls keep `body` as a top-level argument. - -## Shared Text Snippets - -Use these exact snippets when updating pages. Keep them short and repeat them inline; do not add a new MDX partial unless implementation discovers an existing docs convention for shared snippets. - -### Query Parameter Contract - -```md -For operations generated with `--queryable-write-operations`, query parameters may also include `body`. -In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods. -Mutation calls keep `body` as a separate top-level argument. -``` - -### Query Parameter Signature - -```md -`parameters: { path, query, header, body } | QueryKey | void` -``` - -### Infinite Query Parameter Signature - -```md -`parameters: { path, query, header, body } | InfiniteQueryKey | void` -``` - -### Query Filter Parameter Text - -```md -- `filters.parameters: { path, query, header, body }` filters queries by operation parameters. -- For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. -``` - -## Task 1: Align Single Query Hook Parameter Contracts - -**Files:** -- Modify: `website/docs/hooks/useQuery.mdx` -- Modify: `website/docs/hooks/useSuspenseQuery.mdx` -- Modify: `website/docs/hooks/useInfiniteQuery.mdx` -- Modify: `website/docs/hooks/useSuspenseInfiniteQuery.mdx` - -- [x] **Step 1: Update `useQuery` argument wording** - -In `website/docs/hooks/useQuery.mdx`, replace the current first argument block with: - -```md -1. `parameters: { path, query, header, body } | QueryKey | void` - - **Required only if OpenAPI specification defines required parameters** - - If the operation has no required parameters according to OpenAPI, you can omit this argument - - `parameters` will be used to generate the `QueryKey` - - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - - In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods - - Mutation calls keep `body` as a separate top-level argument - - Instead of an object with `{ path, query, header, body }`, you can pass a `QueryKey` as an array - which is also strictly-typed -``` - -- [x] **Step 2: Update `useSuspenseQuery` argument wording** - -In `website/docs/hooks/useSuspenseQuery.mdx`, replace the current first argument block with: - -```md -1. `parameters: { path, query, header, body } | QueryKey | void` - - **Required only if OpenAPI specification defines required parameters** - - If the operation has no required parameters according to OpenAPI, you can omit this argument - - `parameters` will be used to generate the `QueryKey` - - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - - In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods - - Mutation calls keep `body` as a separate top-level argument - - Instead of an object with `{ path, query, header, body }`, you can pass a `QueryKey` as an array - which is also strictly-typed ✨ -``` - -- [x] **Step 3: Update infinite hook argument wording** - -In both `website/docs/hooks/useInfiniteQuery.mdx` and `website/docs/hooks/useSuspenseInfiniteQuery.mdx`, replace the current first argument block with: - -```md -1. `parameters: { path, query, header, body } | InfiniteQueryKey | undefined` - - **Required only if OpenAPI specification defines required parameters** - - If the operation has no required parameters according to OpenAPI, you can omit this argument - - `parameters` will be used to generate the _Infinite Query Key_ - - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - - In that mode, `body` is part of the infinite query key and cache identity - - Mutation calls keep `body` as a separate top-level argument - - Instead of an object with `{ path, query, header, body }`, you can pass a typed `InfiniteQueryKey` from `getInfiniteQueryKey(...)` - which is also strictly-typed ✨ -``` - -- [x] **Step 4: Run a focused grep for old hook wording** - -Run: - -```bash -rg -n "\\{path, query, header\\}|\\{ path, query, header \\}" website/docs/hooks/useQuery.mdx website/docs/hooks/useSuspenseQuery.mdx website/docs/hooks/useInfiniteQuery.mdx website/docs/hooks/useSuspenseInfiniteQuery.mdx -``` - -Expected: no matches for the four files in this task. - -- [x] **Step 5: Commit Task 1** - -Run: - -```bash -git add website/docs/hooks/useQuery.mdx website/docs/hooks/useSuspenseQuery.mdx website/docs/hooks/useInfiniteQuery.mdx website/docs/hooks/useSuspenseInfiniteQuery.mdx -git commit -m "docs: clarify queryable write hook parameters" -``` - -Expected: commit succeeds with only the four hook docs staged. - -## Task 2: Document Body-Aware Multi-Query Hooks - -**Files:** -- Modify: `website/docs/hooks/useQueries.mdx` -- Modify: `website/docs/hooks/useSuspenseQueries.mdx` - -- [x] **Step 1: Add tab imports to `useQueries`** - -In `website/docs/hooks/useQueries.mdx`, add these imports after the frontmatter and before `# useQueries(...)`: - -```mdx -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -``` - -- [x] **Step 2: Update `useQueries` query list wording** - -In `website/docs/hooks/useQueries.mdx`, replace the `options.queries` sub-bullets with: - -```md - - `options.queries: QueryOptions[]` - - **Required** array of _Queries_ to be executed - - `parameters: { path, query, header, body }` will be used for the request - - For operations generated with `--queryable-write-operations`, `body` is part of the query key and cache identity - - `queryKey: QueryKey` will be used for the request instead of the `parameters` - - `queryKey` and `parameters` are mutually exclusive -``` - -- [x] **Step 3: Add a writable operation tab to `useQueries`** - -Replace the single `### Example` code block in `website/docs/hooks/useQueries.mdx` with a `Tabs` block. Keep the existing GET example as the first tab and add this second tab: - -````mdx - - - ```tsx - import { createAPIClient } from './api'; // generated by OpenAPI Qraft - - import { requestFn } from '@openapi-qraft/react'; - import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - - const queryClient = new QueryClient(); - - const api = createAPIClient({ - requestFn, - queryClient, - baseUrl: 'https://api.sandbox.monite.com/v1', - }); - - const useEntityQueries = () => { - return api.entities.getEntities.useQueries({ - queries: [ - { - parameters: { - header: { 'x-monite-version': '2023-09-01' }, - path: { entity_id: '3e3e-3e3e-3e3e' }, - }, - }, - { - parameters: { - header: { 'x-monite-version': '2023-09-01' }, - path: { entity_id: '5c5c-5c5c-5c5c' }, - }, - }, - ], - combine: (results) => results.map((result) => result.data), - }); - }; - ``` - - With body}> - ```tsx - const firstSearch = { - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { - name: 'New Name', - description: 'New Description', - }, - }; - - const secondSearchParameters = { - ...firstSearch, - body: { - name: 'Another Name', - description: 'Another Description', - }, - }; - - const secondSearchQueryKey = - api.approvalPolicies.patchApprovalPoliciesId.getQueryKey( - secondSearchParameters - ); - - const results = api.approvalPolicies.patchApprovalPoliciesId.useQueries({ - queries: [ - { parameters: firstSearch }, - { queryKey: secondSearchQueryKey }, - ], - }); - - // Never pass `secondSearchParameters` as `queryKey` directly. - // `getQueryKey(...)` builds the tuple shape TanStack Query expects. - // `firstSearch.body` and `secondSearchParameters.body` produce different cache entries. - ``` - - -```` - -- [x] **Step 4: Update `useSuspenseQueries` query list wording** - -In `website/docs/hooks/useSuspenseQueries.mdx`, replace the `options.queries` sub-bullets with: - -```md - - `options.queries: QueryOptions[]` - - **Required** array of _Queries_ to be executed - - `parameters: { path, query, header, body }` will be used for the request - - For operations generated with `--queryable-write-operations`, `body` is part of the query key and cache identity - - `queryKey: QueryKey` will be used for the request instead of the `parameters` - - `queryKey` and `parameters` are mutually exclusive -``` - -- [x] **Step 5: Add a short body example note to `useSuspenseQueries`** - -After the existing example in `website/docs/hooks/useSuspenseQueries.mdx`, add: - -````mdx -### Queryable Write Operations - -For operations generated with `--queryable-write-operations`, `useSuspenseQueries` accepts the same `parameters.body` -shape as `useQueries`. Each distinct body is part of the query key and creates a distinct cache entry. - -```tsx -const queryKey = - api.approvalPolicies.patchApprovalPoliciesId.getQueryKey({ - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { name: 'Another Name' }, - }); - -const results = api.approvalPolicies.patchApprovalPoliciesId.useSuspenseQueries({ - queries: [ - { - parameters: { - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { name: 'New Name' }, - }, - }, - { queryKey }, - ], -}); -``` -```` - -- [x] **Step 6: Run focused grep** - -Run: - -```bash -rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ path, query, header \\}" website/docs/hooks/useQueries.mdx website/docs/hooks/useSuspenseQueries.mdx -``` - -Expected: no matches. - -- [x] **Step 7: Commit Task 2** - -Run: - -```bash -git add website/docs/hooks/useQueries.mdx website/docs/hooks/useSuspenseQueries.mdx -git commit -m "docs: show body in multi-query hooks" -``` - -Expected: commit succeeds with only the two multi-query docs staged. - -## Task 3: Align Fetch and Ensure Query-Client Methods - -**Files:** -- Modify: `website/docs/query-client/fetchQuery.mdx` -- Modify: `website/docs/query-client/fetchInfiniteQuery.mdx` -- Modify: `website/docs/query-client/ensureQueryData.mdx` -- Modify: `website/docs/query-client/ensureInfiniteQueryData.mdx` - -- [x] **Step 1: Update normal fetch argument blocks** - -In both `fetchQuery.mdx` and `ensureQueryData.mdx`, replace the first `parameters` bullet with: - -```md -1. - `parameters: { path, query, header, body } | QueryKey | void` - - **Required**, OpenAPI request parameters for the query, strictly-typed ✨ - - `parameters` will be used to generate the `QueryKey` - - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - - In that mode, `body` is part of the query key and cache identity for query-client methods - - Mutation calls keep `body` as a separate top-level argument -``` - -Keep the existing `requestFn`, `baseUrl`, and options bullets after this block. - -- [x] **Step 2: Add a writable `fetchQuery` example tab** - -In `website/docs/query-client/fetchQuery.mdx`, add this tab after the existing basic tab: - -````mdx - With body}> - ```ts - const policy = await api.approvalPolicies.patchApprovalPoliciesId.fetchQuery({ - parameters: { - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { - name: 'New Name', - description: 'New Description', - }, - }, - }); - ``` - -```` - -- [x] **Step 3: Update infinite fetch argument blocks** - -In both `fetchInfiniteQuery.mdx` and `ensureInfiniteQueryData.mdx`, replace the first `parameters` bullet with: - -```md -1. - `parameters: { path, query, header, body } | InfiniteQueryKey | void` - - OpenAPI request parameters for the query, strictly-typed ✨ - - `parameters` will be used to generate the _Infinite Query Key_ - - For operations generated with `--queryable-write-operations`, query parameters may also include `body` - - In that mode, `body` is part of the infinite query key and cache identity - - Mutation calls keep `body` as a separate top-level argument -``` - -Keep the existing fetch options bullets after this block. - -- [x] **Step 4: Run focused grep** - -Run: - -```bash -rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query-client/fetchQuery.mdx website/docs/query-client/fetchInfiniteQuery.mdx website/docs/query-client/ensureQueryData.mdx website/docs/query-client/ensureInfiniteQueryData.mdx -``` - -Expected: no matches. - -- [x] **Step 5: Commit Task 3** - -Run: - -```bash -git add website/docs/query-client/fetchQuery.mdx website/docs/query-client/fetchInfiniteQuery.mdx website/docs/query-client/ensureQueryData.mdx website/docs/query-client/ensureInfiniteQueryData.mdx -git commit -m "docs: clarify body in query fetching methods" -``` - -Expected: commit succeeds with only the four fetch and ensure docs staged. - -## Task 4: Align Query Key, Data, State, and Cache Write Methods - -**Files:** -- Modify: `website/docs/query-client/getQueryKey.mdx` -- Modify: `website/docs/query-client/getInfiniteQueryKey.mdx` -- Modify: `website/docs/query-client/getQueryData.mdx` -- Modify: `website/docs/query-client/getInfiniteQueryData.mdx` -- Modify: `website/docs/query-client/getQueryState.mdx` -- Modify: `website/docs/query-client/getInfiniteQueryState.mdx` -- Modify: `website/docs/query-client/setQueryData.mdx` -- Modify: `website/docs/query-client/setInfiniteQueryData.mdx` - -- [x] **Step 1: Update normal query key/data/state signatures** - -In `getQueryData.mdx`, `getQueryState.mdx`, and `setQueryData.mdx`, replace normal query parameter signatures and nearby QueryKey prose with: - -```md -`parameters: { path, query, header, body } | QueryKey | void` - -For operations generated with `--queryable-write-operations`, query parameters may also include `body`. -In that mode, `body` is part of the query key and cache identity for query-client methods. -Instead of an object with `{ path, query, header, body }`, you can pass a typed `QueryKey` array. -``` - -Use `| QueryKey` without `| void` in `setQueryData.mdx` if the existing method signature does not accept `void`. - -In `getQueryKey.mdx`, keep the argument signature limited to operation parameters: - -```md -`parameters: { path, query, header, body } | void` - -For operations generated with `--queryable-write-operations`, query parameters may also include `body`. -In that mode, `body` is part of the query key and cache identity for query-client methods. -The returned `QueryKey` can be passed to query-client methods that accept typed query key arrays. -``` - -- [x] **Step 2: Add a body cache identity example to `getQueryKey`** - -Add this tab to `website/docs/query-client/getQueryKey.mdx`: - -````mdx - With body}> - ```tsx - const queryKey = - api.approvalPolicies.patchApprovalPoliciesId.getQueryKey({ - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { - name: 'New Name', - description: 'New Description', - }, - }); - - expect(queryKey[1]).toEqual({ - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { - name: 'New Name', - description: 'New Description', - }, - }); - ``` - -```` - -- [x] **Step 3: Add a body cache write/read example to `setQueryData`** - -Add this tab to `website/docs/query-client/setQueryData.mdx`: - -````mdx - With body}> - ```tsx - const parameters = { - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { - name: 'New Name', - description: 'New Description', - }, - }; - - api.approvalPolicies.patchApprovalPoliciesId.setQueryData(parameters, { - id: '2', - name: 'New Name', - description: 'New Description', - }); - - const policy = - api.approvalPolicies.patchApprovalPoliciesId.getQueryData(parameters); - - expect(policy?.name).toEqual('New Name'); - ``` - -```` - -- [x] **Step 4: Update infinite key/data/state/cache signatures** - -In `getInfiniteQueryData.mdx`, `getInfiniteQueryState.mdx`, and `setInfiniteQueryData.mdx`, replace infinite query parameter signatures and nearby query key prose with: - -```md -`parameters: { path, query, header, body } | InfiniteQueryKey | void` - -For operations generated with `--queryable-write-operations`, query parameters may also include `body`. -In that mode, `body` is part of the infinite query key and cache identity. -Instead of an object with `{ path, query, header, body }`, you can pass a typed infinite query key from `getInfiniteQueryKey(...)`. -``` - -Use `| InfiniteQueryKey` without `| void` in `setInfiniteQueryData.mdx` if the existing method signature does not accept `void`. - -In `getInfiniteQueryKey.mdx`, keep the argument signature limited to operation parameters: - -```md -`parameters: { path, query, header, body } | void` - -For operations generated with `--queryable-write-operations`, query parameters may also include `body`. -In that mode, `body` is part of the infinite query key and cache identity. -The returned `InfiniteQueryKey` can be passed to query-client methods that accept typed infinite query key arrays. -``` - -- [x] **Step 5: Run focused grep** - -Run: - -```bash -rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query-client/getQueryKey.mdx website/docs/query-client/getInfiniteQueryKey.mdx website/docs/query-client/getQueryData.mdx website/docs/query-client/getInfiniteQueryData.mdx website/docs/query-client/getQueryState.mdx website/docs/query-client/getInfiniteQueryState.mdx website/docs/query-client/setQueryData.mdx website/docs/query-client/setInfiniteQueryData.mdx -``` - -Expected: no stale matches. If an example intentionally shows mutation invoke arguments, keep it and note it in the task summary. - -- [x] **Step 6: Commit Task 4** - -Run: - -```bash -git add website/docs/query-client/getQueryKey.mdx website/docs/query-client/getInfiniteQueryKey.mdx website/docs/query-client/getQueryData.mdx website/docs/query-client/getInfiniteQueryData.mdx website/docs/query-client/getQueryState.mdx website/docs/query-client/getInfiniteQueryState.mdx website/docs/query-client/setQueryData.mdx website/docs/query-client/setInfiniteQueryData.mdx -git commit -m "docs: clarify body in query cache identity" -``` - -Expected: commit succeeds with only the eight query key/cache docs staged. - -## Task 5: Align Query Filter Pages - -**Files:** -- Modify: `website/docs/query-client/setQueriesData.mdx` -- Modify: `website/docs/query-client/invalidateQueries.mdx` -- Modify: `website/docs/query-client/refetchQueries.mdx` -- Modify: `website/docs/query-client/cancelQueries.mdx` -- Modify: `website/docs/query-client/removeQueries.mdx` -- Modify: `website/docs/query-client/resetQueries.mdx` -- Modify: `website/docs/query-client/isFetching.mdx` - -- [x] **Step 1: Update filter parameter bullets across filter pages** - -In each file listed for this task, replace every query filter parameter bullet that currently says: - -```md -- `filters.parameters: { path, query, header }` will be used for filtering queries by parameters -``` - -or: - -```md -- `filters.parameters: { path, query, header }` filters queries by operation parameters. -``` - -with: - -```md -- `filters.parameters: { path, query, header, body }` filters queries by operation parameters. -- For operations generated with `--queryable-write-operations`, `body` can be included in `filters.parameters` and participates in query cache identity. -``` - -- [x] **Step 2: Update setQueriesData QueryKey prose** - -In `website/docs/query-client/setQueriesData.mdx`, replace: - -```md -It's also possible to use a `QueryKey` as an array instead of an object with `{path, query, header}`: -``` - -with: - -```md -It's also possible to use a `QueryKey` as an array instead of an object with `{ path, query, header, body }`: -``` - -- [x] **Step 3: Add one filter example with body** - -Add this short example after the first filter example in `website/docs/query-client/isFetching.mdx`: - -````mdx - For queryable write operations, `body` can be part of the filter parameters: - - ```ts - const matchingPolicySearches = - api.approvalPolicies.patchApprovalPoliciesId.isFetching({ - infinite: false, - parameters: { - header: { 'x-monite-version': '1' }, - path: { approval_policy_id: '2' }, - body: { name: 'New Name' }, - }, - }); - ``` -```` - -- [x] **Step 4: Run focused grep** - -Run: - -```bash -rg -n "\\{ path, query, header \\}|\\{path, query, header\\}" website/docs/query-client/setQueriesData.mdx website/docs/query-client/invalidateQueries.mdx website/docs/query-client/refetchQueries.mdx website/docs/query-client/cancelQueries.mdx website/docs/query-client/removeQueries.mdx website/docs/query-client/resetQueries.mdx website/docs/query-client/isFetching.mdx -``` - -Expected: no stale query-filter matches. - -- [x] **Step 5: Commit Task 5** - -Run: - -```bash -git add website/docs/query-client/setQueriesData.mdx website/docs/query-client/invalidateQueries.mdx website/docs/query-client/refetchQueries.mdx website/docs/query-client/cancelQueries.mdx website/docs/query-client/removeQueries.mdx website/docs/query-client/resetQueries.mdx website/docs/query-client/isFetching.mdx -git commit -m "docs: clarify body in query filters" -``` - -Expected: commit succeeds with only the seven filter docs staged. - -## Task 6: Boundary Review and Validation - -**Files:** -- Inspect: `website/docs` -- Do not inspect as blockers: `website/versioned_docs/*` - -- [x] **Step 1: Run scoped stale wording search** - -Run: - -```bash -rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ path, query, header \\}" website/docs -``` - -Expected: remaining matches are only mutation-specific docs or intentionally unchanged mutation examples. Record the allowed files in the final summary. Query-surface matches should be fixed before continuing. - -- [x] **Step 2: Check mutation boundary wording** - -Run: - -```bash -rg -n "body.*separate top-level|Mutation calls keep `body`|parameters\\.body" website/docs/hooks website/docs/query-client website/docs/core -``` - -Expected: query-surface pages explain `parameters.body`; mutation-boundary notes say mutation calls keep `body` top-level. There should be no mutation page claiming `parameters.body` for invoke calls. - -- [x] **Step 3: Run website lint** - -Run: - -```bash -yarn workspace openapi-qraft-website lint -``` - -Expected: PASS. - -- [x] **Step 4: Run website build** - -Run: - -```bash -yarn workspace openapi-qraft-website build -``` - -Expected: PASS. - -- [x] **Step 5: Check whitespace** - -Run: - -```bash -git diff --check -``` - -Expected: no output and exit code 0. - -- [x] **Step 6: Commit validation fixes if needed** - -If validation required small formatting or wording fixes, commit them: - -```bash -git add website/docs -git commit -m "docs: polish queryable write operation wording" -``` - -Expected: commit succeeds only if validation fixes were made. If no fixes were needed, skip this commit. - -## Self-Review Notes - -- Spec coverage: hooks, multi-query hooks, fetch/ensure methods, query key/cache helpers, query filters, mutation boundary, current-docs-only validation, and versioned docs exclusion are all represented. -- Placeholder scan: the plan contains no forbidden placeholder tokens or open-ended implementation steps. -- Type consistency: query surfaces use `parameters.body`; mutation invoke boundary keeps top-level `body`; infinite query surfaces use infinite query key wording. diff --git a/docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md b/docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md deleted file mode 100644 index ebb734900..000000000 --- a/docs/superpowers/specs/2026-05-21-query-client-docs-completion-design.md +++ /dev/null @@ -1,85 +0,0 @@ -# Query Client Docs Completion Design - -## Context - -The current documentation under `website/docs` has four query-client pages that still show the active-update notice: - -- `website/docs/query-client/getQueryState.mdx` -- `website/docs/query-client/resetQueries.mdx` -- `website/docs/query-client/getInfiniteQueryState.mdx` -- `website/docs/query-client/setInfiniteQueryData.mdx` - -These pages are part of the current docs and should be completed. Versioned documentation under `website/versioned_docs/*` is intentionally out of scope. If older versioned docs still contain the same notice, leave them unchanged so users are guided toward the current documentation for the most accurate contract. - -## Goal - -Complete the four current query-client reference pages so they match the surrounding documentation quality: - -- explain what the Qraft method does; -- point to the matching TanStack Query `QueryClient` API; -- document arguments and return values; -- show concrete examples using the existing `api` or `qraft` naming conventions; -- remove the active-update notice from the current docs pages. - -## Scope - -In scope: - -- Rewrite the four listed current docs pages. -- Make small, directly related consistency fixes in nearby query-client docs when the page being completed references them. -- Keep examples domain-specific and aligned with existing docs patterns, primarily `pet` and `files`. -- Validate that `website/docs` no longer contains `Documentation is actively being updated`. - -Out of scope: - -- Editing `website/versioned_docs/*`. -- Broad stylistic rewrites across the full query-client section. -- Changing generated code, runtime behavior, or public types. -- Adding new docs infrastructure. - -## Page Design - -### `getQueryState` - -Document it as a typed wrapper around `queryClient.getQueryState`. It accepts operation parameters, a typed `QueryKey`, or `void` for operations without required parameters. It returns the current query state or `undefined` when the query is not in the cache. - -Examples should cover reading state after cached data exists and using a typed query key. - -### `resetQueries` - -Document it as a typed wrapper around `queryClient.resetQueries`. It operates on query filters, not a single direct request. The filters should mirror the nearby `cancelQueries`, `removeQueries`, and `invalidateQueries` docs: - -- `filters.parameters` for operation parameters; -- `filters.queryKey` for an explicit typed query key; -- `filters.infinite` to distinguish regular and infinite query cache entries; -- `filters.predicate` for custom matching. - -The page must not call this method a hook. It should mention that it returns `Promise` and accepts TanStack reset options as the second argument. - -### `getInfiniteQueryState` - -Document it as the infinite-query counterpart to `getQueryState`. It still maps to TanStack `queryClient.getQueryState`, but uses the infinite query key shape and returns state for `OperationInfiniteData`-style cache data. - -Examples should show the method after an infinite query cache entry has been created and should make the `pages` / `pageParams` shape visible. - -### `setInfiniteQueryData` - -Document it as the infinite-query counterpart to `setQueryData`. It writes directly to the cache for one infinite query and accepts parameters or a typed infinite query key, an updater or direct value, and optional TanStack set-data options. - -Examples should show both direct replacement and functional update of `pages` / `pageParams` data. - -## Validation - -After implementation: - -- Run a scoped grep that checks only `website/docs` for `Documentation is actively being updated`. -- Run `git diff --check`. -- Run the repository's docs check/build only if there is a clear local command for it; otherwise record that static docs validation was used. - -Versioned docs are excluded from the active-update grep on purpose. - -## Risks - -- The generated type surface includes optional parameters for some operations, so examples should avoid implying that every operation requires parameters. -- Infinite-query examples can become too abstract if they only reference TanStack. They should show the Qraft-specific `pages` / `pageParams` cache data shape. -- A broad docs sweep could create unnecessary review noise. Keep related cleanup narrow. diff --git a/docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md b/docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md deleted file mode 100644 index 35ac41ee6..000000000 --- a/docs/superpowers/specs/2026-05-21-queryable-write-operations-docs-contract-design.md +++ /dev/null @@ -1,149 +0,0 @@ -# Queryable Write Operations Docs Contract Design - -## Context - -Qraft supports `--queryable-write-operations`, which generates query hooks and query-client methods for writable HTTP operations such as `POST`, `PUT`, and `PATCH`. In that mode, request `body` becomes part of the query parameters shape for the query surface: - -```ts -parameters: { path, query, header, body } | QueryKey | void -``` - -This is already covered by runtime tests, generated fixtures, and generated TSDoc examples. The current hand-written documentation under `website/docs` only documents this clearly in parts of `hooks/useQuery.mdx`; many other query hooks, query-client methods, cache helpers, and query filters still describe the parameters as `{ path, query, header }`. - -Versioned documentation under `website/versioned_docs/*` is out of scope and should remain unchanged. - -## Goal - -Make current `website/docs` accurately describe how `body` works for queryable write operations across the query surface. - -The docs should make three facts clear: - -- Queryable write operations can pass `body` inside `parameters` for query hooks and query-client methods. -- `body` participates in query key and cache identity. -- Mutation invoke calls keep `body` as a separate top-level argument and should not be documented as accepting `body` inside `parameters`. - -## Scope - -In scope: - -- Update current docs under `website/docs` only. -- Update query hook docs where parameter shapes or query lists are described: - - `website/docs/hooks/useQuery.mdx` - - `website/docs/hooks/useSuspenseQuery.mdx` - - `website/docs/hooks/useQueries.mdx` - - `website/docs/hooks/useSuspenseQueries.mdx` - - `website/docs/hooks/useInfiniteQuery.mdx` - - `website/docs/hooks/useSuspenseInfiniteQuery.mdx` -- Update query-client docs where query parameters, query keys, cache identity, or query filters are described: - - `fetchQuery`, `fetchInfiniteQuery` - - `ensureQueryData`, `ensureInfiniteQueryData` - - `getQueryKey`, `getInfiniteQueryKey` - - `getQueryData`, `getInfiniteQueryData` - - `getQueryState`, `getInfiniteQueryState` - - `setQueryData`, `setInfiniteQueryData`, `setQueriesData` - - `invalidateQueries`, `refetchQueries`, `cancelQueries`, `removeQueries`, `resetQueries`, `isFetching` -- Add concrete examples that show writable query operations with `body` in `parameters`. -- Keep the previous rule that active current docs are the source of truth, not versioned docs. - -Out of scope: - -- Editing `website/versioned_docs/*`. -- Changing generated code, runtime behavior, type definitions, snapshots, or tests. -- Rewriting mutation docs to use query-style `parameters.body`. -- Broad prose cleanup unrelated to queryable write operation body handling. - -## Contract Wording - -Use one consistent contract across the affected pages: - -```md -For operations generated with `--queryable-write-operations`, query parameters may also include `body`. -In that mode, `body` is part of the query key and cache identity for query hooks and query-client methods. -Mutation calls keep `body` as a separate top-level argument. -``` - -Reference signatures should use one of these shapes when the page describes query-surface parameters: - -```ts -parameters: { path, query, header, body } | QueryKey | void -``` - -```ts -filters.parameters: { path, query, header, body } -``` - -When a page needs to emphasize OpenAPI optionality, use prose rather than spelling `body?` everywhere. The actual generated type decides whether `body` is required or optional for a specific operation. - -## Example Design - -Add examples where they answer a user question directly instead of duplicating the same snippet everywhere. - -### `useQueries` - -Show two writable query entries for the same operation: - -- one entry passes `parameters` with `body`; -- one entry passes a `queryKey` created from parameters with a different `body`; -- the example explains that the two bodies produce different cache entries. - -### `fetchQuery` - -Show a writable operation where `fetchQuery({ parameters: { path, header, body } })` sends the body while still using query caching. - -### `getQueryKey` and Cache Helpers - -Show `getQueryKey(parametersWithBody)` and then reuse the same parameters with `setQueryData` / `getQueryData` or `getQueryState`. The point is to make `body` visible as part of cache identity, not only as transport input. - -## Mutation Boundary - -Mutation pages should not be mechanically changed from: - -```ts -parameters?: { path, query, header } -``` - -to: - -```ts -parameters?: { path, query, header, body } -``` - -For mutation invoke calls, `body` remains top-level: - -```ts -api.approvalPolicies.patchApprovalPoliciesId({ - parameters: { - path: { approval_policy_id: '2' }, - header: { 'x-monite-version': '1' }, - }, - body: { - name: 'New Name', - }, -}); -``` - -If mutation docs are touched, it should only be to add a short clarification that `parameters.body` belongs to queryable write operations, not mutation invoke calls. - -## Validation - -After implementation: - -- Run a scoped search over `website/docs` for stale query-surface wording: - -```bash -rg -n "\\{ path, query, header \\}|\\{path, query, header\\}|parameters: \\{ path, query, header \\}" website/docs -``` - -- Review remaining matches manually. Matches are allowed when they are mutation-only docs or otherwise intentionally not query-surface. -- Run `yarn workspace openapi-qraft-website lint`. -- Run `yarn workspace openapi-qraft-website build`. -- Run `git diff --check`. - -Do not use `website/versioned_docs/*` as a blocker for this validation. - -## Risks - -- Updating all `{ path, query, header }` text mechanically would incorrectly document mutation invoke calls. -- Using `body?` everywhere can imply all writable query operation bodies are optional. The generated type decides requiredness from OpenAPI. -- Adding too many examples can make reference pages noisy. Prefer one strong body example per workflow family and concise cross-page notes elsewhere. -- Query filters can match by partial parameters, so wording should say `body` can be included in filters for queryable write operations without implying it is always required. From a3eb27e3e67f6a437a150139c57a64d37636b8e3 Mon Sep 17 00:00:00 2001 From: Alex Batalov Date: Sun, 24 May 2026 23:26:28 +0400 Subject: [PATCH 22/22] docs: update spelling expect file with corrected terms --- .github/actions/spelling/expect.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 137234a3a..e01246ae5 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -75,7 +75,7 @@ radist reate redocly refetched -Refetches +refetches remarkjs remarkrc reqid @@ -102,6 +102,7 @@ TMeta TMutation TOperation TPage +TParameters TParams TQuery TRequest