mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
style: apply prettier across the tree
One-shot prettier pass so the new format:check gate starts from a clean baseline. Formatting only — no behaviour change. Generator-owned and vendored artifacts stay untouched via .prettierignore.
This commit is contained in:
1 parent
b3fea2ef59
commit
1f4ba5939d
1000 files changed
+12130
-8385
No files matched your search
@@ -107,7 +107,9 @@ export const GET = apiHandler(async () => {
|
||||
// Only surface timings on the cache-miss path (the hit path skips the
|
||||
// whole builder and leaves `timings` empty).
|
||||
if (Object.keys(timings).length > 0) {
|
||||
annotate({ meta: { ...timings, snapshot_extras_present: body.extras !== null } });
|
||||
annotate({
|
||||
meta: { ...timings, snapshot_extras_present: body.extras !== null },
|
||||
});
|
||||
}
|
||||
|
||||
const response = apiSuccess(body);
|
||||
|
||||
@@ -325,7 +325,10 @@ describe("GET /api/dashboard/summary", () => {
|
||||
};
|
||||
};
|
||||
const bp = body.data.metrics.find((m) => m.id === "bp");
|
||||
expect(bp, "bp tile must be emitted for stale-but-valid history").toBeDefined();
|
||||
expect(
|
||||
bp,
|
||||
"bp tile must be emitted for stale-but-valid history",
|
||||
).toBeDefined();
|
||||
expect(bp?.latestValue).toBe(132);
|
||||
expect(bp?.secondaryValue).toBe(84);
|
||||
expect(bp?.allTimeCount).toBe(28);
|
||||
@@ -421,13 +424,55 @@ describe("GET /api/dashboard/summary", () => {
|
||||
{ type: "PULSE", value: 71, measured_at: days(30) },
|
||||
] as never)
|
||||
.mockResolvedValueOnce([
|
||||
{ type: "PULSE", bucket_start: days(36), mean: 68, count: 3, sum_value: null },
|
||||
{ type: "PULSE", bucket_start: days(35), mean: 70, count: 3, sum_value: null },
|
||||
{ type: "PULSE", bucket_start: days(34), mean: 69, count: 3, sum_value: null },
|
||||
{ type: "PULSE", bucket_start: days(33), mean: 71, count: 3, sum_value: null },
|
||||
{ type: "PULSE", bucket_start: days(32), mean: 73, count: 3, sum_value: null },
|
||||
{ type: "PULSE", bucket_start: days(31), mean: 72, count: 3, sum_value: null },
|
||||
{ type: "PULSE", bucket_start: days(30), mean: 71, count: 3, sum_value: null },
|
||||
{
|
||||
type: "PULSE",
|
||||
bucket_start: days(36),
|
||||
mean: 68,
|
||||
count: 3,
|
||||
sum_value: null,
|
||||
},
|
||||
{
|
||||
type: "PULSE",
|
||||
bucket_start: days(35),
|
||||
mean: 70,
|
||||
count: 3,
|
||||
sum_value: null,
|
||||
},
|
||||
{
|
||||
type: "PULSE",
|
||||
bucket_start: days(34),
|
||||
mean: 69,
|
||||
count: 3,
|
||||
sum_value: null,
|
||||
},
|
||||
{
|
||||
type: "PULSE",
|
||||
bucket_start: days(33),
|
||||
mean: 71,
|
||||
count: 3,
|
||||
sum_value: null,
|
||||
},
|
||||
{
|
||||
type: "PULSE",
|
||||
bucket_start: days(32),
|
||||
mean: 73,
|
||||
count: 3,
|
||||
sum_value: null,
|
||||
},
|
||||
{
|
||||
type: "PULSE",
|
||||
bucket_start: days(31),
|
||||
mean: 72,
|
||||
count: 3,
|
||||
sum_value: null,
|
||||
},
|
||||
{
|
||||
type: "PULSE",
|
||||
bucket_start: days(30),
|
||||
mean: 71,
|
||||
count: 3,
|
||||
sum_value: null,
|
||||
},
|
||||
] as never)
|
||||
.mockResolvedValueOnce([] as never);
|
||||
|
||||
@@ -498,10 +543,26 @@ describe("GET /api/dashboard/summary", () => {
|
||||
] as never);
|
||||
// Raw per-stage rows for the night (the sleep findMany read).
|
||||
vi.mocked(prisma.measurement.findMany).mockResolvedValue([
|
||||
{ value: 480, measuredAt: new Date("2026-06-03T23:00:00.000Z"), sleepStage: "IN_BED" },
|
||||
{ value: 240, measuredAt: new Date("2026-06-04T00:00:00.000Z"), sleepStage: "CORE" },
|
||||
{ value: 90, measuredAt: new Date("2026-06-04T02:00:00.000Z"), sleepStage: "DEEP" },
|
||||
{ value: 80, measuredAt: new Date("2026-06-04T04:00:00.000Z"), sleepStage: "REM" },
|
||||
{
|
||||
value: 480,
|
||||
measuredAt: new Date("2026-06-03T23:00:00.000Z"),
|
||||
sleepStage: "IN_BED",
|
||||
},
|
||||
{
|
||||
value: 240,
|
||||
measuredAt: new Date("2026-06-04T00:00:00.000Z"),
|
||||
sleepStage: "CORE",
|
||||
},
|
||||
{
|
||||
value: 90,
|
||||
measuredAt: new Date("2026-06-04T02:00:00.000Z"),
|
||||
sleepStage: "DEEP",
|
||||
},
|
||||
{
|
||||
value: 80,
|
||||
measuredAt: new Date("2026-06-04T04:00:00.000Z"),
|
||||
sleepStage: "REM",
|
||||
},
|
||||
{ value: 20, measuredAt: wake, sleepStage: "AWAKE" },
|
||||
] as never);
|
||||
const res = await callGet(makeReq());
|
||||
|
||||
@@ -334,9 +334,9 @@ export const GET = apiHandler(async () => {
|
||||
// existing `invalidateUserMeasurements` + the v1.4.38-extended
|
||||
// `invalidateUserMedications` hooks.
|
||||
const body = await cached(
|
||||
caches.analytics as ServerCache<Awaited<
|
||||
ReturnType<typeof buildDashboardSummary>
|
||||
>>,
|
||||
caches.analytics as ServerCache<
|
||||
Awaited<ReturnType<typeof buildDashboardSummary>>
|
||||
>,
|
||||
`${user.id}|dashboard-summary`,
|
||||
() => buildDashboardSummary(user.id, userTz, buildContext(user)),
|
||||
annotate,
|
||||
@@ -350,9 +350,11 @@ interface SummaryBuilderContext {
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
function buildContext(
|
||||
user: { displayName: string | null; username: string; locale: string | null },
|
||||
): SummaryBuilderContext {
|
||||
function buildContext(user: {
|
||||
displayName: string | null;
|
||||
username: string;
|
||||
locale: string | null;
|
||||
}): SummaryBuilderContext {
|
||||
const greetingName = user.displayName ?? user.username;
|
||||
// v1.5.x — accept every shipped locale (de / en / es / fr / it / pl)
|
||||
// so the greeting + streak label resolve against the user's
|
||||
@@ -395,7 +397,10 @@ async function buildDashboardSummary(
|
||||
// perf-verify can attribute a regression to a specific sub-query
|
||||
// without re-instrumenting the route.
|
||||
const timings: Record<string, number> = {};
|
||||
const time = async <T>(label: string, builder: () => Promise<T>): Promise<T> => {
|
||||
const time = async <T>(
|
||||
label: string,
|
||||
builder: () => Promise<T>,
|
||||
): Promise<T> => {
|
||||
const t0 = Date.now();
|
||||
const result = await builder();
|
||||
timings[`dashboard.sub_${label}_ms`] = Date.now() - t0;
|
||||
@@ -424,8 +429,10 @@ async function buildDashboardSummary(
|
||||
measurementStreakDays,
|
||||
sleepStageRows,
|
||||
] = await Promise.all([
|
||||
time("latestEver", () =>
|
||||
prisma.$queryRaw<LatestEverRow[]>`
|
||||
time(
|
||||
"latestEver",
|
||||
() =>
|
||||
prisma.$queryRaw<LatestEverRow[]>`
|
||||
SELECT DISTINCT ON (m."type")
|
||||
m."type" AS type,
|
||||
m."value"::double precision AS value,
|
||||
@@ -436,8 +443,10 @@ async function buildDashboardSummary(
|
||||
ORDER BY m."type", m."measured_at" DESC
|
||||
`,
|
||||
),
|
||||
time("sparkline", () =>
|
||||
prisma.$queryRaw<SparklineRow[]>`
|
||||
time(
|
||||
"sparkline",
|
||||
() =>
|
||||
prisma.$queryRaw<SparklineRow[]>`
|
||||
SELECT type, bucket_start, mean, count, sum_value
|
||||
FROM (
|
||||
SELECT
|
||||
@@ -497,8 +506,10 @@ async function buildDashboardSummary(
|
||||
// conversion is folded server-side so the day boundary matches
|
||||
// `userDayKey`'s output (it formats the timestamp in the user's
|
||||
// tz before slicing YYYY-MM-DD).
|
||||
time("streakDays", () =>
|
||||
prisma.$queryRaw<ActivityDayRow[]>`
|
||||
time(
|
||||
"streakDays",
|
||||
() =>
|
||||
prisma.$queryRaw<ActivityDayRow[]>`
|
||||
SELECT DISTINCT
|
||||
to_char(
|
||||
(m."measured_at" AT TIME ZONE ${userTz}),
|
||||
|
||||
@@ -37,8 +37,7 @@ vi.mock("@/lib/db-compat", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/logging/context", async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import("@/lib/logging/context")>();
|
||||
const actual = await importOriginal<typeof import("@/lib/logging/context")>();
|
||||
return {
|
||||
...actual,
|
||||
annotate: vi.fn(),
|
||||
@@ -188,11 +187,13 @@ describe("PUT /api/dashboard/widgets — 422 multi-issue envelope (v1.4.42 W2)",
|
||||
const res = await callPut(makeReq(payload));
|
||||
expect(res.status).toBe(422);
|
||||
|
||||
const annotated = vi.mocked(annotate).mock.calls.find(
|
||||
(call) =>
|
||||
(call[0] as { action?: { name?: string } })?.action?.name ===
|
||||
"dashboard.widgets.validation-failed",
|
||||
);
|
||||
const annotated = vi
|
||||
.mocked(annotate)
|
||||
.mock.calls.find(
|
||||
(call) =>
|
||||
(call[0] as { action?: { name?: string } })?.action?.name ===
|
||||
"dashboard.widgets.validation-failed",
|
||||
);
|
||||
expect(annotated, "validation-failed annotate call").toBeTruthy();
|
||||
const meta = (annotated![0] as { meta?: Record<string, unknown> }).meta!;
|
||||
|
||||
@@ -206,7 +207,7 @@ describe("PUT /api/dashboard/widgets — 422 multi-issue envelope (v1.4.42 W2)",
|
||||
expect((meta.received_shape_excerpt as string).length).toBeLessThanOrEqual(
|
||||
256,
|
||||
);
|
||||
expect(meta.received_shape_excerpt as string).toContain("\"version\":2");
|
||||
expect(meta.received_shape_excerpt as string).toContain('"version":2');
|
||||
|
||||
// zod_issues is the same sanitised array surfaced under details.issues.
|
||||
const issues = meta.zod_issues as Array<{ path: string; code: string }>;
|
||||
@@ -230,11 +231,13 @@ describe("PUT /api/dashboard/widgets — 422 multi-issue envelope (v1.4.42 W2)",
|
||||
const res = await callPut(makeReq({ version: 99, widgets }));
|
||||
expect(res.status).toBe(422);
|
||||
|
||||
const annotated = vi.mocked(annotate).mock.calls.find(
|
||||
(call) =>
|
||||
(call[0] as { action?: { name?: string } })?.action?.name ===
|
||||
"dashboard.widgets.validation-failed",
|
||||
);
|
||||
const annotated = vi
|
||||
.mocked(annotate)
|
||||
.mock.calls.find(
|
||||
(call) =>
|
||||
(call[0] as { action?: { name?: string } })?.action?.name ===
|
||||
"dashboard.widgets.validation-failed",
|
||||
);
|
||||
const meta = (annotated![0] as { meta?: Record<string, unknown> }).meta!;
|
||||
expect((meta.received_shape_excerpt as string).length).toBe(256);
|
||||
});
|
||||
@@ -268,11 +271,13 @@ describe("PUT /api/dashboard/widgets — 422 multi-issue envelope (v1.4.42 W2)",
|
||||
const res = await callPut(makeReq(payload));
|
||||
expect(res.status).toBe(422);
|
||||
|
||||
const annotated = vi.mocked(annotate).mock.calls.find(
|
||||
(call) =>
|
||||
(call[0] as { action?: { name?: string } })?.action?.name ===
|
||||
"dashboard.widgets.validation-failed",
|
||||
);
|
||||
const annotated = vi
|
||||
.mocked(annotate)
|
||||
.mock.calls.find(
|
||||
(call) =>
|
||||
(call[0] as { action?: { name?: string } })?.action?.name ===
|
||||
"dashboard.widgets.validation-failed",
|
||||
);
|
||||
const meta = (annotated![0] as { meta?: Record<string, unknown> }).meta!;
|
||||
const excerpt = meta.received_shape_excerpt as string;
|
||||
|
||||
@@ -337,7 +342,8 @@ describe("PUT /api/dashboard/widgets — accept-and-ignore unknown ids (v1.7.0 #
|
||||
|
||||
// The persisted blob never carries the unknown id.
|
||||
expect(prisma.user.update).toHaveBeenCalledTimes(1);
|
||||
const updateArg = vi.mocked(prisma.user.update).mock.calls[0]?.[0] as unknown as {
|
||||
const updateArg = vi.mocked(prisma.user.update).mock
|
||||
.calls[0]?.[0] as unknown as {
|
||||
data: { dashboardWidgetsJson: { widgets: Array<{ id: string }> } };
|
||||
};
|
||||
const persistedIds = updateArg.data.dashboardWidgetsJson.widgets.map(
|
||||
@@ -372,11 +378,13 @@ describe("PUT /api/dashboard/widgets — accept-and-ignore unknown ids (v1.7.0 #
|
||||
// annotation fires regardless, before the Zod parse.
|
||||
expect(res.status).toBe(422);
|
||||
|
||||
const dropAnnotate = vi.mocked(annotate).mock.calls.find(
|
||||
(c) =>
|
||||
(c[0] as { action?: { name?: string } }).action?.name ===
|
||||
"dashboard.widgets.unknown-id-dropped",
|
||||
);
|
||||
const dropAnnotate = vi
|
||||
.mocked(annotate)
|
||||
.mock.calls.find(
|
||||
(c) =>
|
||||
(c[0] as { action?: { name?: string } }).action?.name ===
|
||||
"dashboard.widgets.unknown-id-dropped",
|
||||
);
|
||||
expect(dropAnnotate, "unknown-id-dropped annotate call").toBeTruthy();
|
||||
const meta = (dropAnnotate![0] as { meta?: Record<string, unknown> }).meta!;
|
||||
expect(meta.dropped_count).toBe(200);
|
||||
@@ -542,11 +550,13 @@ describe("dashboard widgets — 27-id catalogue round-trip (v1.7.0 W1)", () => {
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
// No id was dropped — the unknown-id annotation must NOT fire.
|
||||
const dropAnnotate = vi.mocked(annotate).mock.calls.find(
|
||||
(c) =>
|
||||
(c[0] as { action?: { name?: string } }).action?.name ===
|
||||
"dashboard.widgets.unknown-id-dropped",
|
||||
);
|
||||
const dropAnnotate = vi
|
||||
.mocked(annotate)
|
||||
.mock.calls.find(
|
||||
(c) =>
|
||||
(c[0] as { action?: { name?: string } }).action?.name ===
|
||||
"dashboard.widgets.unknown-id-dropped",
|
||||
);
|
||||
expect(dropAnnotate).toBeUndefined();
|
||||
|
||||
expect(prisma.user.update).toHaveBeenCalledTimes(1);
|
||||
@@ -557,7 +567,9 @@ describe("dashboard widgets — 27-id catalogue round-trip (v1.7.0 W1)", () => {
|
||||
const persistedIds = updateArg.data.dashboardWidgetsJson.widgets.map(
|
||||
(w) => w.id,
|
||||
);
|
||||
expect(persistedIds.sort()).toEqual([...DASHBOARD_WIDGET_CATALOGUE_IDS].sort());
|
||||
expect(persistedIds.sort()).toEqual(
|
||||
[...DASHBOARD_WIDGET_CATALOGUE_IDS].sort(),
|
||||
);
|
||||
// The response body echoes the full persisted layout.
|
||||
const body = (await res.json()) as {
|
||||
data: { widgets: Array<{ id: string }> };
|
||||
|
||||
@@ -271,7 +271,10 @@ export const PUT = apiHandler(async (request: NextRequest) => {
|
||||
let mergedChartOverlayPrefs: ChartOverlayPrefsMap | undefined = parsed.data
|
||||
.chartOverlayPrefs as ChartOverlayPrefsMap | undefined;
|
||||
let mergedHeroVisible: boolean | undefined = parsed.data.heroVisible;
|
||||
if (mergedChartOverlayPrefs === undefined || mergedHeroVisible === undefined) {
|
||||
if (
|
||||
mergedChartOverlayPrefs === undefined ||
|
||||
mergedHeroVisible === undefined
|
||||
) {
|
||||
const existing = await prisma.user.findUnique({
|
||||
where: { id: user.id },
|
||||
select: { dashboardWidgetsJson: true },
|
||||
|
||||
Reference in new issue
Block a user