mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
chore(release): v1.13.0 — per-user custom mood tags + catalogue hide
Let a user shape their own mood-tag set on top of the global catalogue: create custom tags (label encrypted at rest, icon from a fixed allow-list), and hide built-in tags per user. Custom tags live in `mood_tags` with a non-null `user_id` and a `custom:<uuid>` key; `GET /api/mood/tags` returns the effective per-user set (catalogue − hidden + own customs) with new `custom` + `label` fields, and `?include=hidden` surfaces hidden catalogue tags for the management screen. The write path resolves a `custom:` key only against the caller's own rows — a foreign custom key is dropped, never linked. Delete soft-deactivates by default (history intact); `?purge=true` removes the row and its links. BINARY-only for v1. New: POST/PATCH/DELETE /api/mood/tags/custom[/:key], PUT /api/mood/tags/:key/hidden, migration 0127 (user_id + label_encrypted columns, mood_tag_hidden table, `custom` category). Integration setup snapshots + restores the seeded catalogue because the new mood_tags→users FK makes TRUNCATE users CASCADE wipe it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
09bdd49791
commit
f1329b24e1
21 files changed
+934
-121
No files matched your search
@@ -26,6 +26,11 @@ export function getPrismaClient(): PrismaClient {
|
||||
return prisma;
|
||||
}
|
||||
|
||||
/** Lazily-captured global mood-tag catalogue (NULL user_id rows). */
|
||||
let catalogueSnapshot:
|
||||
| Awaited<ReturnType<PrismaClient["moodTag"]["findMany"]>>
|
||||
| null = null;
|
||||
|
||||
/**
|
||||
* Truncate every user-facing table in dependency-safe order using
|
||||
* `TRUNCATE … RESTART IDENTITY CASCADE`. Call from beforeEach() to make
|
||||
@@ -74,8 +79,29 @@ export async function truncateAllTables(client: PrismaClient): Promise<void> {
|
||||
"workouts",
|
||||
];
|
||||
|
||||
// v1.13.0 — the mood-tag catalogue (`mood_tags` rows with NULL user_id) is
|
||||
// global reference data seeded by migrations and is intentionally NOT in the
|
||||
// truncate list, so tests can rely on it. But `mood_tags.user_id` now FKs to
|
||||
// `users`, so `TRUNCATE users CASCADE` cascades into `mood_tags` and wipes
|
||||
// the catalogue too (TRUNCATE CASCADE truncates dependent tables wholesale,
|
||||
// regardless of the ON DELETE action). Snapshot the catalogue once (before
|
||||
// the first truncate clears it) and restore it after each truncate so the
|
||||
// migration-seeded catalogue persists across tests as it did before the FK.
|
||||
if (catalogueSnapshot === null) {
|
||||
catalogueSnapshot = await client.moodTag.findMany({
|
||||
where: { userId: null },
|
||||
});
|
||||
}
|
||||
|
||||
const quoted = tables.map((t) => `"${t}"`).join(", ");
|
||||
await client.$executeRawUnsafe(
|
||||
`TRUNCATE TABLE ${quoted} RESTART IDENTITY CASCADE;`,
|
||||
);
|
||||
|
||||
if (catalogueSnapshot.length > 0) {
|
||||
await client.moodTag.createMany({
|
||||
data: catalogueSnapshot,
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user