Merge exams grading into homework
Redirect /teacher/exams/grading* to /teacher/homework/submissions; remove exam grading UI/actions/data-access; add homework student workflow and update design docs.
This commit is contained in:
90
docs/scripts/baseline-migrations.js
Normal file
90
docs/scripts/baseline-migrations.js
Normal file
@@ -0,0 +1,90 @@
|
||||
require("dotenv/config");
|
||||
|
||||
const fs = require("node:fs");
|
||||
const crypto = require("node:crypto");
|
||||
const path = require("node:path");
|
||||
const mysql = require("mysql2/promise");
|
||||
|
||||
const JOURNAL = {
|
||||
"0000_aberrant_cobalt_man": 1766460456274,
|
||||
"0001_flawless_texas_twister": 1767004087964,
|
||||
"0002_equal_wolfpack": 1767145757594,
|
||||
};
|
||||
|
||||
function sha256Hex(input) {
|
||||
return crypto.createHash("sha256").update(input).digest("hex");
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const url = process.env.DATABASE_URL;
|
||||
if (!url) {
|
||||
throw new Error("DATABASE_URL is not set");
|
||||
}
|
||||
|
||||
const conn = await mysql.createConnection(url);
|
||||
|
||||
await conn.query(
|
||||
"CREATE TABLE IF NOT EXISTS `__drizzle_migrations` (id serial primary key, hash text not null, created_at bigint)"
|
||||
);
|
||||
|
||||
const [existing] = await conn.query(
|
||||
"SELECT id, hash, created_at FROM `__drizzle_migrations` ORDER BY created_at DESC LIMIT 1"
|
||||
);
|
||||
if (Array.isArray(existing) && existing.length > 0) {
|
||||
console.log("✅ __drizzle_migrations already has entries. Skip baselining.");
|
||||
await conn.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const [[accountsRow]] = await conn.query(
|
||||
"SELECT COUNT(*) AS cnt FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='accounts'"
|
||||
);
|
||||
const accountsExists = Number(accountsRow?.cnt ?? 0) > 0;
|
||||
if (!accountsExists) {
|
||||
console.log("ℹ️ No existing tables detected (accounts missing). Skip baselining.");
|
||||
await conn.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const [[structureRow]] = await conn.query(
|
||||
"SELECT COUNT(*) AS cnt FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='exams' AND column_name='structure'"
|
||||
);
|
||||
const examsStructureExists = Number(structureRow?.cnt ?? 0) > 0;
|
||||
|
||||
const [[homeworkRow]] = await conn.query(
|
||||
"SELECT COUNT(*) AS cnt FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='homework_assignments'"
|
||||
);
|
||||
const homeworkExists = Number(homeworkRow?.cnt ?? 0) > 0;
|
||||
|
||||
const baselineTags = [];
|
||||
baselineTags.push("0000_aberrant_cobalt_man");
|
||||
if (examsStructureExists) baselineTags.push("0001_flawless_texas_twister");
|
||||
if (homeworkExists) baselineTags.push("0002_equal_wolfpack");
|
||||
|
||||
const drizzleDir = path.resolve(__dirname, "..", "..", "drizzle");
|
||||
for (const tag of baselineTags) {
|
||||
const sqlPath = path.join(drizzleDir, `${tag}.sql`);
|
||||
if (!fs.existsSync(sqlPath)) {
|
||||
throw new Error(`Missing migration file: ${sqlPath}`);
|
||||
}
|
||||
const sqlText = fs.readFileSync(sqlPath).toString();
|
||||
const hash = sha256Hex(sqlText);
|
||||
const createdAt = JOURNAL[tag];
|
||||
if (typeof createdAt !== "number") {
|
||||
throw new Error(`Missing journal timestamp for: ${tag}`);
|
||||
}
|
||||
await conn.query(
|
||||
"INSERT INTO `__drizzle_migrations` (`hash`, `created_at`) VALUES (?, ?)",
|
||||
[hash, createdAt]
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`✅ Baselined __drizzle_migrations: ${baselineTags.join(", ")}`);
|
||||
await conn.end();
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error("❌ Baseline failed:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user