Refactor Study Desk application structure
This commit is contained in:
parent
faaccf8a7e
commit
089439ed90
145 changed files with 8087 additions and 3412 deletions
BIN
audit-results/tmp/audit-migration.db
Normal file
BIN
audit-results/tmp/audit-migration.db
Normal file
Binary file not shown.
26
audit-results/tmp/generated-before.sha256
Normal file
26
audit-results/tmp/generated-before.sha256
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
cb737289f5b5f6cdb8b90fc23d2c89ebd41d6602ce99e88bf6dfd751beab7103 *src/generated/prisma/browser.ts
|
||||
2ea331124cc56c9c9a360b4a85f42f029992811ece7efe9db0ec1300a43f59c3 *src/generated/prisma/client.ts
|
||||
f1f6280ff65c1e8aab5ce30307c8777ce1795f81bf1a513396263fc1c9a30e5c *src/generated/prisma/commonInputTypes.ts
|
||||
8bcc37ae19ee9c55424b735ce5f3a0972b7e741958ef86b350c9a54dc2238a0d *src/generated/prisma/enums.ts
|
||||
d52628a3dc8285d9014e2fda489badce6c88604810e2975310ab6c40ec3c708d *src/generated/prisma/internal/class.ts
|
||||
91794eb9b3c395e57b96d18f2bae895149f7b70ddf0fda8b817e7aa9da17a950 *src/generated/prisma/internal/prismaNamespace.ts
|
||||
6645109792ed08507d79da319aaecc2752bffa6e8bd5a3364dccc5ae93e2f23c *src/generated/prisma/internal/prismaNamespaceBrowser.ts
|
||||
b8ffef1ad4428179847aafe66abee3ad5eb74a84fff46265532551b10ab2537d *src/generated/prisma/models.ts
|
||||
daecbb1c94a96d19da4accfdf81fe8f11fa73c543958016bc7d6060d454f3943 *src/generated/prisma/models/AnswerOption.ts
|
||||
87e18727cec17a341d32709bc0c1602c66e6c6dcc57672b9c9fbe38a6ce12801 *src/generated/prisma/models/ArcadeAttempt.ts
|
||||
0c9de62bdbefafe8b5ff5300d1d764cc73235a077f8e3b3e03e6144287610c9d *src/generated/prisma/models/ArcadePack.ts
|
||||
67b8ea01f0a866d14db7fdff3178a080e2879990129c5e08690463fb9940f48d *src/generated/prisma/models/AuthSecurity.ts
|
||||
6885465a57019e8cba28755d9c6abaa087e913d666d02d8912abf0790c41a77b *src/generated/prisma/models/Class.ts
|
||||
ea873177511c6f7354dc01ec0ad228d9f777bca2fbfb15d281d3f2ab8f817ebf *src/generated/prisma/models/Deck.ts
|
||||
1082ff29bec6e4f920c93d778032ffffa324c312b05efd6c5fa7ada1be6674f7 *src/generated/prisma/models/Flashcard.ts
|
||||
de94c2da405c08a0b690aeb1b0cdc03582c94ccddaf913f4c6d1b18d8c413b61 *src/generated/prisma/models/MaterialGroup.ts
|
||||
941998d2c098e9fe5cd0a888bac470190108238c936c1d7cfce2742ed1e40d8a *src/generated/prisma/models/Question.ts
|
||||
3d54ed93e516f4d773c200b166a84ab2c9c8b7b0d7f7ddfd61afc3ca057ee755 *src/generated/prisma/models/QuizAttempt.ts
|
||||
454f19f97a82b8f37fc5c5179e87afe6ea185a79810043471d55c0a8ca26f14a *src/generated/prisma/models/QuizSet.ts
|
||||
3b884aaaad311e8f22c1390cf24ebe69b74b52a97c213781d2a4cbb56288b8a7 *src/generated/prisma/models/Setting.ts
|
||||
1ccf32b2f56b1d35c9b7152d2e1817b4c1b7853549a1ff187e9fb7c29fa49f2a *src/generated/prisma/models/ShareLink.ts
|
||||
cba950d431c702afe67f3ac92d8397275d3aeeebbc59d357fd20dec2123e0ee2 *src/generated/prisma/models/SpacedRepetitionCardState.ts
|
||||
2ef43d1c5d7e2eb0d85080fb29703ae99c1704ba8f5200703e2bb8e7a617bf04 *src/generated/prisma/models/SpacedRepetitionSet.ts
|
||||
0bf9eab9f937ef2d621ccf0cea8e209eae9372a9b333dfe6b18267e563a6b2b0 *src/generated/prisma/models/SpacedRepetitionSetDeck.ts
|
||||
916bda8f95647f0dc3560bc6848c4a97d4c1f37fd5ed54e6736d9d7d45e08adc *src/generated/prisma/models/StudyActivity.ts
|
||||
36724157e76b49df49e7827eacbcb0ab8336917f35913777701d8a6830770500 *src/generated/prisma/models/StudyProgress.ts
|
||||
52
audit-results/tmp/inspect-db.cjs
Normal file
52
audit-results/tmp/inspect-db.cjs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Read-only diagnostic: introspect the temp DB created by `prisma migrate deploy`
|
||||
// to check whether the migrated schema matches schema.prisma (drift check).
|
||||
// Usage: node audit-results/tmp/inspect-db.cjs <path-to-sqlite-db>
|
||||
const path = require("node:path");
|
||||
const Database = require("better-sqlite3");
|
||||
|
||||
const dbPath = process.argv[2];
|
||||
if (!dbPath) {
|
||||
console.error("usage: node inspect-db.cjs <db-path>");
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
const db = new Database(path.resolve(dbPath), { readonly: true });
|
||||
|
||||
const tables = db
|
||||
.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
|
||||
.all()
|
||||
.map((r) => r.name);
|
||||
|
||||
console.log("=== TABLES ===");
|
||||
console.log(tables.join(", "));
|
||||
console.log("Has MaterialGroup table:", tables.includes("MaterialGroup"));
|
||||
|
||||
for (const table of ["Deck", "QuizSet", "ShareLink", "MaterialGroup"]) {
|
||||
if (tables.includes(table)) {
|
||||
const cols = db
|
||||
.prepare(`PRAGMA table_info('${table}')`)
|
||||
.all()
|
||||
.map((r) => r.name);
|
||||
console.log(`--- ${table} columns ---`);
|
||||
console.log(cols.join(", "));
|
||||
if (table === "Deck" || table === "QuizSet" || table === "ShareLink") {
|
||||
console.log(` -> has groupId:`, cols.includes("groupId"));
|
||||
}
|
||||
} else {
|
||||
console.log(`--- ${table}: MISSING TABLE ---`);
|
||||
}
|
||||
}
|
||||
|
||||
const indexes = db
|
||||
.prepare("SELECT name, tbl_name FROM sqlite_master WHERE type='index' ORDER BY name")
|
||||
.all()
|
||||
.map((r) => `${r.tbl_name}.${r.name}`);
|
||||
console.log("=== INDEXES (count) ===", indexes.length);
|
||||
|
||||
// Confirm migrations table
|
||||
const applied = db.prepare("SELECT migration_name FROM _prisma_migrations ORDER BY started_at").all();
|
||||
console.log("=== APPLIED MIGRATIONS ===");
|
||||
applied.forEach((m) => console.log(" -", m.migration_name));
|
||||
|
||||
db.close();
|
||||
console.log("DONE");
|
||||
40
audit-results/tmp/reproduce-drift.cjs
Normal file
40
audit-results/tmp/reproduce-drift.cjs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Read-only diagnostic: execute the exact SQL shape the generated Prisma client
|
||||
// emits for deck.findMany() / materialGroup.findMany() against a DB built purely
|
||||
// from `prisma migrate deploy` (predev + Docker entrypoint flow).
|
||||
// Proves DBAUD-01: migrated DB is incompatible with the shipped client.
|
||||
const path = require("node:path");
|
||||
const Database = require("better-sqlite3");
|
||||
|
||||
const dbPath = path.resolve("audit-results/tmp/audit-migration.db");
|
||||
const db = new Database(dbPath, { readonly: true });
|
||||
|
||||
// 1. Shape of prisma.deck.findMany({ include: { class: true } }) — Prisma selects
|
||||
// every scalar field, including groupId (schema.prisma:33-34, generated client).
|
||||
const deckSql =
|
||||
'SELECT "Deck"."id", "Deck"."classId", "Deck"."name", "Deck"."description", "Deck"."sortOrder", "Deck"."createdAt", "Deck"."groupId" FROM "Deck"';
|
||||
try {
|
||||
db.prepare(deckSql).all();
|
||||
console.log("deck.findMany SQL: OK");
|
||||
} catch (e) {
|
||||
console.log("deck.findMany SQL: FAILED ->", e.message);
|
||||
}
|
||||
|
||||
// 2. Shape of prisma.materialGroup.findMany()
|
||||
const groupSql = 'SELECT "MaterialGroup"."id", "MaterialGroup"."classId", "MaterialGroup"."name", "MaterialGroup"."type", "MaterialGroup"."sortOrder", "MaterialGroup"."createdAt" FROM "MaterialGroup"';
|
||||
try {
|
||||
db.prepare(groupSql).all();
|
||||
console.log("materialGroup.findMany SQL: OK");
|
||||
} catch (e) {
|
||||
console.log("materialGroup.findMany SQL: FAILED ->", e.message);
|
||||
}
|
||||
|
||||
// 3. Shape of prisma.shareLink.findFirst() (share page validation)
|
||||
const shareSql = 'SELECT "ShareLink"."id", "ShareLink"."targetType", "ShareLink"."deckId", "ShareLink"."quizSetId", "ShareLink"."groupId", "ShareLink"."createdAt" FROM "ShareLink" LIMIT 1';
|
||||
try {
|
||||
db.prepare(shareSql).all();
|
||||
console.log("shareLink.findFirst SQL: OK");
|
||||
} catch (e) {
|
||||
console.log("shareLink.findFirst SQL: FAILED ->", e.message);
|
||||
}
|
||||
|
||||
db.close();
|
||||
27
audit-results/tmp/validate-findings.cjs
Normal file
27
audit-results/tmp/validate-findings.cjs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Validates audit-results/FINDINGS.json parses and reports counts per severity.
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
|
||||
const file = path.resolve("audit-results/FINDINGS.json");
|
||||
const raw = fs.readFileSync(file, "utf8");
|
||||
const data = JSON.parse(raw); // throws if invalid
|
||||
|
||||
const findings = data.findings;
|
||||
const bySeverity = {};
|
||||
for (const f of findings) {
|
||||
bySeverity[f.severity] = (bySeverity[f.severity] || 0) + 1;
|
||||
}
|
||||
const byConfidence = {};
|
||||
for (const f of findings) {
|
||||
byConfidence[f.confidence] = (byConfidence[f.confidence] || 0) + 1;
|
||||
}
|
||||
|
||||
const ids = findings.map((f) => f.id);
|
||||
const dupes = ids.filter((id, i) => ids.indexOf(id) !== i);
|
||||
if (dupes.length) throw new Error("duplicate ids: " + dupes.join(","));
|
||||
|
||||
console.log("FINDINGS.json: VALID JSON");
|
||||
console.log("total findings:", findings.length);
|
||||
console.log("by severity:", JSON.stringify(bySeverity));
|
||||
console.log("by confidence:", JSON.stringify(byConfidence));
|
||||
console.log("ids:", ids.join(", "));
|
||||
Loading…
Add table
Add a link
Reference in a new issue