mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
R-E H-5. Up to v0.4.1.1 the iOS app stored mood-entry prose as `tags: ["note:<text>"]` because the server had no dedicated column. The workaround contaminated the tags axis with prose the Coach evidence shelf misread as taxonomic labels. Schema (migration 0063, additive): - mood_entries.note (TEXT, nullable) Validation + routes: - createMoodEntrySchema gains optional note (max 500 chars) - updateMoodEntrySchema accepts note + null to clear - POST /api/mood-entries persists note alongside tags - PUT /api/mood-entries/[id] honours partial note updates - POST /api/mood-entries/bulk carries note through the bulk path Backfill script at scripts/backfill-mood-note-column.ts lifts the legacy note:<text> tag entries into the new column. Idempotent dry-run mode is the default; --confirm commits. Helper logic lives in src/lib/mood/note-backfill.ts for tight unit coverage. iOS contract: additive. Old iOS payloads (no note field) round-trip unchanged. New iOS code paths can read or write note without touching tags.
41 lines
1.1 KiB
TypeScript
41 lines
1.1 KiB
TypeScript
/**
|
|
* v1.4.30 — pure helper for the `MoodEntry.note` backfill (R-E H-5).
|
|
*
|
|
* Pulls the first `note:<text>` entry out of a JSON-encoded tags array
|
|
* and returns the cleaned tags JSON alongside the extracted note. Used
|
|
* by `scripts/backfill-mood-note-column.ts` (CLI) — kept in `src/lib/`
|
|
* so unit tests can exercise the bucketing without booting `dotenv`
|
|
* + the Prisma client.
|
|
*/
|
|
export function extractNoteAndSlimTags(tagsJson: string): {
|
|
note: string | null;
|
|
newTags: string | null;
|
|
} {
|
|
let parsed: unknown;
|
|
try {
|
|
parsed = JSON.parse(tagsJson);
|
|
} catch {
|
|
return { note: null, newTags: tagsJson };
|
|
}
|
|
if (!Array.isArray(parsed)) {
|
|
return { note: null, newTags: tagsJson };
|
|
}
|
|
let extracted: string | null = null;
|
|
const remaining: string[] = [];
|
|
for (const tag of parsed) {
|
|
if (typeof tag !== "string") {
|
|
remaining.push(String(tag));
|
|
continue;
|
|
}
|
|
if (extracted === null && tag.startsWith("note:")) {
|
|
extracted = tag.slice("note:".length);
|
|
} else {
|
|
remaining.push(tag);
|
|
}
|
|
}
|
|
return {
|
|
note: extracted,
|
|
newTags: remaining.length > 0 ? JSON.stringify(remaining) : null,
|
|
};
|
|
}
|