resolver.pipe
This is a functional utility that makes it easier and cleaner to write complex resolvers.
resolver.zod()
resolver.authorize()
import {resolver} from "blitz"
import db from "db"
import * as z from "zod"
export const CreateProject = z.object({
name: z.string(),
dueDate: z.date().optional(),
orgId: z.number().optional(),
})
export default resolver.pipe(
resolver.zod(CreateProject),
resolver.authorize(),
// Set default orgId
(input, {session}) => ({...input, orgId: input.orgId ?? session.orgId}),
async (input, ctx) => {
console.log("Creating project...", input.orgId)
const project = await db.project.create({
data: input,
})
console.log("Created project")
return project
},
)
The input type of the entire composed resolver function is determined by the input type of the first argument to pipe.
This means you will almost always want resolver.zod()
to be the first in
the pipe.
It accepts from 1 to N functions which take input data as first argument
and middleware ctx
as the second argument.
The output of the first function is the first input argument of the next function. The output of the last function is the final resolver result data that will be sent to the client.
The Typescript types are automatically inferred from one function to the next.
// 1 function
const resolver = resolver.pipe((input: ResolverInput, ctx: Ctx) => ResolverOutput)
// 2 functions
const resolver = resolver.pipe(
(input: ResolverInput, ctx: Ctx) => A),
(input: A, ctx: Ctx) => ResolverOutput),
)
// 3 functions
const resolver = resolver.pipe(
(input: ResolverInput, ctx: Ctx) => A),
(input: A, ctx: Ctx) => B),
(input: B, ctx: Ctx) => ResolverOutput),
)
// ... etc
This returns a composed function of type (input, ctx) => Promise<result>
which is the standard resolver type.
resolver.zod
This is a resolver adapter for Zod,
an awesome input validation library. It takes a zod schema and runs
schema.parse
on the input data.
import {resolver} from 'blitz'
import * as z from "zod"
export const CreateProject = z.object({
name: z.string(),
dueDate: z.date().optional(),
orgId: z.number().optional(),
})
export default resolver.pipe(
resolver.zod(CreateProject), // highlight-line
async (input, ctx) => {
// stuff
},
)
const pipeFn = resolver.zod(MyZodSchema)
ZodSchema:
a zod schemaA function to give resolver.pipe
of type
(rawInput, ctx: Ctx) => validInput
resolver.authorize
import {resolver} from 'blitz'
export default resolver.pipe(
resolver.authorize(),
// resolver.authorize('admin'),
async (input, ctx) => {
// stuff
},
)
const pipeFn = resolver.authorize(...isAuthorizedArgs)
...isAuthorizedArgs
: The same arguments as your
isAuthorized
adapterA function to give resolver.pipe
of type (input, ctx: Ctx) => input
paginate
This is a handy utility for query pagination
import {paginate, Ctx} from "blitz"
import db, {Prisma} from "db"
interface GetProjectSInput
extends Pick<
Prisma.ProjectFindManyArgs,
"where" | "orderBy" | "skip" | "take"
> {}
export default async function getProjects(
{where, orderBy, skip = 0, take = 100}: GetProjectsInput,
ctx: Ctx,
) {
ctx.session.$authorize()
const {items: projects, hasMore, nextPage, count} = await paginate({
count: () => db.project.count({where}),
query: (paginateArgs) =>
db.project.findMany({...paginateArgs, where, orderBy}),
skip,
take,
})
return {
projects,
nextPage,
hasMore,
count,
}
}
const paginationData = await paginate(paginateArguments))
count
: () => Promise <number>
query
: (payload: { skip: number; take: number }) => Promise<T>
skip
: number
take
: number
maxTake
: number
take
. It protects your DB when "take"
is sent by the user.paginationData
items
: T
(Data resolver by the query
function)nextPage
: { skip: number, take: number } | null
(Next page
pagination payload)hasMore
: boolean
(True if there are more items to load.)count
: number
(Total number of items. Resolved by the count
function)invokeWithMiddleware
This is for imperatively invoking queries/mutations on the server. It ensures appropriate middleware is run before/after your resolver.
import {
invokeWithMiddleware,
GetServerSideProps,
Link,
BlitzPage,
PromiseReturnType,
} from "blitz"
import getProducts from "app/products/queries/getProducts"
type PageProps = {
products: PromiseReturnType<typeof getProducts>
}
export const getServerSideProps: GetServerSideProps<PageProps> = async ({
req,
res,
}) => {
const products = await invokeWithMiddleware(
getProducts,
{orderBy: {id: "desc"}},
{req, res},
)
return {
props: {products},
}
}
const Page: BlitzPage<PageProps> = function ({products}) {
return (
<div>
<h1>Products</h1>
<div id="products">
{products.map((product) => (
<p key={product.id}>
<Link
href="/products/[handle]"
as={`/products/${product.handle}`}
>
<a>{product.name}</a>
</Link>
</p>
))}
</div>
</div>
)
}
export default Page
const results = await invokeWithMiddleware(resolver, resolverInputArguments, {req, res}))
resolver:
A Blitz query resolver or
mutation resolverresolverInputArguments
resolver
req
res
middleware
results