npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@avandar/query-hooks

v0.1.2

Published

Avandar conventions layered over TanStack Query: useQuery/useMutation wrappers and a withQueryHooks client augmenter

Downloads

211

Readme

@avandar/query-hooks

Conventions layered over TanStack Query: thin useQuery and useMutation wrappers that return tuples and handle cache invalidation declaratively, plus a withQueryHooks augmenter that generates query and mutation hooks for a service client.

ESM only. Requires Node 22+ and React 19.

Install

pnpm add @avandar/query-hooks
pnpm add react @tanstack/react-query

react and @tanstack/react-query are peer dependencies: your app owns the QueryClientProvider, and a second copy of either would break hooks and cache identity.

Error reporting

This package does not know how your app surfaces errors. When a query or mutation fails and the caller supplied no onError, it calls an injected reporter, defaulting to console.error.

import { AvaQueryProvider } from "@avandar/query-hooks";

<AvaQueryProvider
  onError={({ title, message, cause }) => showToast(title, message, cause)}
>
  <App />
</AvaQueryProvider>;

Mounting the provider is optional.

| Export | Description | | ---------------------------- | ---------------------------------------------- | | AvaQueryProvider | Supplies the error reporter | | useAvaQueryErrorReporter() | Reads the active reporter | | AvaQueryErrorReporter | ({ title, message, cause }) => void |


useQuery(options)

Wraps TanStack's useQuery and:

  • catches errors thrown by queryFn, reports them in development, and re-throws so the query still lands in an error state,
  • returns a tuple [data, isLoading, queryResult] for easier destructuring,
  • adds usePreviousDataAsPlaceholder, shorthand for placeholderData: (prev) => prev.
const [users, isLoading] = useQuery({
  queryKey: ["users"],
  queryFn: fetchUsers,
});

| Type | Description | | --------------------- | ----------------------------------------------- | | UseQueryOptions | Options accepted by useQuery | | UseQueryResult | The raw TanStack result object | | UseQueryResultTuple | The [data, isLoading, queryResult] shape |

useMutation(options)

Wraps TanStack's useMutation and:

  • returns a tuple [mutate, isPending, mutationResult],
  • exposes mutate.async for callers that want a promise,
  • accepts queryToInvalidate / queriesToInvalidate and queryToRefetch / queriesToRefetch, applied after a successful mutation and before your own onSuccess,
  • falls back to the injected error reporter when you supply no onError (a specific message in development, a generic one in production).
const [createUser, isCreating] = useMutation({
  mutationFn: api.createUser,
  queryToInvalidate: ["users"],
});

createUser({ name: "Alice" });
await createUser.async({ name: "Bob" });

The plural options take precedence over the singular ones.

| Type | Description | | ------------------------ | ------------------------------------------------------ | | UseMutationOptions | TanStack's options plus the invalidate/refetch fields | | UseMutationResult | The raw TanStack mutation result | | UseMutateFunction | The mutate callable, with .async attached | | UseMutationResultTuple | The [mutate, isPending, mutationResult] shape |


withQueryHooks(client, { queryFns?, mutationFns? })

Augments a service client (or any object whose values are single-argument promise-returning functions) with generated use<Name> hooks. Each queryFns entry becomes a hook wrapping useQuery; each mutationFns entry becomes one wrapping useMutation.

const UserClient = withQueryHooks(rawUserClient, {
  queryFns: ["getById", "getAll"],
  mutationFns: ["insert", "update", "delete"],
});

const [user] = UserClient.useGetById({ id: userId });
const [users] = UserClient.useGetAll();
const [createUser] = UserClient.useInsert({ invalidateGetAllQuery: true });

// loader-friendly, shares the cache
await UserClient.withCache(queryClient).withEnsureQueryData().getAll();

Parameters are passed differently depending on their shape: an object parameter is spread directly (useGetById({ id })), while a scalar parameter uses the { arg } envelope (useGetByName({ arg: "sprocket" })).

The augmented client also exposes:

  • QueryKeys — query-key builder functions, one per listed query function, useful for manual invalidation. Functions in the params are stripped so keys stay serialisable.
  • withCache(queryClient) — returns withEnsureQueryData() and withFetchQuery() variants so non-hook calls share the same cache.

Mutation hooks accept UseMutationOptions plus invalidateGetAllQuery, which appends the client's getAll key to the invalidation list.

| Export | Description | | --------------------------- | -------------------------------------------------- | | DEFAULT_QUERY_FN_NAMES | Names treated as queries by default | | DEFAULT_MUTATION_FN_NAMES | Names treated as mutations by default | | WithQueryHooks | The augmented client type | | FnNameReturningPromise | Keys of an object whose values return a Promise |

DefaultError, QueryClient, and QueryKey are re-exported unchanged from @tanstack/react-query for convenience.

License

MIT