{"_id":"@avandar/query-hooks","_rev":"3-db428fed1dfd6ac4f746289998730293","name":"@avandar/query-hooks","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@avandar/query-hooks","version":"0.1.0","license":"MIT","_id":"@avandar/query-hooks@0.1.0","maintainers":[{"name":"jpsyx","email":"pablowritescode@gmail.com"}],"homepage":"https://github.com/AvandarLabs/avandar/tree/main/packages/web/query-hooks#readme","bugs":{"url":"https://github.com/AvandarLabs/avandar/issues"},"dist":{"shasum":"432eaad57a9ece0c342a660e62ee70aef6b80cd6","tarball":"https://registry.npmjs.org/@avandar/query-hooks/-/query-hooks-0.1.0.tgz","fileCount":6,"integrity":"sha512-1tj4JIZ81clDN+5LMgqkvrNGSdy9/jM6/ojGfUUjz3OLzqy0ZTkglvGDLrGsut/FTjzrQbpk99rNDfgzys+Wrw==","signatures":[{"sig":"MEUCIQCAae6NWO9nEKLuTBeb8Vaenw1btNBnJPQ4UkkZeNg9qAIgJQLH2FUVaZC/vFVqoW55mVZ6yQ5wlKkryGJPMLdsnqM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@avandar%2fquery-hooks@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":76196},"type":"module","_from":"file:avandar-query-hooks-0.1.0.tgz","engines":{"node":">=22.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsup","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"jpsyx","email":"pablowritescode@gmail.com"},"_resolved":"/tmp/3122de1bcf22f62bcd53d8199c536f3a/avandar-query-hooks-0.1.0.tgz","_integrity":"sha512-1tj4JIZ81clDN+5LMgqkvrNGSdy9/jM6/ojGfUUjz3OLzqy0ZTkglvGDLrGsut/FTjzrQbpk99rNDfgzys+Wrw==","repository":{"url":"git+https://github.com/AvandarLabs/avandar.git","type":"git","directory":"packages/web/query-hooks"},"_npmVersion":"11.12.1","description":"Avandar conventions layered over TanStack Query: useQuery/useMutation wrappers and a withQueryHooks client augmenter","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"type-fest":"^5.4.4","@avandar/utils":"0.1.0","@avandar/clients":"0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","jsdom":"^26.1.0","react":"19.2.5","vitest":"^3.2.4","react-dom":"19.2.5","typescript":"~5.9.3","@tanstack/react-query":"^5.81.5","@testing-library/react":"^16.3.0"},"peerDependencies":{"react":"^19.0.0","@tanstack/react-query":"^5.81.5"},"_npmOperationalInternal":{"tmp":"tmp/query-hooks_0.1.0_1786411751944_0.1170038853416071","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@avandar/query-hooks","version":"0.1.1","license":"MIT","_id":"@avandar/query-hooks@0.1.1","maintainers":[{"name":"jpsyx","email":"pablowritescode@gmail.com"}],"homepage":"https://github.com/AvandarLabs/avandar/tree/main/packages/web/query-hooks#readme","bugs":{"url":"https://github.com/AvandarLabs/avandar/issues"},"dist":{"shasum":"0dbe776bf1a714279a6b26116ab0e30c1567a372","tarball":"https://registry.npmjs.org/@avandar/query-hooks/-/query-hooks-0.1.1.tgz","fileCount":6,"integrity":"sha512-kpY86OKdMRqhPlJzrPcS0J6DeZA4Jo69rO/tTuN3d2+X3g52UC4HnZgqNbFTbl2cPluf64e38gZU4VqF9V9vIQ==","signatures":[{"sig":"MEYCIQDskOvlk3hDsPpyixh+tu/cRRSWNge5OICq4fUkuXuw5wIhAKr4mj49KE25/8LAPFGB/asdKLJEeC5L69BuIDl+6A4C","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@avandar%2fquery-hooks@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":76196},"type":"module","_from":"file:avandar-query-hooks-0.1.1.tgz","engines":{"node":">=22.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsup","test:watch":"vitest","type-check":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e7f6155a-946b-4e51-af8e-144b0989daa0"}},"_resolved":"/tmp/a3968f25d0bc839d80d1e325f5612ca2/avandar-query-hooks-0.1.1.tgz","_integrity":"sha512-kpY86OKdMRqhPlJzrPcS0J6DeZA4Jo69rO/tTuN3d2+X3g52UC4HnZgqNbFTbl2cPluf64e38gZU4VqF9V9vIQ==","repository":{"url":"git+https://github.com/AvandarLabs/avandar.git","type":"git","directory":"packages/web/query-hooks"},"_npmVersion":"11.12.1","description":"Avandar conventions layered over TanStack Query: useQuery/useMutation wrappers and a withQueryHooks client augmenter","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{"type-fest":"^5.4.4","@avandar/utils":"0.1.1","@avandar/clients":"0.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","jsdom":"^26.1.0","react":"19.2.5","vitest":"^3.2.4","react-dom":"19.2.5","typescript":"~5.9.3","@tanstack/react-query":"^5.81.5","@testing-library/react":"^16.3.0"},"peerDependencies":{"react":"^19.0.0","@tanstack/react-query":"^5.81.5"},"_npmOperationalInternal":{"tmp":"tmp/query-hooks_0.1.1_1786447316238_0.5991402827834105","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@avandar/query-hooks","version":"0.1.2","description":"Avandar conventions layered over TanStack Query: useQuery/useMutation wrappers and a withQueryHooks client augmenter","license":"MIT","repository":{"type":"git","url":"git+https://github.com/AvandarLabs/avandar.git","directory":"packages/web/query-hooks"},"homepage":"https://github.com/AvandarLabs/avandar/tree/main/packages/web/query-hooks#readme","bugs":{"url":"https://github.com/AvandarLabs/avandar/issues"},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"sideEffects":false,"dependencies":{"type-fest":"^5.4.4","@avandar/clients":"0.1.2","@avandar/utils":"0.1.2"},"peerDependencies":{"@tanstack/react-query":"^5.81.5","react":"^19.0.0"},"devDependencies":{"@tanstack/react-query":"^5.81.5","@testing-library/react":"^16.3.0","jsdom":"^26.1.0","react":"19.2.5","react-dom":"19.2.5","tsup":"^8.5.0","typescript":"~5.9.3","vitest":"^3.2.4"},"engines":{"node":">=22.0.0"},"publishConfig":{"access":"public"},"scripts":{"build":"tsup","test":"vitest run --passWithNoTests","test:watch":"vitest","type-check":"tsc --noEmit"},"_id":"@avandar/query-hooks@0.1.2","_integrity":"sha512-Y9HE3cHyng+ORI/1JReDgYXEh+gb31i8eoX6w+zo6zQoKejoirKeW9o5n5KlihnaOyzHFk/M0YbnOZJ5LhtwGA==","_resolved":"/tmp/fd1388c00fef2f891386cb04f3dc2d48/avandar-query-hooks-0.1.2.tgz","_from":"file:avandar-query-hooks-0.1.2.tgz","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-Y9HE3cHyng+ORI/1JReDgYXEh+gb31i8eoX6w+zo6zQoKejoirKeW9o5n5KlihnaOyzHFk/M0YbnOZJ5LhtwGA==","shasum":"a8e4373a521a6013725979f01a3a6e8174743d35","tarball":"https://registry.npmjs.org/@avandar/query-hooks/-/query-hooks-0.1.2.tgz","fileCount":6,"unpackedSize":76196,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@avandar%2fquery-hooks@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDSwsWVrFHgx1FXStRjXrg12v9loOQZ17FDbp2ftFQq4AiEAqvSv4QYxwW1e8OpMFG1ti3I8WREjhcRDnDB8VfJKI3g="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e7f6155a-946b-4e51-af8e-144b0989daa0"}},"directories":{},"maintainers":[{"name":"jpsyx","email":"pablowritescode@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/query-hooks_0.1.2_1786500349415_0.5344318110714312"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-11T01:29:11.742Z","modified":"2026-08-12T02:05:49.987Z","0.1.0":"2026-08-11T01:29:12.115Z","0.1.1":"2026-08-11T11:21:56.380Z","0.1.2":"2026-08-12T02:05:49.587Z"},"bugs":{"url":"https://github.com/AvandarLabs/avandar/issues"},"license":"MIT","homepage":"https://github.com/AvandarLabs/avandar/tree/main/packages/web/query-hooks#readme","repository":{"type":"git","url":"git+https://github.com/AvandarLabs/avandar.git","directory":"packages/web/query-hooks"},"description":"Avandar conventions layered over TanStack Query: useQuery/useMutation wrappers and a withQueryHooks client augmenter","maintainers":[{"name":"jpsyx","email":"pablowritescode@gmail.com"}],"readme":"# @avandar/query-hooks\n\nConventions layered over [TanStack Query](https://tanstack.com/query): thin\n`useQuery` and `useMutation` wrappers that return tuples and handle cache\ninvalidation declaratively, plus a `withQueryHooks` augmenter that generates\nquery and mutation hooks for a service client.\n\nESM only. Requires Node 22+ and React 19.\n\n## Install\n\n```sh\npnpm add @avandar/query-hooks\npnpm add react @tanstack/react-query\n```\n\n`react` and `@tanstack/react-query` are peer dependencies: your app owns the\n`QueryClientProvider`, and a second copy of either would break hooks and cache\nidentity.\n\n## Error reporting\n\nThis package does not know how your app surfaces errors. When a query or\nmutation fails and the caller supplied no `onError`, it calls an injected\nreporter, defaulting to `console.error`.\n\n```tsx\nimport { AvaQueryProvider } from \"@avandar/query-hooks\";\n\n<AvaQueryProvider\n  onError={({ title, message, cause }) => showToast(title, message, cause)}\n>\n  <App />\n</AvaQueryProvider>;\n```\n\nMounting the provider is optional.\n\n| Export                       | Description                                    |\n| ---------------------------- | ---------------------------------------------- |\n| `AvaQueryProvider`           | Supplies the error reporter                    |\n| `useAvaQueryErrorReporter()` | Reads the active reporter                      |\n| `AvaQueryErrorReporter`      | `({ title, message, cause }) => void`          |\n\n---\n\n## `useQuery(options)`\n\nWraps TanStack's `useQuery` and:\n\n- catches errors thrown by `queryFn`, reports them in development, and\n  re-throws so the query still lands in an error state,\n- returns a tuple `[data, isLoading, queryResult]` for easier destructuring,\n- adds `usePreviousDataAsPlaceholder`, shorthand for\n  `placeholderData: (prev) => prev`.\n\n```ts\nconst [users, isLoading] = useQuery({\n  queryKey: [\"users\"],\n  queryFn: fetchUsers,\n});\n```\n\n| Type                  | Description                                     |\n| --------------------- | ----------------------------------------------- |\n| `UseQueryOptions`     | Options accepted by `useQuery`                  |\n| `UseQueryResult`      | The raw TanStack result object                  |\n| `UseQueryResultTuple` | The `[data, isLoading, queryResult]` shape      |\n\n## `useMutation(options)`\n\nWraps TanStack's `useMutation` and:\n\n- returns a tuple `[mutate, isPending, mutationResult]`,\n- exposes `mutate.async` for callers that want a promise,\n- accepts `queryToInvalidate` / `queriesToInvalidate` and `queryToRefetch` /\n  `queriesToRefetch`, applied after a successful mutation and before your own\n  `onSuccess`,\n- falls back to the injected error reporter when you supply no `onError`\n  (a specific message in development, a generic one in production).\n\n```ts\nconst [createUser, isCreating] = useMutation({\n  mutationFn: api.createUser,\n  queryToInvalidate: [\"users\"],\n});\n\ncreateUser({ name: \"Alice\" });\nawait createUser.async({ name: \"Bob\" });\n```\n\nThe plural options take precedence over the singular ones.\n\n| Type                     | Description                                            |\n| ------------------------ | ------------------------------------------------------ |\n| `UseMutationOptions`     | TanStack's options plus the invalidate/refetch fields   |\n| `UseMutationResult`      | The raw TanStack mutation result                        |\n| `UseMutateFunction`      | The `mutate` callable, with `.async` attached           |\n| `UseMutationResultTuple` | The `[mutate, isPending, mutationResult]` shape         |\n\n---\n\n## `withQueryHooks(client, { queryFns?, mutationFns? })`\n\nAugments a service client (or any object whose values are single-argument\npromise-returning functions) with generated `use<Name>` hooks. Each `queryFns`\nentry becomes a hook wrapping `useQuery`; each `mutationFns` entry becomes one\nwrapping `useMutation`.\n\n```ts\nconst UserClient = withQueryHooks(rawUserClient, {\n  queryFns: [\"getById\", \"getAll\"],\n  mutationFns: [\"insert\", \"update\", \"delete\"],\n});\n\nconst [user] = UserClient.useGetById({ id: userId });\nconst [users] = UserClient.useGetAll();\nconst [createUser] = UserClient.useInsert({ invalidateGetAllQuery: true });\n\n// loader-friendly, shares the cache\nawait UserClient.withCache(queryClient).withEnsureQueryData().getAll();\n```\n\nParameters are passed differently depending on their shape: an **object**\nparameter is spread directly (`useGetById({ id })`), while a **scalar**\nparameter uses the `{ arg }` envelope (`useGetByName({ arg: \"sprocket\" })`).\n\nThe augmented client also exposes:\n\n- `QueryKeys` — query-key builder functions, one per listed query function,\n  useful for manual invalidation. Functions in the params are stripped so keys\n  stay serialisable.\n- `withCache(queryClient)` — returns `withEnsureQueryData()` and\n  `withFetchQuery()` variants so non-hook calls share the same cache.\n\nMutation hooks accept `UseMutationOptions` plus `invalidateGetAllQuery`, which\nappends the client's `getAll` key to the invalidation list.\n\n| Export                      | Description                                        |\n| --------------------------- | -------------------------------------------------- |\n| `DEFAULT_QUERY_FN_NAMES`    | Names treated as queries by default                 |\n| `DEFAULT_MUTATION_FN_NAMES` | Names treated as mutations by default               |\n| `WithQueryHooks`            | The augmented client type                           |\n| `FnNameReturningPromise`    | Keys of an object whose values return a `Promise`   |\n\n`DefaultError`, `QueryClient`, and `QueryKey` are re-exported unchanged from\n`@tanstack/react-query` for convenience.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}