diff --git a/lib/db/schema.ts b/lib/db/schema.ts index 8377516..ab5a564 100644 --- a/lib/db/schema.ts +++ b/lib/db/schema.ts @@ -1,16 +1,37 @@ import { z } from "zod" -// When defining your database schema, try to use snake case for column names. + // When defining your database schema, try to use snake case for column names. -export const thingSchema = z.object({ - thing_id: z.string(), - name: z.string(), - description: z.string(), -}) -export type Thing = z.infer + export const thingSchema = z.object({ + thing_id: z.string(), + name: z.string(), + description: z.string(), + }) + export type Thing = z.infer -export const databaseSchema = z.object({ - idCounter: z.number().default(0), - things: z.array(thingSchema).default([]), -}) -export type DatabaseSchema = z.infer + export const bountySchema = z.object({ + bounty_id: z.string(), + issue_url: z.string(), + amount_usd: z.number(), + status: z.enum(["open", "in_progress", "paid"]).default("open"), + created_at: z.string(), + }) + export type Bounty = z.infer + + export const paymentSchema = z.object({ + payment_id: z.string(), + bounty_id: z.string(), + recipient_username: z.string(), + amount_usd: z.number(), + paid_at: z.string(), + }) + export type Payment = z.infer + + export const databaseSchema = z.object({ + idCounter: z.number().default(0), + things: z.array(thingSchema).default([]), + bounties: z.array(bountySchema).default([]), + payments: z.array(paymentSchema).default([]), + }) + export type DatabaseSchema = z.infer + \ No newline at end of file diff --git a/routes/bounties/create.ts b/routes/bounties/create.ts new file mode 100644 index 0000000..68dacc7 --- /dev/null +++ b/routes/bounties/create.ts @@ -0,0 +1,32 @@ +import { withRouteSpec } from "lib/middleware/with-winter-spec" + import { z } from "zod" + import { randomUUID } from "crypto" + + export default withRouteSpec({ + methods: ["POST"], + jsonBody: z.object({ + issue_url: z.string().url(), + amount_usd: z.number().positive(), + }), + jsonResponse: z.object({ + bounty: z.object({ + bounty_id: z.string(), + issue_url: z.string(), + amount_usd: z.number(), + status: z.string(), + created_at: z.string(), + }), + }), + })(async (req, ctx) => { + const { issue_url, amount_usd } = await req.json() + const bounty = { + bounty_id: randomUUID(), + issue_url, + amount_usd, + status: "open" as const, + created_at: new Date().toISOString(), + } + ctx.db.addBounty(bounty) + return ctx.json({ bounty }) + }) + \ No newline at end of file diff --git a/routes/bounties/list.ts b/routes/bounties/list.ts new file mode 100644 index 0000000..ff80c61 --- /dev/null +++ b/routes/bounties/list.ts @@ -0,0 +1,18 @@ +import { withRouteSpec } from "lib/middleware/with-winter-spec" + import { z } from "zod" + + export default withRouteSpec({ + methods: ["GET"], + jsonResponse: z.object({ + bounties: z.array(z.object({ + bounty_id: z.string(), + issue_url: z.string(), + amount_usd: z.number(), + status: z.string(), + created_at: z.string(), + })), + }), + })(async (req, ctx) => { + return ctx.json({ bounties: ctx.db.getBounties() }) + }) + \ No newline at end of file diff --git a/routes/payments/create.ts b/routes/payments/create.ts new file mode 100644 index 0000000..a14a9c2 --- /dev/null +++ b/routes/payments/create.ts @@ -0,0 +1,33 @@ +import { withRouteSpec } from "lib/middleware/with-winter-spec" + import { z } from "zod" + import { randomUUID } from "crypto" + + export default withRouteSpec({ + methods: ["POST"], + jsonBody: z.object({ + bounty_id: z.string(), + recipient_username: z.string(), + amount_usd: z.number().positive(), + }), + jsonResponse: z.object({ + payment: z.object({ + payment_id: z.string(), + bounty_id: z.string(), + recipient_username: z.string(), + amount_usd: z.number(), + paid_at: z.string(), + }), + }), + })(async (req, ctx) => { + const { bounty_id, recipient_username, amount_usd } = await req.json() + const payment = { + payment_id: randomUUID(), + bounty_id, + recipient_username, + amount_usd, + paid_at: new Date().toISOString(), + } + ctx.db.addPayment(payment) + return ctx.json({ payment }) + }) + \ No newline at end of file