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:
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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"})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user