From cec8ea52d6cf5aa55e293ffcb76c0e506aa9ac4f Mon Sep 17 00:00:00 2001 From: Robert Soriano Date: Wed, 18 May 2022 09:20:29 -0700 Subject: [PATCH] update readme --- README.md | 81 ++-------------------------------------- recipes/authorization.md | 51 +++++++++++++++++++++++++ recipes/validation.md | 23 ++++++++++++ 3 files changed, 78 insertions(+), 77 deletions(-) create mode 100644 recipes/authorization.md create mode 100644 recipes/validation.md diff --git a/README.md b/README.md index c6a93b4..45d1c61 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ export const router = trpc }, }) -// optional +// Optional export const createContext = (event: CompatibilityEvent) => { // ... return { @@ -50,7 +50,7 @@ export const createContext = (event: CompatibilityEvent) => { } } -// optional +// Optional export const responseMeta = () => { // ... return { @@ -75,81 +75,8 @@ console.log(farewell); // => 👈 goodbye ## Recipes -### Validation - -tRPC works out-of-the-box with yup/superstruct/zod/myzod/custom validators. Learn more about input validation [here](https://trpc.io/docs/router#input-validation). - -```ts -// ~/server/trpc/index.ts -import { z } from 'zod' - -export const router = trpc - .router() - .mutation('createUser', { - // validate input with Zod - input: z.object({ - name: z.string().min(5) - }), - async resolve(req) { - // use your ORM of choice - return await UserModel.create({ - data: req.input, - }) - }, - }) -``` - -### Authorization - -The `createContext`-function is called for each incoming request so here you can add contextual information about the calling user from the request object. Learn more about authorization [here](https://trpc.io/docs/authorization). - -```ts -// ~/server/trpc/index.ts -import * as trpc from '@trpc/server' -import type { CompatibilityEvent } from 'h3' -import { decodeAndVerifyJwtToken } from '~/somewhere/in/your/app/utils' - -// The app's context - is generated for each incoming request -export async function createContext({ req }: CompatibilityEvent) { - // Create your context based on the request object - // Will be available as `ctx` in all your resolvers - - // This is just an example of something you'd might want to do in your ctx fn - async function getUserFromHeader() { - if (req.headers.authorization) { - const user = await decodeAndVerifyJwtToken(req.headers.authorization.split(' ')[1]) - return user - } - return null - } - const user = await getUserFromHeader() - - return { - user, - } -} - -export const router = trpc - .router>() - // open for anyone - .query('hello', { - input: z.string().nullish(), - resolve: ({ input, ctx }) => { - return `hello ${input ?? ctx.user?.name ?? 'world'}` - }, - }) - // checked in resolver - .query('secret', { - resolve: ({ ctx }) => { - if (!ctx.user) - throw new trpc.TRPCError({ code: 'UNAUTHORIZED' }) - - return { - secret: 'sauce', - } - }, - }) -``` +- [Validation](/recipes/validation.md) +- [Authorization](/recipes/authorization.md) Learn more about tRPC.io [here](https://trpc.io/docs). diff --git a/recipes/authorization.md b/recipes/authorization.md new file mode 100644 index 0000000..629bb72 --- /dev/null +++ b/recipes/authorization.md @@ -0,0 +1,51 @@ +## Authorization + +The `createContext`-function is called for each incoming request so here you can add contextual information about the calling user from the request object. Learn more about authorization [here](https://trpc.io/docs/authorization). + +```ts +// ~/server/trpc/index.ts +import * as trpc from '@trpc/server' +import type { CompatibilityEvent } from 'h3' +import { decodeAndVerifyJwtToken } from '~/somewhere/in/your/app/utils' + +// The app's context - is generated for each incoming request +export async function createContext({ req }: CompatibilityEvent) { + // Create your context based on the request object + // Will be available as `ctx` in all your resolvers + + // This is just an example of something you'd might want to do in your ctx fn + async function getUserFromHeader() { + if (req.headers.authorization) { + const user = await decodeAndVerifyJwtToken(req.headers.authorization.split(' ')[1]) + return user + } + return null + } + const user = await getUserFromHeader() + + return { + user, + } +} + +export const router = trpc + .router>() + // open for anyone + .query('hello', { + input: z.string().nullish(), + resolve: ({ input, ctx }) => { + return `hello ${input ?? ctx.user?.name ?? 'world'}` + }, + }) + // checked in resolver + .query('secret', { + resolve: ({ ctx }) => { + if (!ctx.user) + throw new trpc.TRPCError({ code: 'UNAUTHORIZED' }) + + return { + secret: 'sauce', + } + }, + }) +``` diff --git a/recipes/validation.md b/recipes/validation.md new file mode 100644 index 0000000..14a3fb9 --- /dev/null +++ b/recipes/validation.md @@ -0,0 +1,23 @@ +## Validation + +tRPC works out-of-the-box with yup/superstruct/zod/myzod/custom validators. Learn more about input validation [here](https://trpc.io/docs/router#input-validation). + +```ts +// ~/server/trpc/index.ts +import { z } from 'zod' + +export const router = trpc + .router() + .mutation('createUser', { + // validate input with Zod + input: z.object({ + name: z.string().min(5) + }), + async resolve(req) { + // use your ORM of choice + return await UserModel.create({ + data: req.input, + }) + }, + }) +```