import { Hono } from "hono"; import { logger } from "hono/logger"; import { z } from "zod"; import { db } from "./db"; const app = new Hono(); app.use(logger()); app.get("/health", (c) => c.json({ ok: true })); // --- Customers ------------------------------------------------------------- app.get("/customers", (c) => { return c.json(db.query("SELECT * FROM customers ORDER BY created_at").all()); }); app.get("/customers/:id/invoices", (c) => { const rows = db .query("SELECT * FROM invoices WHERE customer_id = ? ORDER BY created_at DESC") .all(c.req.param("id")); return c.json(rows); }); // --- Subscriptions (happy path: subscribe -> first invoice) ----------------- const CreateSubscription = z.object({ customer_id: z.string(), plan_id: z.string(), }); app.post("/subscriptions", async (c) => { const parsed = CreateSubscription.safeParse(await c.req.json().catch(() => null)); if (!parsed.success) return c.json({ error: z.treeifyError(parsed.error) }, 400); const { customer_id, plan_id } = parsed.data; const customer = db.query("SELECT id FROM customers WHERE id = ?").get(customer_id); if (!customer) return c.json({ error: "customer not found" }, 404); const plan = db .query<{ id: string; amount_cents: number; currency: string; interval: string }, [string]>( "SELECT * FROM plans WHERE id = ?", ) .get(plan_id); if (!plan) return c.json({ error: "plan not found" }, 404); const subId = `sub_${crypto.randomUUID().slice(0, 8)}`; const invId = `inv_${crypto.randomUUID().slice(0, 8)}`; db.transaction(() => { db.run( `INSERT INTO subscriptions (id, customer_id, plan_id, status, current_period_start, current_period_end) VALUES (?, ?, ?, 'active', datetime('now'), datetime('now', ?))`, [subId, customer_id, plan_id, `+1 ${plan.interval}`], ); db.run( `INSERT INTO invoices (id, subscription_id, customer_id, amount_cents, currency, status, due_at) VALUES (?, ?, ?, ?, ?, 'open', datetime('now', '+14 days'))`, [invId, subId, customer_id, plan.amount_cents, plan.currency], ); })(); const subscription = db.query("SELECT * FROM subscriptions WHERE id = ?").get(subId); const invoice = db.query("SELECT * FROM invoices WHERE id = ?").get(invId); return c.json({ subscription, invoice }, 201); }); export default { port: Number(process.env.PORT ?? 3000), fetch: app.fetch, }; console.log(`listening on http://localhost:${process.env.PORT ?? 3000}`);