resolver.pipeThis 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),
)
// ... etcThis returns a composed function of type (input, ctx) => Promise<result>
which is the standard resolver type.
resolver.zodThis 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.authorizeimport {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
paginateThis 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: numbertake: numbermaxTake: numbertake. It protects your DB when "take"
is sent by the user.paginationDataitems: 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)invokeWithMiddlewareThis 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 Pageconst results = await invokeWithMiddleware(resolver, resolverInputArguments, {req, res}))resolver: A Blitz query resolver or
mutation resolverresolverInputArgumentsresolverreqresmiddlewareresults