Files
trpc-nuxt/docs/content/1.get-started/2.usage.md
2022-12-13 18:07:15 +02:00

4.1 KiB

title, description
title description
Usage tRPC-Nuxt provides first class integration with tRPC.

Usage

Recommended but not enforced file structure. This is what you get when starting from the examples.

.
├── server
   ├── api
      └── trpc
          └── [trpc].ts  # <-- tRPC HTTP handler
      └── [..]
   ├── trpc
      ├── routers
         ├── index.ts  # <-- main app router
         ├── todo.ts  # <-- sub routers
         └── [..]
      ├── context.ts   # <-- create app context
      └── trpc.ts      # <-- procedure helpers
├── plugins
   ├── client.ts  # <-- tRPC Client as a plugin
└── [..]

1. Create a tRPC router

Initialize your tRPC backend using the initTRPC function and create your first router.

::code-group

import { initTRPC } from '@trpc/server'
import { Context } from '@/server/trpc/context'

// Avoid exporting the entire t-object since it's not very
// descriptive and can be confusing to newcomers used to t
// meaning translation in i18n libraries.
const t = initTRPC.context<Context>().create()

// Base router and procedure helpers
export const router = t.router
export const publicProcedure = t.procedure
import { z } from 'zod'
import { publicProcedure, router } from '../trpc'

export const appRouter = router({
  hello: publicProcedure
    .input(
      z.object({
        text: z.string().nullish(),
      }),
    )
    .query(({ input }) => {
      return {
        greeting: `hello ${input?.text ?? 'world'}`,
      }
    }),
})

// export type definition of API
export type AppRouter = typeof appRouter
import { createNuxtApiHandler } from 'trpc-nuxt'
import { appRouter } from '@/server/trpc/routers'
import { createContext } from '@/server/trpc/context'

// export API handler
export default createNuxtApiHandler({
  router: appRouter,
  createContext,
})
import { inferAsyncReturnType } from '@trpc/server'

/**
 * Creates context for an incoming request
 * @link https://trpc.io/docs/context
 */
export const createContext = () => {}

export type Context = inferAsyncReturnType<typeof createContext>;

::

::alert{type=info} If you need to split your router into several subrouters, you can implement them in the server/trpc/routers directory and import and merge them to a single root appRouter. ::

2. Create tRPC client plugin

Create a strongly-typed plugin using your API's type signature.

import { httpBatchLink, createTRPCProxyClient } from '@trpc/client'
import type { AppRouter } from '@/server/trpc/routers'
import { FetchError } from 'ofetch'

export default defineNuxtPlugin(() => {
  const client = createTRPCProxyClient<AppRouter>({
    links: [
      httpBatchLink({
        url: '/api/trpc',
        
        
        /**
         * Replace regular `fetch` with a `$fetch` from nuxt
         *
         * During server-side rendering, calling $fetch to fetch your internal API routes
         * will directly call the relevant function (emulating the request),
         * saving an additional API call.
         *
         * @see https://nuxt.com/docs/api/utils/dollarfetch
         */
        fetch: (input, options) =>
          globalThis.$fetch.raw(input.toString(), options)
            .catch((e) => {
              if (e instanceof FetchError && e.response)
                return e.response

              throw e
            })
            .then(response => ({
              ...response,
              json: () => Promise.resolve(response._data),
            })),
            
      }),
    ],
  })

  return {
    provide: {
      client,
    },
  }
})

3. Make API requests

<script setup lang="ts">
const { $client } = useNuxtApp()

const data = await $client.hello.query({ text: 'client' })
</script>

<template>
  <p>{{data?.greeting }}</p>
</template>