Set up a read API using Vercel serverless functions (#49)
* Set up read API using Vercel serverless functions Featuring: /api/v0/markets /api/v0/market/[contractId] /api/v0/slug/[contractSlug] * Include tags in API
This commit is contained in:
parent
6701bfca0d
commit
51aa8df010
|
@ -1,13 +0,0 @@
|
|||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
type Data = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export default function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Data>
|
||||
) {
|
||||
res.status(200).json({ name: 'John Doe' })
|
||||
}
|
67
web/pages/api/v0/_types.ts
Normal file
67
web/pages/api/v0/_types.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
import { Bet } from '../../../../common/bet'
|
||||
import { getProbability } from '../../../../common/calculate'
|
||||
import { Comment } from '../../../../common/comment'
|
||||
import { Contract } from '../../../../common/contract'
|
||||
|
||||
export type LiteContract = {
|
||||
id: string
|
||||
creatorUsername: string
|
||||
creatorName: string
|
||||
createdTime: number
|
||||
closeTime?: number
|
||||
question: string
|
||||
description: string
|
||||
tags: string[]
|
||||
url: string
|
||||
pool: number
|
||||
probability: number
|
||||
volume7Days: number
|
||||
volume24Hours: number
|
||||
isResolved: boolean
|
||||
resolution?: string
|
||||
}
|
||||
|
||||
export type FullContract = LiteContract & {
|
||||
bets: Bet[]
|
||||
comments: Comment[]
|
||||
}
|
||||
|
||||
export type ApiError = {
|
||||
error: string
|
||||
}
|
||||
|
||||
export function toLiteContract({
|
||||
id,
|
||||
creatorUsername,
|
||||
creatorName,
|
||||
createdTime,
|
||||
closeTime,
|
||||
question,
|
||||
description,
|
||||
tags,
|
||||
slug,
|
||||
pool,
|
||||
totalShares,
|
||||
volume7Days,
|
||||
volume24Hours,
|
||||
isResolved,
|
||||
resolution,
|
||||
}: Contract): LiteContract {
|
||||
return {
|
||||
id,
|
||||
creatorUsername,
|
||||
creatorName,
|
||||
createdTime,
|
||||
closeTime,
|
||||
question,
|
||||
description,
|
||||
tags,
|
||||
url: `https://manifold.markets/${creatorUsername}/${slug}`,
|
||||
pool: pool.YES + pool.NO,
|
||||
probability: getProbability(totalShares),
|
||||
volume7Days,
|
||||
volume24Hours,
|
||||
isResolved,
|
||||
resolution,
|
||||
}
|
||||
}
|
32
web/pages/api/v0/market/[id].ts
Normal file
32
web/pages/api/v0/market/[id].ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { listAllBets } from '../../../../lib/firebase/bets'
|
||||
import { listAllComments } from '../../../../lib/firebase/comments'
|
||||
import { getContractFromId } from '../../../../lib/firebase/contracts'
|
||||
import { FullContract, ApiError, toLiteContract } from '../_types'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<FullContract | ApiError>
|
||||
) {
|
||||
const { id } = req.query
|
||||
const contractId = id as string
|
||||
|
||||
const [contract, bets, comments] = await Promise.all([
|
||||
getContractFromId(contractId),
|
||||
listAllBets(contractId),
|
||||
listAllComments(contractId),
|
||||
])
|
||||
|
||||
if (!contract) {
|
||||
res.status(404).json({ error: 'Contract not found' })
|
||||
return
|
||||
}
|
||||
|
||||
// Cache on Vercel edge servers for 2min
|
||||
res.setHeader('Cache-Control', 'max-age=0, s-maxage=120')
|
||||
return res.status(200).json({
|
||||
...toLiteContract(contract),
|
||||
bets,
|
||||
comments,
|
||||
})
|
||||
}
|
16
web/pages/api/v0/markets.ts
Normal file
16
web/pages/api/v0/markets.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Next.js API route support: https://vercel.com/docs/concepts/functions/serverless-functions
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { listAllContracts } from '../../../lib/firebase/contracts'
|
||||
import { toLiteContract } from './_types'
|
||||
|
||||
type Data = any[]
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Data>
|
||||
) {
|
||||
const contracts = await listAllContracts()
|
||||
// Serve from Vercel cache, then update. see https://vercel.com/docs/concepts/functions/edge-caching
|
||||
res.setHeader('Cache-Control', 's-maxage=1, stale-while-revalidate')
|
||||
res.status(200).json(contracts.map(toLiteContract))
|
||||
}
|
32
web/pages/api/v0/slug/[slug].ts
Normal file
32
web/pages/api/v0/slug/[slug].ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { listAllBets } from '../../../../lib/firebase/bets'
|
||||
import { listAllComments } from '../../../../lib/firebase/comments'
|
||||
import { getContractFromSlug } from '../../../../lib/firebase/contracts'
|
||||
import { FullContract, ApiError, toLiteContract } from '../_types'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<FullContract | ApiError>
|
||||
) {
|
||||
const { slug } = req.query
|
||||
|
||||
const contract = await getContractFromSlug(slug as string)
|
||||
|
||||
if (!contract) {
|
||||
res.status(404).json({ error: 'Contract not found' })
|
||||
return
|
||||
}
|
||||
|
||||
const [bets, comments] = await Promise.all([
|
||||
listAllBets(contract.id),
|
||||
listAllComments(contract.id),
|
||||
])
|
||||
|
||||
// Cache on Vercel edge servers for 2min
|
||||
res.setHeader('Cache-Control', 'max-age=0, s-maxage=120')
|
||||
return res.status(200).json({
|
||||
...toLiteContract(contract),
|
||||
bets,
|
||||
comments,
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user