mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
merge(labs): drop orphaned lab read helper and dead trend query-key
This commit is contained in:
commit
a4b508f720
2 files changed
+4
-52
No files matched your search
+4
-48
@@ -1,23 +1,14 @@
|
||||
/**
|
||||
* v1.17.1 — server-side helpers for the structured lab-result store.
|
||||
*
|
||||
* Two concerns live here:
|
||||
*
|
||||
* 1. The AES-256-GCM ↔ `Bytes` codec for `LabResult.noteEncrypted`. The
|
||||
* free-text note is the only sensitive column on the model; it shares
|
||||
* the `encrypt()` string format (`"<keyId>.<base64>"`) every other
|
||||
* `*Encrypted` column uses, encoded as UTF-8 bytes.
|
||||
*
|
||||
* 2. `findLatestLabResultForAnalytes` — the read point the Vorsorge
|
||||
* annual-blood-panel reminder consults to decide whether a panel was
|
||||
* recorded inside its lead-time window. Exposed here, NOT coupled to
|
||||
* the reminder's code, so the reminder can mark itself satisfied
|
||||
* without this module taking a dependency on it.
|
||||
* The AES-256-GCM ↔ `Bytes` codec for `LabResult.noteEncrypted`. The
|
||||
* free-text note is the only sensitive column on the model; it shares the
|
||||
* `encrypt()` string format (`"<keyId>.<base64>"`) every other `*Encrypted`
|
||||
* column uses, encoded as UTF-8 bytes.
|
||||
*/
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
import { decrypt, encrypt } from "@/lib/crypto";
|
||||
import { prisma } from "@/lib/db";
|
||||
|
||||
/** Encrypt a UTF-8 note into the `Bytes` payload the schema stores. */
|
||||
export function encryptNoteToBytes(plaintext: string): Uint8Array<ArrayBuffer> {
|
||||
@@ -34,38 +25,3 @@ export function encryptNoteToBytes(plaintext: string): Uint8Array<ArrayBuffer> {
|
||||
export function decryptNoteFromBytes(buf: Uint8Array): string {
|
||||
return decrypt(Buffer.from(buf).toString("utf8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Latest live (non-tombstoned) lab result for any of the given analytes,
|
||||
* recorded at or after `since`. Returns the single most-recent matching
|
||||
* row by `takenAt`, or `null` when no matching result exists in the window.
|
||||
*
|
||||
* Case-insensitive analyte match so "HbA1c" / "hba1c" resolve the same — a
|
||||
* lab report's casing is not the user's concern. The Vorsorge reminder
|
||||
* passes the analytes that satisfy an annual blood panel (e.g. an HbA1c or
|
||||
* a lipid marker) plus the reminder's window start; a non-null return means
|
||||
* the panel was recorded and the reminder can mark itself satisfied.
|
||||
*/
|
||||
export async function findLatestLabResultForAnalytes(
|
||||
userId: string,
|
||||
analytes: string[],
|
||||
since: Date,
|
||||
): Promise<{ id: string; analyte: string; takenAt: Date } | null> {
|
||||
if (analytes.length === 0) return null;
|
||||
const candidates = await prisma.labResult.findMany({
|
||||
where: {
|
||||
userId,
|
||||
deletedAt: null,
|
||||
takenAt: { gte: since },
|
||||
// Prisma has no case-insensitive `in`; match each analyte
|
||||
// case-insensitively and let the DB OR them together.
|
||||
OR: analytes.map((a) => ({
|
||||
analyte: { equals: a, mode: "insensitive" as const },
|
||||
})),
|
||||
},
|
||||
orderBy: { takenAt: "desc" },
|
||||
take: 1,
|
||||
select: { id: true, analyte: true, takenAt: true },
|
||||
});
|
||||
return candidates[0] ?? null;
|
||||
}
|
||||
@@ -26,8 +26,4 @@ export const labKeys = {
|
||||
params.page,
|
||||
params.sortDir,
|
||||
] as const,
|
||||
|
||||
/** Per-analyte trend series (≥2 values) shown inline on a grouped card. */
|
||||
labAnalyteTrend: (analyte: string) =>
|
||||
["lab-results", "trend", analyte] as const,
|
||||
};
|
||||
Reference in new issue
Block a user