From 0f00e561a1a5dcc826901b451be3fe6529cf6bc2 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Sun, 18 Dec 2022 21:42:12 -0800 Subject: [PATCH] docs: add simple and recommended usage pages --- .../content/1.get-started/2.usage/1.simple.md | 144 ++++++++++++++++++ .../{2.usage.md => 2.usage/2.recommended.md} | 54 ++++--- 2 files changed, 178 insertions(+), 20 deletions(-) create mode 100644 docs/content/1.get-started/2.usage/1.simple.md rename docs/content/1.get-started/{2.usage.md => 2.usage/2.recommended.md} (72%) diff --git a/docs/content/1.get-started/2.usage/1.simple.md b/docs/content/1.get-started/2.usage/1.simple.md new file mode 100644 index 0000000..8cb41f1 --- /dev/null +++ b/docs/content/1.get-started/2.usage/1.simple.md @@ -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({ + 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] + + + +``` diff --git a/docs/content/1.get-started/2.usage.md b/docs/content/1.get-started/2.usage/2.recommended.md similarity index 72% rename from docs/content/1.get-started/2.usage.md rename to docs/content/1.get-started/2.usage/2.recommended.md index e96eacb..1e1413f 100644 --- a/docs/content/1.get-started/2.usage.md +++ b/docs/content/1.get-started/2.usage/2.recommended.md @@ -1,11 +1,9 @@ --- -title: Usage +title: Recommended Usage description: tRPC-Nuxt provides first class integration with tRPC. --- -# Usage - -## Recommended file structure +# Recommended Usage 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 │ │ └── trpc.ts # <-- procedure helpers ├── 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 ```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 { 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().create() -// Base router and procedure helpers -export const router = t.router -export const publicProcedure = t.procedure +/** + * Unprotected procedure + **/ +export const publicProcedure = t.procedure; +export const router = t.router; +export const middleware = t.middleware; ``` ```ts [server/trpc/routers/index.ts] @@ -72,8 +79,8 @@ export type AppRouter = typeof appRouter ```ts [server/api/trpc/[trpc].ts] import { createNuxtApiHandler } from 'trpc-nuxt' -import { appRouter } from '@/server/trpc/routers' -import { createContext } from '@/server/trpc/context' +import { appRouter } from '~/server/trpc/routers' +import { createContext } from '~/server/trpc/context' // export API handler 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. ```ts [plugins/client.ts] -import { httpBatchLink, createTRPCProxyClient } from '@trpc/client' -import type { AppRouter } from '@/server/trpc/routers' +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(() => { - const client = createTRPCProxyClient({ + /** + * createTRPCNuxtClient adds a `useQuery` composable + * built on top of `useAsyncData`. + */ + const client = createTRPCNuxtClient({ links: [ httpBatchLink({ url: '/api/trpc', @@ -150,16 +162,18 @@ export default defineNuxtPlugin(() => { }) ``` -## 3. Make API requests +## 3. Make an API request ```vue [pages/index.vue] ```