feat: initial sbsports deployment setup
Add Coolify/Woodpecker CI config, .gitignore, and deployment scripts.
This commit is contained in:
150
server/index.js
Normal file
150
server/index.js
Normal file
@@ -0,0 +1,150 @@
|
||||
import express from "express";
|
||||
import { join, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import db from "./db.js";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
// Serve Vue build in production
|
||||
const distPath = join(__dirname, "../dist");
|
||||
app.use(express.static(distPath));
|
||||
|
||||
// ── Students ──────────────────────────────────────────────────────────────
|
||||
|
||||
app.get("/api/students", (_req, res) => {
|
||||
res.json(
|
||||
db.prepare("SELECT * FROM students ORDER BY lastName, firstName").all(),
|
||||
);
|
||||
});
|
||||
|
||||
app.post("/api/students", (req, res) => {
|
||||
const { id, firstName, lastName, age, sex, weight, height, imc } = req.body;
|
||||
db.prepare(
|
||||
`
|
||||
INSERT INTO students (id, firstName, lastName, age, sex, weight, height, imc)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`,
|
||||
).run(id, firstName, lastName, age, sex, weight, height, imc);
|
||||
res.status(201).json({ id });
|
||||
});
|
||||
|
||||
app.put("/api/students/:id", (req, res) => {
|
||||
const { firstName, lastName, age, sex, weight, height, imc } = req.body;
|
||||
const info = db
|
||||
.prepare(
|
||||
`
|
||||
UPDATE students SET firstName=?, lastName=?, age=?, sex=?, weight=?, height=?, imc=?
|
||||
WHERE id=?
|
||||
`,
|
||||
)
|
||||
.run(firstName, lastName, age, sex, weight, height, imc, req.params.id);
|
||||
if (info.changes === 0) return res.status(404).json({ error: "Not found" });
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
app.delete("/api/students/:id", (req, res) => {
|
||||
// CASCADE deletes linked activities automatically (FK ON DELETE CASCADE)
|
||||
db.prepare("DELETE FROM students WHERE id=?").run(req.params.id);
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
// ── Activities ────────────────────────────────────────────────────────────
|
||||
|
||||
app.get("/api/activities", (_req, res) => {
|
||||
res.json(
|
||||
db.prepare("SELECT * FROM activities ORDER BY createdAt DESC").all(),
|
||||
);
|
||||
});
|
||||
|
||||
app.post("/api/activities", (req, res) => {
|
||||
const {
|
||||
id,
|
||||
studentId,
|
||||
type,
|
||||
durationInput,
|
||||
durationUnit,
|
||||
duration,
|
||||
displayDuration,
|
||||
intensity,
|
||||
lifestyle,
|
||||
anxiety,
|
||||
grade,
|
||||
date,
|
||||
} = req.body;
|
||||
db.prepare(
|
||||
`
|
||||
INSERT INTO activities
|
||||
(id, studentId, type, durationInput, durationUnit, duration, displayDuration, intensity, lifestyle, anxiety, grade, date)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`,
|
||||
).run(
|
||||
id,
|
||||
studentId,
|
||||
type,
|
||||
durationInput,
|
||||
durationUnit,
|
||||
duration,
|
||||
displayDuration,
|
||||
intensity,
|
||||
lifestyle,
|
||||
anxiety ?? 0,
|
||||
grade,
|
||||
date,
|
||||
);
|
||||
res.status(201).json({ id });
|
||||
});
|
||||
|
||||
app.put("/api/activities/:id", (req, res) => {
|
||||
const {
|
||||
type,
|
||||
durationInput,
|
||||
durationUnit,
|
||||
duration,
|
||||
displayDuration,
|
||||
intensity,
|
||||
lifestyle,
|
||||
anxiety,
|
||||
grade,
|
||||
date,
|
||||
} = req.body;
|
||||
const info = db
|
||||
.prepare(
|
||||
`
|
||||
UPDATE activities
|
||||
SET type=?, durationInput=?, durationUnit=?, duration=?, displayDuration=?,
|
||||
intensity=?, lifestyle=?, anxiety=?, grade=?, date=?
|
||||
WHERE id=?
|
||||
`,
|
||||
)
|
||||
.run(
|
||||
type,
|
||||
durationInput,
|
||||
durationUnit,
|
||||
duration,
|
||||
displayDuration,
|
||||
intensity,
|
||||
lifestyle,
|
||||
anxiety ?? 0,
|
||||
grade,
|
||||
date,
|
||||
req.params.id,
|
||||
);
|
||||
if (info.changes === 0) return res.status(404).json({ error: "Not found" });
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
app.delete("/api/activities/:id", (req, res) => {
|
||||
db.prepare("DELETE FROM activities WHERE id=?").run(req.params.id);
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
// ── SPA fallback ──────────────────────────────────────────────────────────
|
||||
app.get("*", (_req, res) => {
|
||||
res.sendFile(join(distPath, "index.html"));
|
||||
});
|
||||
|
||||
app.listen(PORT, () => console.log(`SB Sports API running on :${PORT}`));
|
||||
Reference in New Issue
Block a user