1
0
mirror of synced 2025-12-25 02:00:48 -05:00

Use parseAsync by default and add argument to parse sync to common zod validations (#2616)

* don't throw an error if checkYarn is null or checkYarn.stdout is null or undefined

* make sure to check if this version is less than the latest version

* fix forgotpassword test template, sync auth example tests

* revert to ensure monorepo tests work

* revert to original password and index tests

* remove merge reference

* fix merge issue

* Quirrel recipe: start > dev, double quote command

* add Suspense boundary

* Update packages/generator/templates/app/app/pages/_app.tsx

* send "blitz.js" in x-powered-by header

* Update test for powered-by-header

Considered making the test check to see if anything at all was present, but not needed for our use case right now

* Update test to check for x-powered-by

* update favicon to be orange in new blitz apps

* Support both NEXT_PUBLIC_ and BLITZ_PUBLIC_ 

Make webpack take environment variables prefixed with either NEXT_PUBLIC_ and BLITZ_PUBLIC_ to the frontends environemtn variables

* Revert "Support both NEXT_PUBLIC_ and BLITZ_PUBLIC_ "

This reverts commit 9760bcb70d.

* define parser type, add argument to resolver zod

* Add tests for argument, no value

* add ability to parse async, and tests

* Fix lint issue

* use fn overloads, return promise conditionally

* Update packages/core/src/server/resolver.ts

* fix linter issue

Co-authored-by: Roshan Manuel <Roshan,manuel@angelic-group.com>
Co-authored-by: Brandon Bayer <b@bayer.ws>

(major)
This commit is contained in:
Roshan Manuel
2021-08-25 10:54:23 -05:00
committed by GitHub
parent 8d98843573
commit ee97985859
4 changed files with 119 additions and 36 deletions

View File

@@ -1,35 +1,63 @@
import {Ctx} from "next/types"
import {z} from "zod"
import {resolver} from "./resolver"
import {ParserType, resolver} from "./resolver"
describe("resolver", () => {
it("should typecheck and pass along value", async () => {
const resolver1 = resolver.pipe(
resolver.zod(
z.object({
email: z.string().email(),
}),
),
resolver.authorize(),
(input) => {
return input.email
},
)
const result1 = await resolver1(
{email: "test@example.com"},
{session: {$authorize: () => undefined} as Ctx},
)
expect(result1).toBe("test@example.com")
const resolver2 = resolver.pipe(
/*resolver.authorize(), */ (input: {email: string}) => {
return input.email
},
)
const result2 = await resolver2(
{email: "test@example.com"},
{session: {$authorize: () => undefined} as Ctx},
)
expect(result2).toBe("test@example.com")
await resolverTest({})
})
it("should typecheck and pass along value if sync resolver is specified", async () => {
await resolverTest({type: "sync"})
})
it("should typecheck and pass along value if async resolver is specified", async () => {
await resolverTest({type: "async"})
})
})
const syncResolver = resolver.pipe(
resolver.zod(
z.object({
email: z.string().email(),
}),
"sync",
),
resolver.authorize({}),
(input) => {
return input.email
},
)
const asyncResolver = resolver.pipe(
resolver.zod(
z.object({
email: z.string().email(),
}),
"async",
),
resolver.authorize({}),
(input) => {
return input.email
},
)
const resolverTest = async ({type}: {type?: ParserType}) => {
const resolver1 = type === "sync" ? syncResolver : asyncResolver
const result1 = await resolver1(
{email: "test@example.com"},
{session: {$authorize: () => undefined} as Ctx},
)
expect(result1).toBe("test@example.com")
const resolver2 = resolver.pipe(
/*resolver.authorize(), */ (input: {email: string}) => {
return input.email
},
)
const result2 = await resolver2(
{email: "test@example.com"},
{session: {$authorize: () => undefined} as Ctx},
)
expect(result2).toBe("test@example.com")
}

View File

@@ -290,10 +290,33 @@ const authorize: ResolverAuthorize = (...args) => {
}
}
export type ParserType = "sync" | "async"
function zod<Schema extends ZodSchema<any, any>, Type = zInfer<Schema>>(
schema: Schema,
parserType: "sync",
): (input: Type) => Type
function zod<Schema extends ZodSchema<any, any>, Type = zInfer<Schema>>(
schema: Schema,
parserType: "async",
): (input: Type) => Promise<Type>
function zod<Schema extends ZodSchema<any, any>, Type = zInfer<Schema>>(
schema: Schema,
): (input: Type) => Promise<Type>
function zod<Schema extends ZodSchema<any, any>, Type = zInfer<Schema>>(
schema: Schema,
parserType: ParserType = "async",
){
if(parserType === "sync"){
return (input: Type) : Type => schema.parse(input)
}else{
return (input: Type) : Promise<Type> => schema.parseAsync(input)
}
}
export const resolver = {
pipe,
zod<Schema extends ZodSchema<any, any>, Type = zInfer<Schema>>(schema: Schema) {
return (input: Type): Type => schema.parse(input)
},
zod,
authorize,
}

View File

@@ -80,11 +80,19 @@ describe("formatZodError", () => {
})
describe("validateZodSchema", () => {
it("passes validation", () => {
expect(validateZodSchema(Schema)({test: "test"})).toEqual({})
it("passes validation", async () => {
expect(await validateZodSchema(Schema)({test: "test"})).toEqual({})
})
it("fails validation", () => {
expect(validateZodSchema(Schema)({})).toEqual({test: "Required"})
it("fails validation", async () => {
expect(await validateZodSchema(Schema)({})).toEqual({test: "Required"})
})
it("passes validation if synchronous", () => {
expect(validateZodSchema(Schema, "sync")({test: "test"})).toEqual({})
})
it("fails validation if synchronous", () => {
expect(validateZodSchema(Schema, "sync")({})).toEqual({test: "Required"})
})
})

View File

@@ -1,4 +1,5 @@
import {ZodError} from "zod"
import {ParserType} from "../server/resolver"
export const isServer = typeof window === "undefined"
export const isClient = typeof window !== "undefined"
@@ -42,7 +43,7 @@ export function recursiveFormatZodErrors(errors: any) {
return formattedErrors
}
export const validateZodSchema = (schema: any) => (values: any): any => {
const validateZodSchemaSync = (schema: any): any => (values: any) => {
if (!schema) return {}
try {
schema.parse(values)
@@ -51,3 +52,26 @@ export const validateZodSchema = (schema: any) => (values: any): any => {
return error.format ? formatZodError(error) : error.toString()
}
}
const validateZodSchemaAsync = (schema: any) => async (values: any) => {
if (!schema) return {}
try {
await schema.parseAsync(values)
return {}
} catch (error) {
return error.format ? formatZodError(error) : error.toString()
}
}
// type zodSchemaReturn = typeof validateZodSchemaAsync | typeof validateZodSchemaSync
// : (((values:any) => any) | ((values:any) => Promise<any>)) =>
export function validateZodSchema(schema: any, parserType: "sync"): (values: any) => any
export function validateZodSchema(schema: any, parserType: "async"): (values: any) => Promise<any>
export function validateZodSchema(schema: any): (values: any) => Promise<any>
export function validateZodSchema(schema: any, parserType: ParserType = "async") {
if (parserType === "sync") {
return validateZodSchemaSync(schema)
} else {
return validateZodSchemaAsync(schema)
}
}