Update /markets to use zod validation

This commit is contained in:
Benjamin 2022-07-01 19:34:16 -07:00
parent c71aa148d4
commit 4a3ffff9c4
2 changed files with 39 additions and 35 deletions

View File

@ -3,20 +3,22 @@ import { applyCorsHeaders, CORS_UNRESTRICTED } from 'web/lib/api/cors'
import { Bet, getBets } from 'web/lib/firebase/bets' import { Bet, getBets } from 'web/lib/firebase/bets'
import { getContractFromSlug } from 'web/lib/firebase/contracts' import { getContractFromSlug } from 'web/lib/firebase/contracts'
import { getUserByUsername } from 'web/lib/firebase/users' import { getUserByUsername } from 'web/lib/firebase/users'
import { ApiError, ValidationError } from '../_types' import { ApiError, ValidationError } from './_types'
import { z } from 'zod' import { z } from 'zod'
import { validate } from '../_validate' import { validate } from './_validate'
const queryParams = z.object({ const queryParams = z
username: z.string().optional(), .object({
market: z.string().optional(), username: z.string().optional(),
limit: z market: z.string().optional(),
.number() limit: z
.default(1000) .number()
.or(z.string().regex(/\d+/).transform(Number)) .default(1000)
.refine((n) => n >= 0 && n <= 1000, 'Limit must be between 0 and 1000'), .or(z.string().regex(/\d+/).transform(Number))
before: z.string().optional(), .refine((n) => n >= 0 && n <= 1000, 'Limit must be between 0 and 1000'),
}) before: z.string().optional(),
})
.strict()
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,

View File

@ -2,38 +2,40 @@
import type { NextApiRequest, NextApiResponse } from 'next' import type { NextApiRequest, NextApiResponse } from 'next'
import { listAllContracts } from 'web/lib/firebase/contracts' import { listAllContracts } from 'web/lib/firebase/contracts'
import { applyCorsHeaders, CORS_UNRESTRICTED } from 'web/lib/api/cors' import { applyCorsHeaders, CORS_UNRESTRICTED } from 'web/lib/api/cors'
import { toLiteMarket } from './_types' import { toLiteMarket, ValidationError } from './_types'
import { z } from 'zod'
import { validate } from './_validate'
const queryParams = z
.object({
limit: z
.number()
.default(1000)
.or(z.string().regex(/\d+/).transform(Number))
.refine((n) => n >= 0 && n <= 1000, 'Limit must be between 0 and 1000'),
before: z.string().optional(),
})
.strict()
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse res: NextApiResponse
) { ) {
await applyCorsHeaders(req, res, CORS_UNRESTRICTED) await applyCorsHeaders(req, res, CORS_UNRESTRICTED)
let before: string | undefined
let limit: number | undefined let params: z.infer<typeof queryParams>
if (req.query.before != null) { try {
if (typeof req.query.before !== 'string') { params = validate(queryParams, req.query)
res.status(400).json({ error: 'before must be null or a market ID.' }) } catch (e) {
return if (e instanceof ValidationError) {
return res.status(400).json(e)
} }
before = req.query.before console.error(`Unknown error during validation: ${e}`)
} return res.status(500).json({ error: 'Unknown error during validation' })
if (req.query.limit != null) {
if (typeof req.query.limit !== 'string') {
res
.status(400)
.json({ error: 'limit must be null or a number of markets to return.' })
return
}
limit = parseInt(req.query.limit)
} else {
limit = 1000
}
if (limit < 1 || limit > 1000) {
res.status(400).json({ error: 'limit must be between 1 and 1000.' })
return
} }
const { limit, before } = params
try { try {
const contracts = await listAllContracts(limit, before) const contracts = await listAllContracts(limit, before)
// Serve from Vercel cache, then update. see https://vercel.com/docs/concepts/functions/edge-caching // Serve from Vercel cache, then update. see https://vercel.com/docs/concepts/functions/edge-caching