JSPM

@colonel-sandvich/trpc-vue-query

0.8.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 20
  • Score
    100M100P100Q63595F
  • License MIT

Package Exports

    Readme

    trpc-vue-query

    A simple package to bridge the gap between TRPC and TanStack Query for Vue much like how TRPC has their own in-house React Query Integration

    Why this package?

    If you're using @tanstack/vue-query then you might know that working with query keys and query functions can sometimes become cumbersome. A lead maintainer of Tanstack Query, TkDodo, has said that "Separating QueryKey from QueryFunction was a mistake".

    So this package tightly couples your keys and functions leading to brilliant DX 🚀

    Before:

    const currentUserQuery = queryOptions({
      queryKey: ["user", "current"],
      queryFn: () => trpc.user.current.query(),
    });
    
    const { data } = useQuery(currentUserQuery);
    
    const { mutateAsync } = useMutation({
      mutationFn: (input: UnwrapRef<typeof form>) => trpc.user.signUp.mutate(input),
      onSuccess: async () => {
        await useQueryClient().invalidateQueries({
          queryKey: currentUserQuery.queryKey,
        });
        await navigateTo("/onboarding");
      },
    });

    After:

    const { data } = useClient().user.current.useQuery();
    
    const { mutateAsync } = useClient().user.signUp.useMutation({
      onSuccess: async () => {
        await useClient().user.current.invalidate();
        await navigateTo("/onboarding");
      },
    });

    Install

    pnpm i @colonel-sandvich/trpc-vue-query

    Setup (Vue)

    1. Plug in the plugin

    // main.ts
    import { TrpcVueQueryPlugin } from "@colonel-sandvich/trpc-vue-query";
    import { VueQueryPlugin } from "@tanstack/vue-query";
    import { httpBatchLink } from "@trpc/client";
    import { createApp } from "vue";
    import App from "./src/App.vue";
    import { trpc } from "your-path-to-trpc-client";
    // ^ See https://trpc.io/docs/client/vanilla/setup#3-initialize-the-trpc-client
    
    export const app = createApp(App);
    
    app
      .use(VueQueryPlugin) // Make sure {@tanstack/vue-query}'s plugin goes first
      .use(TrpcVueQueryPlugin, {
        trpcClient: trpc,
      })
      .mount("#app");

    2. Make a composable

    // src/composables/useClient.ts
    import { TrpcVueClient, clientKey } from "@colonel-sandvich/trpc-vue-query";
    import { inject } from "vue";
    import type { AppRouter } from "your-path-to-trpc-app-router-type";
    
    export function useClient() {
      return inject(clientKey) as TrpcVueClient<AppRouter>;
    }

    Setup (Nuxt)

    0. Setup @tanstack/vue-query for Nuxt if you haven't already

    // src/plugins/01.vueQueryPlugin.ts
    
    // Important that this plugin comes before the `02.clientPlugin` since that has this plugin as a dependency
    export default defineNuxtPlugin((nuxt) => {
      nuxt.vueApp.use(VueQueryPlugin);
    
      // Below is for SSR. Remove if you don't need this
      // Provided from TanStack Query docs: https://tanstack.com/query/v5/docs/vue/guides/ssr
      const vueQueryState = useState<DehydratedState | null>("vue-query");
    
      if (process.server) {
        nuxt.hooks.hook("app:rendered", () => {
          vueQueryState.value = dehydrate(queryClient);
        });
      }
    
      if (process.client) {
        nuxt.hooks.hook("app:created", () => {
          hydrate(queryClient, vueQueryState.value);
        });
      }
    });

    1. Make a plugin

    // src/plugins/02.clientPlugin.ts
    
    export default defineNuxtPlugin(() => {
      const trpc = createTRPCProxyClient<AppRouter>({
        links: [
          httpBatchLink({
            url: "/api/trpc",
            headers: useRequestHeaders(),
            fetch: customFetchWrapper(), // Crucial for SSR
          }),
        ],
      });
    
      const client = createTrpcVueClient(trpc, useQueryClient());
    
      return {
        provide: {
          client,
        },
      };
    });

    2. Make a composable

    // src/composables/useClient.ts
    
    export const useClient = () => {
      return useNuxtApp().$client;
    };

    You're Done!

    Go check out /examples to see some basic uses.

    Quickstart for testing examples/vue-minimal

    pnpm i Anywhere

    cd examples/vue-minimal

    pnpm dev

    If ports 3000 (client) and 3001 (server) are available then you should up and running

    Goals of the project

    • Easier integration with Vue and Nuxt
    • Feature parity with TRPC's React Query (or at least as much as is possible with Vue Query)
      • Subscriptions
    • Documentation

    Contributing

    Please please please absolutely make an issue or PR for any bugs or feature requests, I highly encourage it.

    Acknowledgments

    Big thanks to Robert Soriano for his trpc-nuxt package that inspired this package.

    Star History

    Star History Chart