mirror of
https://github.com/ArthurDanjou/trpc-nuxt.git
synced 2026-01-30 19:57:54 +01:00
docs: add simple and recommended usage pages
This commit is contained in:
144
docs/content/1.get-started/2.usage/1.simple.md
Normal file
144
docs/content/1.get-started/2.usage/1.simple.md
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
---
|
||||||
|
title: Simple Usage
|
||||||
|
description: tRPC-Nuxt provides first class integration with tRPC.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Simple Usage
|
||||||
|
|
||||||
|
## 1. Create a tRPC router
|
||||||
|
|
||||||
|
Initialize your tRPC backend using the `initTRPC` function and create your first router.
|
||||||
|
|
||||||
|
::code-group
|
||||||
|
|
||||||
|
```ts [server/trpc/trpc.ts]
|
||||||
|
/**
|
||||||
|
* This is your entry point to setup the root configuration for tRPC on the server.
|
||||||
|
* - `initTRPC` should only be used once per app.
|
||||||
|
* - We export only the functionality that we use so we can enforce which base procedures should be used
|
||||||
|
*
|
||||||
|
* Learn how to create protected base procedures and other things below:
|
||||||
|
* @see https://trpc.io/docs/v10/router
|
||||||
|
* @see https://trpc.io/docs/v10/procedures
|
||||||
|
*/
|
||||||
|
import { initTRPC } from '@trpc/server'
|
||||||
|
|
||||||
|
const t = initTRPC.create()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unprotected procedure
|
||||||
|
**/
|
||||||
|
export const publicProcedure = t.procedure;
|
||||||
|
|
||||||
|
export const router = t.router;
|
||||||
|
export const middleware = t.middleware;
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts [server/api/trpc/[trpc].ts]
|
||||||
|
/**
|
||||||
|
* This is the API-handler of your app that contains all your API routes.
|
||||||
|
* On a bigger app, you will probably want to split this file up into multiple files.
|
||||||
|
*/
|
||||||
|
import { createNuxtApiHandler } from 'trpc-nuxt'
|
||||||
|
import { publicProcedure, router } from '~/server/trpc/trpc'
|
||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
|
export const appRouter = router({
|
||||||
|
hello: publicProcedure
|
||||||
|
// This is the input schema of your procedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
text: z.string().nullish(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(({ input }) => {
|
||||||
|
// This is what you're returning to your client
|
||||||
|
return {
|
||||||
|
greeting: `hello ${input?.text ?? 'world'}`,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
// export only the type definition of the API
|
||||||
|
// None of the actual implementation is exposed to the client
|
||||||
|
export type AppRouter = typeof appRouter;
|
||||||
|
|
||||||
|
// export API handler
|
||||||
|
export default createNuxtApiHandler({
|
||||||
|
router: appRouter,
|
||||||
|
createContext: () => ({}),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
## 2. Create tRPC client plugin
|
||||||
|
|
||||||
|
Create a strongly-typed plugin using your API's type signature.
|
||||||
|
|
||||||
|
```ts [plugins/client.ts]
|
||||||
|
import { httpBatchLink } from '@trpc/client'
|
||||||
|
import { createTRPCNuxtClient } from 'trpc-nuxt/client'
|
||||||
|
import type { AppRouter } from '~/server/trpc/routers'
|
||||||
|
import { FetchError } from 'ofetch'
|
||||||
|
|
||||||
|
export default defineNuxtPlugin(() => {
|
||||||
|
/**
|
||||||
|
* createTRPCNuxtClient adds a `useQuery` composable
|
||||||
|
* built on top of `useAsyncData`.
|
||||||
|
*/
|
||||||
|
const client = createTRPCNuxtClient<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 an API request
|
||||||
|
|
||||||
|
```vue [pages/index.vue]
|
||||||
|
<script setup lang="ts">
|
||||||
|
const { $client } = useNuxtApp()
|
||||||
|
|
||||||
|
const hello = await $client.hello.useQuery({ text: 'client' })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<p>{{ hello.data?.greeting }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: Usage
|
title: Recommended Usage
|
||||||
description: tRPC-Nuxt provides first class integration with tRPC.
|
description: tRPC-Nuxt provides first class integration with tRPC.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Usage
|
# Recommended Usage
|
||||||
|
|
||||||
## Recommended file structure
|
|
||||||
|
|
||||||
Recommended but not enforced file structure. This is what you get when starting from [the examples](../main/example-apps.md).
|
Recommended but not enforced file structure. This is what you get when starting from [the examples](../main/example-apps.md).
|
||||||
|
|
||||||
@@ -24,7 +22,7 @@ Recommended but not enforced file structure. This is what you get when starting
|
|||||||
│ │ ├── context.ts # <-- create app context
|
│ │ ├── context.ts # <-- create app context
|
||||||
│ │ └── trpc.ts # <-- procedure helpers
|
│ │ └── trpc.ts # <-- procedure helpers
|
||||||
├── plugins
|
├── plugins
|
||||||
│ ├── client.ts # <-- tRPC Client as a plugin
|
│ ├── client.ts # <-- tRPC client plugin
|
||||||
└── [..]
|
└── [..]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -35,17 +33,26 @@ Initialize your tRPC backend using the `initTRPC` function and create your first
|
|||||||
::code-group
|
::code-group
|
||||||
|
|
||||||
```ts [server/trpc/trpc.ts]
|
```ts [server/trpc/trpc.ts]
|
||||||
|
/**
|
||||||
|
* This is your entry point to setup the root configuration for tRPC on the server.
|
||||||
|
* - `initTRPC` should only be used once per app.
|
||||||
|
* - We export only the functionality that we use so we can enforce which base procedures should be used
|
||||||
|
*
|
||||||
|
* Learn how to create protected base procedures and other things below:
|
||||||
|
* @see https://trpc.io/docs/v10/router
|
||||||
|
* @see https://trpc.io/docs/v10/procedures
|
||||||
|
*/
|
||||||
import { initTRPC } from '@trpc/server'
|
import { initTRPC } from '@trpc/server'
|
||||||
import { Context } from '@/server/trpc/context'
|
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()
|
const t = initTRPC.context<Context>().create()
|
||||||
|
|
||||||
// Base router and procedure helpers
|
/**
|
||||||
export const router = t.router
|
* Unprotected procedure
|
||||||
export const publicProcedure = t.procedure
|
**/
|
||||||
|
export const publicProcedure = t.procedure;
|
||||||
|
export const router = t.router;
|
||||||
|
export const middleware = t.middleware;
|
||||||
```
|
```
|
||||||
|
|
||||||
```ts [server/trpc/routers/index.ts]
|
```ts [server/trpc/routers/index.ts]
|
||||||
@@ -72,8 +79,8 @@ export type AppRouter = typeof appRouter
|
|||||||
|
|
||||||
```ts [server/api/trpc/[trpc].ts]
|
```ts [server/api/trpc/[trpc].ts]
|
||||||
import { createNuxtApiHandler } from 'trpc-nuxt'
|
import { createNuxtApiHandler } from 'trpc-nuxt'
|
||||||
import { appRouter } from '@/server/trpc/routers'
|
import { appRouter } from '~/server/trpc/routers'
|
||||||
import { createContext } from '@/server/trpc/context'
|
import { createContext } from '~/server/trpc/context'
|
||||||
|
|
||||||
// export API handler
|
// export API handler
|
||||||
export default createNuxtApiHandler({
|
export default createNuxtApiHandler({
|
||||||
@@ -105,12 +112,17 @@ If you need to split your router into several subrouters, you can implement them
|
|||||||
Create a strongly-typed plugin using your API's type signature.
|
Create a strongly-typed plugin using your API's type signature.
|
||||||
|
|
||||||
```ts [plugins/client.ts]
|
```ts [plugins/client.ts]
|
||||||
import { httpBatchLink, createTRPCProxyClient } from '@trpc/client'
|
import { httpBatchLink } from '@trpc/client'
|
||||||
import type { AppRouter } from '@/server/trpc/routers'
|
import { createTRPCNuxtClient } from 'trpc-nuxt/client'
|
||||||
|
import type { AppRouter } from '~/server/trpc/routers'
|
||||||
import { FetchError } from 'ofetch'
|
import { FetchError } from 'ofetch'
|
||||||
|
|
||||||
export default defineNuxtPlugin(() => {
|
export default defineNuxtPlugin(() => {
|
||||||
const client = createTRPCProxyClient<AppRouter>({
|
/**
|
||||||
|
* createTRPCNuxtClient adds a `useQuery` composable
|
||||||
|
* built on top of `useAsyncData`.
|
||||||
|
*/
|
||||||
|
const client = createTRPCNuxtClient<AppRouter>({
|
||||||
links: [
|
links: [
|
||||||
httpBatchLink({
|
httpBatchLink({
|
||||||
url: '/api/trpc',
|
url: '/api/trpc',
|
||||||
@@ -150,16 +162,18 @@ export default defineNuxtPlugin(() => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3. Make API requests
|
## 3. Make an API request
|
||||||
|
|
||||||
```vue [pages/index.vue]
|
```vue [pages/index.vue]
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { $client } = useNuxtApp()
|
const { $client } = useNuxtApp()
|
||||||
|
|
||||||
const data = await $client.hello.query({ text: 'client' })
|
const hello = await $client.hello.useQuery({ text: 'client' })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<p>{{data?.greeting }}</p>
|
<div>
|
||||||
|
<p>{{ hello.data?.greeting }}</p>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
Reference in New Issue
Block a user