mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
refactor(types): move BackupRow and BackupsList out of route handler into src/types/backups.ts
Resolves the single component → route-handler import in the codebase (`components/admin/backups-section.tsx ← app/api/admin/backups/route.ts`) flagged by the v1.4.39 org audit (recommendation #2). The DTOs now live in `src/types/backups.ts`; the route handler keeps owning the HTTP contract and re-imports the shared types from there.
This commit is contained in:
1 parent
4cca62dce9
commit
bba38b8c66
6 files changed
+52
-28
No files matched your search
@@ -10,34 +10,13 @@ import { prisma } from "@/lib/db";
|
||||
import { apiHandler, requireAdmin } from "@/lib/api-handler";
|
||||
import { apiSuccess } from "@/lib/api-response";
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
// v1.4.41 W-ORG — `BackupRow` / `BackupsList` moved to `src/types/backups.ts`
|
||||
// so callers (in particular `components/admin/backups-section.tsx`) don't
|
||||
// have to reach across the component → route-handler layer boundary.
|
||||
import type { BackupRow, BackupsList } from "@/types/backups";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export interface BackupRow {
|
||||
id: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
type: string;
|
||||
/**
|
||||
* Size of the encrypted blob in bytes — useful for capacity planning.
|
||||
* The blob itself is never returned.
|
||||
*/
|
||||
sizeBytes: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface BackupsList {
|
||||
rows: BackupRow[];
|
||||
/**
|
||||
* Soft retention hint — the worker is configured for weekly backups
|
||||
* (see `DATA_BACKUP_CRON` in `src/lib/jobs/reminder-worker.ts`), and
|
||||
* the model upserts in-place per (userId, type), so each user has
|
||||
* exactly one current snapshot. The frontend uses this to label the
|
||||
* grid; no server-side enforcement.
|
||||
*/
|
||||
retentionDays: number;
|
||||
}
|
||||
|
||||
export const GET = apiHandler(async () => {
|
||||
await requireAdmin();
|
||||
annotate({ action: { name: "admin.backups.list" } });
|
||||
|
||||
@@ -38,7 +38,9 @@ export const GET = apiHandler(async () => {
|
||||
appSettings,
|
||||
] = await Promise.all([
|
||||
prisma.user.count(),
|
||||
prisma.measurement.count(),
|
||||
// v1.4.41 W-DELETED-2 — exclude soft-deleted measurements from the
|
||||
// admin status count so the dashboard tile reflects live data only.
|
||||
prisma.measurement.count({ where: { deletedAt: null } }),
|
||||
prisma.medication.count(),
|
||||
prisma.medicationIntakeEvent.count(),
|
||||
prisma.apiToken.count({ where: { revoked: false } }),
|
||||
|
||||
@@ -60,6 +60,10 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
userId: user.id,
|
||||
measuredAt: { gte: start, lte: end },
|
||||
type: { in: ["BLOOD_PRESSURE_SYS", "BLOOD_PRESSURE_DIA"] },
|
||||
// v1.4.41 W-DELETED-2 — hide soft-deleted rows from the
|
||||
// section-availability probe so the dialog does not offer a
|
||||
// section that would render an empty PDF block.
|
||||
deletedAt: null,
|
||||
},
|
||||
}),
|
||||
prisma.measurement.count({
|
||||
@@ -67,6 +71,7 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
userId: user.id,
|
||||
measuredAt: { gte: start, lte: end },
|
||||
type: "WEIGHT",
|
||||
deletedAt: null,
|
||||
},
|
||||
}),
|
||||
prisma.measurement.count({
|
||||
@@ -74,6 +79,7 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
userId: user.id,
|
||||
measuredAt: { gte: start, lte: end },
|
||||
type: "PULSE",
|
||||
deletedAt: null,
|
||||
},
|
||||
}),
|
||||
prisma.moodEntry.count({
|
||||
|
||||
Reference in new issue
Block a user