chore(format): prettier sweep across develop

Mostly table column normalisation under docs/audit/ + planning, object-
literal expansion in src/lib/ai/coach/snapshot.ts after the W4 F6 Apple
Health metric block landed, and small wrap/unwrap line adjustments in
the device + APNs routes / tests touched across W3/W4/W5 sessions.
No behavioural change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-11 08:27:51 +02:00
1 parent 5dcd3954a0
commit f1e6630958
70 files changed
+899 -660

No files matched your search

@@ -60,22 +60,30 @@ function req(): NextRequest {
beforeEach(() => {
vi.resetAllMocks();
vi.mocked(prisma.refreshToken.findMany).mockResolvedValue([]);
vi.mocked(prisma.refreshToken.updateMany).mockResolvedValue({ count: 0 } as never);
vi.mocked(prisma.apiToken.updateMany).mockResolvedValue({ count: 0 } as never);
vi.mocked(prisma.refreshToken.updateMany).mockResolvedValue({
count: 0,
} as never);
vi.mocked(prisma.apiToken.updateMany).mockResolvedValue({
count: 0,
} as never);
vi.mocked(prisma.$transaction).mockResolvedValue([] as never);
});
describe("DELETE /api/auth/me/devices/[id]", () => {
it("returns 401 when unauthenticated", async () => {
vi.mocked(getSession).mockResolvedValue(null);
const res = await DELETE(req(), { params: Promise.resolve({ id: "dev-1" }) });
const res = await DELETE(req(), {
params: Promise.resolve({ id: "dev-1" }),
});
expect(res.status).toBe(401);
});
it("returns 404 when the device doesn't exist", async () => {
vi.mocked(getSession).mockResolvedValue(SESSION_OK as never);
vi.mocked(prisma.device.findUnique).mockResolvedValue(null);
const res = await DELETE(req(), { params: Promise.resolve({ id: "dev-x" }) });
const res = await DELETE(req(), {
params: Promise.resolve({ id: "dev-x" }),
});
expect(res.status).toBe(404);
});
@@ -87,7 +95,9 @@ describe("DELETE /api/auth/me/devices/[id]", () => {
model: "iPhone",
bundleId: "io.healthlog.app",
} as never);
const res = await DELETE(req(), { params: Promise.resolve({ id: "dev-x" }) });
const res = await DELETE(req(), {
params: Promise.resolve({ id: "dev-x" }),
});
expect(res.status).toBe(404);
expect(vi.mocked(prisma.device.delete)).not.toHaveBeenCalled();
});
@@ -105,11 +115,17 @@ describe("DELETE /api/auth/me/devices/[id]", () => {
{ accessTokenHash: "hash:a2" },
{ accessTokenHash: null },
] as never);
vi.mocked(prisma.refreshToken.updateMany).mockResolvedValue({ count: 3 } as never);
vi.mocked(prisma.apiToken.updateMany).mockResolvedValue({ count: 2 } as never);
vi.mocked(prisma.refreshToken.updateMany).mockResolvedValue({
count: 3,
} as never);
vi.mocked(prisma.apiToken.updateMany).mockResolvedValue({
count: 2,
} as never);
vi.mocked(prisma.device.delete).mockResolvedValue({ id: "dev-1" } as never);
const res = await DELETE(req(), { params: Promise.resolve({ id: "dev-1" }) });
const res = await DELETE(req(), {
params: Promise.resolve({ id: "dev-1" }),
});
expect(res.status).toBe(200);
const body = await res.json();
expect(body.data.revoked).toBe(true);
@@ -120,7 +136,8 @@ describe("DELETE /api/auth/me/devices/[id]", () => {
});
// The refresh-token revoke filter MUST scope to the deviceId, not
// every refresh row the user has.
const updateCall = vi.mocked(prisma.refreshToken.updateMany).mock.calls[0]?.[0];
const updateCall = vi.mocked(prisma.refreshToken.updateMany).mock
.calls[0]?.[0];
expect(updateCall?.where).toMatchObject({
userId: "user-1",
deviceId: "dev-1",
+5 -1
View File
@@ -55,7 +55,11 @@ export const DELETE = apiHandler(
},
});
annotate({
action: { name: "auth.me.devices.revoke", entity_type: "device", entity_id: result.id },
action: {
name: "auth.me.devices.revoke",
entity_type: "device",
entity_id: result.id,
},
meta: {
refresh_tokens_revoked: result.refreshTokensRevoked,
access_tokens_revoked: result.accessTokensRevoked,
@@ -60,15 +60,21 @@ function req(): NextRequest {
beforeEach(() => {
vi.resetAllMocks();
vi.mocked(prisma.refreshToken.findMany).mockResolvedValue([]);
vi.mocked(prisma.refreshToken.updateMany).mockResolvedValue({ count: 0 } as never);
vi.mocked(prisma.apiToken.updateMany).mockResolvedValue({ count: 0 } as never);
vi.mocked(prisma.refreshToken.updateMany).mockResolvedValue({
count: 0,
} as never);
vi.mocked(prisma.apiToken.updateMany).mockResolvedValue({
count: 0,
} as never);
vi.mocked(prisma.$transaction).mockResolvedValue([] as never);
});
describe("DELETE /api/devices/[id] (iOS token-rotation endpoint)", () => {
it("returns 401 when unauthenticated", async () => {
vi.mocked(getSession).mockResolvedValue(null);
const res = await DELETE(req(), { params: Promise.resolve({ id: "dev-1" }) });
const res = await DELETE(req(), {
params: Promise.resolve({ id: "dev-1" }),
});
expect(res.status).toBe(401);
});
@@ -80,7 +86,9 @@ describe("DELETE /api/devices/[id] (iOS token-rotation endpoint)", () => {
model: "iPhone",
bundleId: "io.healthlog.app",
} as never);
const res = await DELETE(req(), { params: Promise.resolve({ id: "dev-x" }) });
const res = await DELETE(req(), {
params: Promise.resolve({ id: "dev-x" }),
});
expect(res.status).toBe(404);
});
@@ -97,7 +105,9 @@ describe("DELETE /api/devices/[id] (iOS token-rotation endpoint)", () => {
] as never);
vi.mocked(prisma.device.delete).mockResolvedValue({ id: "dev-1" } as never);
const res = await DELETE(req(), { params: Promise.resolve({ id: "dev-1" }) });
const res = await DELETE(req(), {
params: Promise.resolve({ id: "dev-1" }),
});
expect(res.status).toBe(200);
expect(vi.mocked(prisma.device.delete)).toHaveBeenCalled();
});
+5 -1
View File
@@ -46,7 +46,11 @@ export const DELETE = apiHandler(
},
});
annotate({
action: { name: "devices.revoke", entity_type: "device", entity_id: result.id },
action: {
name: "devices.revoke",
entity_type: "device",
entity_id: result.id,
},
meta: {
refresh_tokens_revoked: result.refreshTokensRevoked,
access_tokens_revoked: result.accessTokensRevoked,
+1 -4
View File
@@ -114,10 +114,7 @@ export const POST = apiHandler(async (request: NextRequest) => {
deviceId: existingApns.id,
},
});
return apiError(
"APNs token already registered to another account",
409,
);
return apiError("APNs token already registered to another account", 409);
}
}
+9 -6
View File
@@ -25,7 +25,12 @@ import { prisma } from "@/lib/db";
import { apiHandler, requireAuth } from "@/lib/api-handler";
import { annotate } from "@/lib/logging/context";
import { auditLog } from "@/lib/auth/audit";
import { apiError, apiSuccess, getClientIp, safeJson } from "@/lib/api-response";
import {
apiError,
apiSuccess,
getClientIp,
safeJson,
} from "@/lib/api-response";
import { withIdempotency } from "@/lib/idempotency";
import { mapAppleHealthEntry } from "@/lib/measurements/apple-health-mapping";
import { validateMeasurementRange } from "@/lib/validations/measurement";
@@ -84,11 +89,9 @@ async function postBatch(request: NextRequest): Promise<Response> {
Array.isArray((rawBody as { entries: unknown }).entries) &&
(rawBody as { entries: unknown[] }).entries.length > MAX_BATCH_ENTRIES
) {
return apiError(
`Batch exceeds the ${MAX_BATCH_ENTRIES}-entry limit`,
422,
{ errorCode: "coach.batch.too_large" },
);
return apiError(`Batch exceeds the ${MAX_BATCH_ENTRIES}-entry limit`, 422, {
errorCode: "coach.batch.too_large",
});
}
const parsed = batchPayloadSchema.safeParse(rawBody);