feat: convert campaigns, game-items, game-talents, rolls routes to async mysql2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aaron Wood 2026-04-11 00:09:46 -04:00
parent dbc12ac816
commit 268997a009
4 changed files with 54 additions and 49 deletions

View file

@ -1,50 +1,55 @@
import { Router } from "express"; import { Router } from "express";
import type { RowDataPacket, ResultSetHeader } from "mysql2";
import db from "../db.js"; import db from "../db.js";
const router = Router(); const router = Router();
// GET /api/campaigns — list all campaigns // GET /api/campaigns
router.get("/", (_req, res) => { router.get("/", async (_req, res) => {
const campaigns = db const [rows] = await db.execute<RowDataPacket[]>(
.prepare("SELECT * FROM campaigns ORDER BY created_at DESC") "SELECT * FROM campaigns ORDER BY created_at DESC"
.all(); );
res.json(campaigns); res.json(rows);
}); });
// POST /api/campaigns — create a campaign // POST /api/campaigns
router.post("/", (req, res) => { router.post("/", async (req, res) => {
const { name } = req.body; const { name } = req.body;
if (!name || !name.trim()) { if (!name?.trim()) {
res.status(400).json({ error: "Campaign name is required" }); res.status(400).json({ error: "Campaign name is required" });
return; return;
} }
const result = db const [result] = await db.execute<ResultSetHeader>(
.prepare("INSERT INTO campaigns (name) VALUES (?)") "INSERT INTO campaigns (name) VALUES (?)",
.run(name.trim()); [name.trim()]
const campaign = db );
.prepare("SELECT * FROM campaigns WHERE id = ?") const [rows] = await db.execute<RowDataPacket[]>(
.get(result.lastInsertRowid); "SELECT * FROM campaigns WHERE id = ?",
res.status(201).json(campaign); [result.insertId]
);
res.status(201).json(rows[0]);
}); });
// GET /api/campaigns/:id — get a single campaign // GET /api/campaigns/:id
router.get("/:id", (req, res) => { router.get("/:id", async (req, res) => {
const campaign = db const [rows] = await db.execute<RowDataPacket[]>(
.prepare("SELECT * FROM campaigns WHERE id = ?") "SELECT * FROM campaigns WHERE id = ?",
.get(req.params.id); [req.params.id]
if (!campaign) { );
if (rows.length === 0) {
res.status(404).json({ error: "Campaign not found" }); res.status(404).json({ error: "Campaign not found" });
return; return;
} }
res.json(campaign); res.json(rows[0]);
}); });
// DELETE /api/campaigns/:id — delete a campaign (cascades to characters) // DELETE /api/campaigns/:id
router.delete("/:id", (req, res) => { router.delete("/:id", async (req, res) => {
const result = db const [result] = await db.execute<ResultSetHeader>(
.prepare("DELETE FROM campaigns WHERE id = ?") "DELETE FROM campaigns WHERE id = ?",
.run(req.params.id); [req.params.id]
if (result.changes === 0) { );
if (result.affectedRows === 0) {
res.status(404).json({ error: "Campaign not found" }); res.status(404).json({ error: "Campaign not found" });
return; return;
} }

View file

@ -1,13 +1,14 @@
import { Router } from "express"; import { Router } from "express";
import type { RowDataPacket } from "mysql2";
import db from "../db.js"; import db from "../db.js";
const router = Router(); const router = Router();
router.get("/", (_req, res) => { router.get("/", async (_req, res) => {
const items = db const [rows] = await db.execute<RowDataPacket[]>(
.prepare("SELECT * FROM game_items ORDER BY type, name") "SELECT * FROM game_items ORDER BY type, name"
.all() as Array<Record<string, unknown>>; );
const parsed = items.map((item) => ({ const parsed = rows.map((item) => ({
...item, ...item,
effects: JSON.parse(item.effects as string), effects: JSON.parse(item.effects as string),
properties: JSON.parse(item.properties as string), properties: JSON.parse(item.properties as string),

View file

@ -1,13 +1,14 @@
import { Router } from "express"; import { Router } from "express";
import type { RowDataPacket } from "mysql2";
import db from "../db.js"; import db from "../db.js";
const router = Router(); const router = Router();
router.get("/", (_req, res) => { router.get("/", async (_req, res) => {
const talents = db const [rows] = await db.execute<RowDataPacket[]>(
.prepare("SELECT * FROM game_talents ORDER BY source, name") "SELECT * FROM game_talents ORDER BY source, name"
.all() as Array<Record<string, unknown>>; );
const parsed = talents.map((t) => ({ const parsed = rows.map((t) => ({
...t, ...t,
effect: JSON.parse(t.effect as string), effect: JSON.parse(t.effect as string),
})); }));

View file

@ -1,24 +1,22 @@
import { Router } from "express"; import { Router } from "express";
import type { RowDataPacket } from "mysql2";
import db from "../db.js"; import db from "../db.js";
const router = Router({ mergeParams: true }); const router = Router({ mergeParams: true });
router.get("/", (req, res) => { router.get("/", async (req: any, res) => {
const { campaignId } = req.params; const { campaignId } = req.params as { campaignId: string };
const rolls = db const [rows] = await db.execute<RowDataPacket[]>(
.prepare( "SELECT * FROM roll_log WHERE campaign_id = ? ORDER BY created_at DESC LIMIT 50",
"SELECT * FROM roll_log WHERE campaign_id = ? ORDER BY created_at DESC LIMIT 50", [campaignId]
) );
.all(campaignId) as Array<Record<string, unknown>>; const parsed = rows.map((r) => ({
const parsed = rolls.map((r) => ({
...r, ...r,
rolls: JSON.parse(r.rolls as string), rolls: JSON.parse(r.rolls as string),
advantage: r.advantage === 1, advantage: r.advantage === 1,
disadvantage: r.disadvantage === 1, disadvantage: r.disadvantage === 1,
nat20: r.nat20 === 1, nat20: r.nat20 === 1,
})); }));
res.json(parsed); res.json(parsed);
}); });